File: /usr/src/linux/drivers/message/fusion/mptbase.c

1     /*
2      *  linux/drivers/message/fusion/mptbase.c
3      *      High performance SCSI + LAN / Fibre Channel device drivers.
4      *      This is the Fusion MPT base driver which supports multiple
5      *      (SCSI + LAN) specialized protocol drivers.
6      *      For use with PCI chip/adapter(s):
7      *          LSIFC9xx/LSI409xx Fibre Channel
8      *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
9      *
10      *  Credits:
11      *      There are lots of people not mentioned below that deserve credit
12      *      and thanks but won't get it here - sorry in advance that you
13      *      got overlooked.
14      *
15      *      This driver would not exist if not for Alan Cox's development
16      *      of the linux i2o driver.
17      *
18      *      A special thanks to Noah Romer (LSI Logic) for tons of work
19      *      and tough debugging on the LAN driver, especially early on;-)
20      *      And to Roger Hickerson (LSI Logic) for tirelessly supporting
21      *      this driver project.
22      *
23      *      All manner of help from Stephen Shirron (LSI Logic):
24      *      low-level FC analysis, debug + various fixes in FCxx firmware,
25      *      initial port to alpha platform, various driver code optimizations,
26      *      being a faithful sounding board on all sorts of issues & ideas,
27      *      etc.
28      *
29      *      A huge debt of gratitude is owed to David S. Miller (DaveM)
30      *      for fixing much of the stupid and broken stuff in the early
31      *      driver while porting to sparc64 platform.  THANK YOU!
32      *
33      *      Special thanks goes to the I2O LAN driver people at the
34      *      University of Helsinki, who, unbeknownst to them, provided
35      *      the inspiration and initial structure for this driver.
36      *
37      *      A really huge debt of gratitude is owed to Eddie C. Dost
38      *      for gobs of hard work fixing and optimizing LAN code.
39      *      THANK YOU!
40      *
41      *  Copyright (c) 1999-2001 LSI Logic Corporation
42      *  Originally By: Steven J. Ralston
43      *  (mailto:Steve.Ralston@lsil.com)
44      *
45      *  $Id: mptbase.c,v 1.53.4.1 2001/08/24 20:07:05 sralston Exp $
46      */
47     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
48     /*
49         This program is free software; you can redistribute it and/or modify
50         it under the terms of the GNU General Public License as published by
51         the Free Software Foundation; version 2 of the License.
52     
53         This program is distributed in the hope that it will be useful,
54         but WITHOUT ANY WARRANTY; without even the implied warranty of
55         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
56         GNU General Public License for more details.
57     
58         NO WARRANTY
59         THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
60         CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
61         LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
62         MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
63         solely responsible for determining the appropriateness of using and
64         distributing the Program and assumes all risks associated with its
65         exercise of rights under this Agreement, including but not limited to
66         the risks and costs of program errors, damage to or loss of data,
67         programs or equipment, and unavailability or interruption of operations.
68     
69         DISCLAIMER OF LIABILITY
70         NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
71         DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
72         DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
73         ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
74         TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
75         USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
76         HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
77     
78         You should have received a copy of the GNU General Public License
79         along with this program; if not, write to the Free Software
80         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
81     */
82     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
83     
84     #include <linux/config.h>
85     #include <linux/version.h>
86     #include <linux/kernel.h>
87     #include <linux/module.h>
88     #include <linux/errno.h>
89     #include <linux/init.h>
90     #include <linux/slab.h>
91     #include <linux/types.h>
92     #include <linux/pci.h>
93     #include <linux/kdev_t.h>
94     #include <linux/blkdev.h>
95     #include <linux/delay.h>
96     #include <linux/proc_fs.h>
97     #include <asm/io.h>
98     #ifdef CONFIG_MTRR
99     #include <asm/mtrr.h>
100     #endif
101     
102     #include "mptbase.h"
103     
104     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
105     #define my_NAME		"Fusion MPT base driver"
106     #define my_VERSION	MPT_LINUX_VERSION_COMMON
107     #define MYNAM		"mptbase"
108     
109     MODULE_AUTHOR(MODULEAUTHOR);
110     MODULE_DESCRIPTION(my_NAME);
111     
112     /*
113      *  cmd line parameters
114      */
115     MODULE_PARM(PortIo, "0-1i");
116     MODULE_PARM_DESC(PortIo, "[0]=Use mmap, 1=Use port io");
117     MODULE_PARM(HardReset, "0-1i");
118     MODULE_PARM_DESC(HardReset, "0=Disable HardReset, [1]=Enable HardReset");
119     static int PortIo = 0;
120     static int HardReset = 1;
121     
122     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
123     /*
124      *  Public data...
125      */
126     int mpt_lan_index = 0;
127     int mpt_stm_index = 0;
128     
129     void *mpt_v_ASCQ_TablePtr = NULL;
130     const char **mpt_ScsiOpcodesPtr = NULL;
131     int mpt_ASCQ_TableSz = 0;
132     
133     #define WHOINIT_UNKNOWN		0xAA
134     
135     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
136     /*
137      *  Private data...
138      */
139     					/* Adapter lookup table */
140     static MPT_ADAPTER		*mpt_adapters[MPT_MAX_ADAPTERS] = {0};
141     static MPT_ADAPTER_TRACKER	 MptAdapters;
142     					/* Callback lookup table */
143     static MPT_CALLBACK		 MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
144     					/* Protocol driver class lookup table */
145     static int	 		 MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
146     					/* Event handler lookup table */
147     static MPT_EVHANDLER		 MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
148     					/* Reset handler lookup table */
149     static MPT_RESETHANDLER		 MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
150     
151     static int	FusionInitCalled = 0;
152     static int	mpt_base_index = -1;
153     
154     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
155     /*
156      *  Forward protos...
157      */
158     static void	mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
159     static int	mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
160     
161     static int 	mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason);
162     static int 	mpt_adapter_install(struct pci_dev *pdev);
163     static void	mpt_detect_929_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);
164     static void	mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup);
165     static void	mpt_adapter_dispose(MPT_ADAPTER *ioc);
166     
167     static void	MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
168     static int	MakeIocReady(MPT_ADAPTER *ioc, int force);
169     static u32	GetIocState(MPT_ADAPTER *ioc, int cooked);
170     static int	GetIocFacts(MPT_ADAPTER *ioc);
171     static int	GetPortFacts(MPT_ADAPTER *ioc, int portnum);
172     static int	SendIocInit(MPT_ADAPTER *ioc);
173     static int	SendPortEnable(MPT_ADAPTER *ioc, int portnum);
174     static int	mpt_fc9x9_reset(MPT_ADAPTER *ioc, int ignore);
175     static int	KickStart(MPT_ADAPTER *ioc, int ignore);
176     static int	SendIocReset(MPT_ADAPTER *ioc, u8 reset_type);
177     static int	PrimeIocFifos(MPT_ADAPTER *ioc);
178     static int	HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait);
179     static int	WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong);
180     static int	WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong);
181     static int	WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong);
182     static int	GetLanConfigPages(MPT_ADAPTER *ioc);
183     static int	SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
184     static int	SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
185     
186     static int	procmpt_create(void);
187     #ifdef CONFIG_PROC_FS
188     static int	procmpt_destroy(void);
189     #endif
190     static int	procmpt_read_summary(char *page, char **start, off_t off, int count, int *eof, void *data);
191     static int	procmpt_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data);
192     /*static int	procmpt_info(char *buf, char **start, off_t offset, int len);*/
193     
194     static int	ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
195     static void	mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
196     static void	mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
197     
198     static struct proc_dir_entry	*procmpt_root_dir = NULL;
199     
200     int		fusion_init(void);
201     static void	fusion_exit(void);
202     
203     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
204     /* 20000207 -sralston
205      *  GRRRRR...  IOSpace (port i/o) register access (for the 909) is back!
206      * 20000517 -sralston
207      *  Let's trying going back to default mmap register access...
208      */
209     
210     static inline u32 CHIPREG_READ32(volatile u32 *a)
211     {
212     	if (PortIo)
213     		return inl((unsigned long)a);
214     	else
215     		return readl(a);
216     }
217     
218     static inline void CHIPREG_WRITE32(volatile u32 *a, u32 v)
219     {
220     	if (PortIo)
221     		outl(v, (unsigned long)a);
222     	else
223     		writel(v, a);
224     }
225     
226     
227     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
228     /**
229      *	mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
230      *	@irq: irq number (not used)
231      *	@bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
232      *	@r: pt_regs pointer (not used)
233      *
234      *	This routine is registered via the request_irq() kernel API call,
235      *	and handles all interrupts generated from a specific MPT adapter
236      *	(also referred to as a IO Controller or IOC).
237      *	This routine must clear the interrupt from the adapter and does
238      *	so by reading the reply FIFO.  Multiple replies may be processed
239      *	per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
240      *	which is currently set to 32 in mptbase.h.
241      *
242      *	This routine handles register-level access of the adapter but
243      *	dispatches (calls) a protocol-specific callback routine to handle
244      *	the protocol-specific details of the MPT request completion.
245      */
246     static void
247     mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
248     {
249     	MPT_ADAPTER	*ioc;
250     	MPT_FRAME_HDR	*mf;
251     	MPT_FRAME_HDR	*mr;
252     	u32		 pa;
253     	u32		*m;
254     	int		 req_idx;
255     	int		 cb_idx;
256     	int		 type;
257     	int		 freeme;
258     	int		 count = 0;
259     
260     	ioc = bus_id;
261     
262     	/*
263     	 *  Drain the reply FIFO!
264     	 *
265     	 * NOTES: I've seen up to 10 replies processed in this loop, so far...
266     	 * Update: I've seen up to 9182 replies processed in this loop! ??
267     	 * Update: Limit ourselves to processing max of N replies
268     	 *	(bottom of loop).
269     	 */
270     	while (1) {
271     
272     		if ((pa = CHIPREG_READ32(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)
273     			return;
274     
275     		cb_idx = 0;
276     		freeme = 0;
277     
278     		/*
279     		 *  Check for non-TURBO reply!
280     		 */
281     		if (pa & MPI_ADDRESS_REPLY_A_BIT) {
282     			dma_addr_t reply_dma_addr;
283     			u16 ioc_stat;
284     
285     			/* non-TURBO reply!  Hmmm, something may be up...
286     			 *  Newest turbo reply mechanism; get address
287     			 *  via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
288     			 */
289     			reply_dma_addr = (pa = (pa << 1));
290     
291     			/* Map DMA address of reply header to cpu address. */
292     			m = (u32 *) ((u8 *)ioc->reply_frames +
293     					(reply_dma_addr - ioc->reply_frames_dma));
294     
295     			mr = (MPT_FRAME_HDR *) m;
296     			req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
297     			cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
298     			mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
299     
300     			dprintk((KERN_INFO MYNAM ": %s: Got non-TURBO reply=%p\n",
301     					ioc->name, mr));
302     			DBG_DUMP_REPLY_FRAME(mr)
303     
304     			/* NEW!  20010301 -sralston
305     			 *  Check/log IOC log info
306     			 */
307     			ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
308     	 		if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
309     				u32	 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
310     				if ((int)ioc->chip_type <= (int)FC929)
311     					mpt_fc_log_info(ioc, log_info);
312     				else
313     					mpt_sp_log_info(ioc, log_info);
314     			}
315     		} else {
316     			/*
317     			 *  Process turbo (context) reply...
318     			 */
319     			dirqprintk((KERN_INFO MYNAM ": %s: Got TURBO reply(=%08x)\n", ioc->name, pa));
320     			type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
321     			if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
322     				cb_idx = mpt_stm_index;
323     				mf = NULL;
324     				mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
325     			} else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
326     				cb_idx = mpt_lan_index;
327     				/*
328     				 * BUG FIX!  20001218 -sralston
329     				 *  Blind set of mf to NULL here was fatal
330     				 *  after lan_reply says "freeme"
331     				 *  Fix sort of combined with an optimization here;
332     				 *  added explicit check for case where lan_reply
333     				 *  was just returning 1 and doing nothing else.
334     				 *  For this case skip the callback, but set up
335     				 *  proper mf value first here:-)
336     				 */
337     				if ((pa & 0x58000000) == 0x58000000) {
338     					req_idx = pa & 0x0000FFFF;
339     					mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
340     					freeme = 1;
341     					/*
342     					 *  IMPORTANT!  Invalidate the callback!
343     					 */
344     					cb_idx = 0;
345     				} else {
346     					mf = NULL;
347     				}
348     				mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
349     			} else {
350     				req_idx = pa & 0x0000FFFF;
351     				cb_idx = (pa & 0x00FF0000) >> 16;
352     				mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
353     				mr = NULL;
354     			}
355     			pa = 0;					/* No reply flush! */
356     		}
357     
358     		/*  Check for (valid) IO callback!  */
359     		if (cb_idx) {
360     			/*  Do the callback!  */
361     			freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);
362     		}
363     
364     		if (pa) {
365     			/*  Flush (non-TURBO) reply with a WRITE!  */
366     			CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
367     		}
368     
369     		if (freeme) {
370     			unsigned long flags;
371     
372     			/*  Put Request back on FreeQ!  */
373     			spin_lock_irqsave(&ioc->FreeQlock, flags);
374     			Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
375     			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
376     		}
377     
378     		count++;
379     		dirqprintk((KERN_INFO MYNAM ": %s: ISR processed frame #%d\n", ioc->name, count));
380     		mb();
381     
382     		if (count >= MPT_MAX_REPLIES_PER_ISR) {
383     			dirqprintk((KERN_INFO MYNAM ": %s: ISR processed %d replies.",
384     					ioc->name, count));
385     			dirqprintk((" Giving this ISR a break!\n"));
386     			return;
387     		}
388     
389     	}	/* drain reply FIFO */
390     }
391     
392     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
393     /*
394      *	mpt_base_reply - MPT base driver's callback routine; all base driver
395      *	"internal" request/reply processing is routed here.
396      *	Currently used for EventNotification and EventAck handling.
397      *	@ioc: Pointer to MPT_ADAPTER structure
398      *	@mf: Pointer to original MPT request frame
399      *	@reply: Pointer to MPT reply frame (NULL if TurboReply)
400      *
401      *	Returns 1 indicating original alloc'd request frame ptr
402      *	should be freed, or 0 if it shouldn't.
403      */
404     static int
405     mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
406     {
407     	int freereq = 1;
408     	u8 func;
409     
410     	dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply() called\n", ioc->name));
411     
412     	if ((mf == NULL) ||
413     	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
414     		printk(KERN_ERR MYNAM ": %s: ERROR - NULL or BAD request frame ptr! (=%p)\n",
415     				ioc->name, mf);
416     		return 1;
417     	}
418     
419     	if (reply == NULL) {
420     		dprintk((KERN_ERR MYNAM ": %s: ERROR - Unexpected NULL Event (turbo?) reply!\n",
421     				ioc->name));
422     		return 1;
423     	}
424     
425     	if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
426     		dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
427     		DBG_DUMP_REQUEST_FRAME_HDR(mf)
428     	}
429     
430     	func = reply->u.hdr.Function;
431     	dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply, Function=%02Xh\n",
432     			ioc->name, func));
433     
434     	if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
435     		EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
436     		int evHandlers = 0;
437     		int results;
438     
439     		results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
440     		if (results != evHandlers) {
441     			/* CHECKME! Any special handling needed here? */
442     			dprintk((KERN_WARNING MYNAM ": %s: Hmmm... Called %d event handlers, sum results = %d\n",
443     					ioc->name, evHandlers, results));
444     		}
445     
446     		/*
447     		 *  Hmmm...  It seems that EventNotificationReply is an exception
448     		 *  to the rule of one reply per request.
449     		 */
450     		if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
451     			freereq = 0;
452     #ifdef CONFIG_PROC_FS
453     //		LogEvent(ioc, pEvReply);
454     #endif
455     	} else if (func == MPI_FUNCTION_EVENT_ACK) {
456     		dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply, EventAck reply received\n",
457     				ioc->name));
458     	} else {
459     		printk(KERN_ERR MYNAM ": %s: ERROR - Unexpected msg function (=%02Xh) reply received!\n",
460     				ioc->name, func);
461     	}
462     
463     	/*
464     	 *  Conditionally tell caller to free the original
465     	 *  EventNotification/EventAck/unexpected request frame!
466     	 */
467     	return freereq;
468     }
469     
470     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
471     /**
472      *	mpt_register - Register protocol-specific main callback handler.
473      *	@cbfunc: callback function pointer
474      *	@dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
475      *
476      *	This routine is called by a protocol-specific driver (SCSI host,
477      *	LAN, SCSI target) to register it's reply callback routine.  Each
478      *	protocol-specific driver must do this before it will be able to
479      *	use any IOC resources, such as obtaining request frames.
480      *
481      *	NOTES: The SCSI protocol driver currently calls this routine twice
482      *	in order to register separate callbacks; one for "normal" SCSI IO
483      *	and another for MptScsiTaskMgmt requests.
484      *
485      *	Returns a positive integer valued "handle" in the
486      *	range (and S.O.D. order) {7,6,...,1} if successful.
487      *	Any non-positive return value (including zero!) should be considered
488      *	an error by the caller.
489      */
490     int
491     mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
492     {
493     	int r = -1;
494     	int i;
495     
496     #ifndef MODULE
497     	/*
498     	 *  Handle possibility of the mptscsih_detect() routine getting
499     	 *  called *before* fusion_init!
500     	 */
501     	if (!FusionInitCalled) {
502     		dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n"));
503     		/*
504     		 *  NOTE! We'll get recursion here, as fusion_init()
505     		 *  calls mpt_register()!
506     		 */
507     		fusion_init();
508     		FusionInitCalled++;
509     	}
510     #endif
511     
512     	/*
513     	 *  Search for empty callback slot in this order: {7,6,...,1}
514     	 *  (slot/handle 0 is reserved!)
515     	 */
516     	for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
517     		if (MptCallbacks[i] == NULL) {
518     			MptCallbacks[i] = cbfunc;
519     			MptDriverClass[i] = dclass;
520     			MptEvHandlers[i] = NULL;
521     			r = i;
522     			if (cbfunc != mpt_base_reply) {
523     				MOD_INC_USE_COUNT;
524     			}
525     			break;
526     		}
527     	}
528     
529     	return r;
530     }
531     
532     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
533     /**
534      *	mpt_deregister - Deregister a protocol drivers resources.
535      *	@cb_idx: previously registered callback handle
536      *
537      *	Each protocol-specific driver should call this routine when it's
538      *	module is unloaded.
539      */
540     void
541     mpt_deregister(int cb_idx)
542     {
543     	if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
544     		MptCallbacks[cb_idx] = NULL;
545     		MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
546     		MptEvHandlers[cb_idx] = NULL;
547     		if (cb_idx != mpt_base_index) {
548     			MOD_DEC_USE_COUNT;
549     		}
550     	}
551     }
552     
553     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
554     /**
555      *	mpt_event_register - Register protocol-specific event callback
556      *	handler.
557      *	@cb_idx: previously registered (via mpt_register) callback handle
558      *	@ev_cbfunc: callback function
559      *
560      *	This routine can be called by one or more protocol-specific drivers
561      *	if/when they choose to be notified of MPT events.
562      *
563      *	Returns 0 for success.
564      */
565     int
566     mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
567     {
568     	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
569     		return -1;
570     
571     	MptEvHandlers[cb_idx] = ev_cbfunc;
572     	return 0;
573     }
574     
575     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
576     /**
577      *	mpt_event_deregister - Deregister protocol-specific event callback
578      *	handler.
579      *	@cb_idx: previously registered callback handle
580      *
581      *	Each protocol-specific driver should call this routine
582      *	when it does not (or can no longer) handle events,
583      *	or when it's module is unloaded.
584      */
585     void
586     mpt_event_deregister(int cb_idx)
587     {
588     	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
589     		return;
590     
591     	MptEvHandlers[cb_idx] = NULL;
592     }
593     
594     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
595     /**
596      *	mpt_reset_register - Register protocol-specific IOC reset handler.
597      *	@cb_idx: previously registered (via mpt_register) callback handle
598      *	@reset_func: reset function
599      *
600      *	This routine can be called by one or more protocol-specific drivers
601      *	if/when they choose to be notified of IOC resets.
602      *
603      *	Returns 0 for success.
604      */
605     int
606     mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
607     {
608     	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
609     		return -1;
610     
611     	MptResetHandlers[cb_idx] = reset_func;
612     	return 0;
613     }
614     
615     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
616     /**
617      *	mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
618      *	@cb_idx: previously registered callback handle
619      *
620      *	Each protocol-specific driver should call this routine
621      *	when it does not (or can no longer) handle IOC reset handling,
622      *	or when it's module is unloaded.
623      */
624     void
625     mpt_reset_deregister(int cb_idx)
626     {
627     	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
628     		return;
629     
630     	MptResetHandlers[cb_idx] = NULL;
631     }
632     
633     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
634     /**
635      *	mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
636      *	allocated per MPT adapter.
637      *	@handle: Handle of registered MPT protocol driver
638      *	@iocid: IOC unique identifier (integer)
639      *
640      *	Returns pointer to a MPT request frame or %NULL if none are available.
641      */
642     MPT_FRAME_HDR*
643     mpt_get_msg_frame(int handle, int iocid)
644     {
645     	MPT_FRAME_HDR *mf = NULL;
646     	MPT_ADAPTER *iocp;
647     	unsigned long flags;
648     
649     	/* validate handle and ioc identifier */
650     	iocp = mpt_adapters[iocid];
651     	spin_lock_irqsave(&iocp->FreeQlock, flags);
652     	if (! Q_IS_EMPTY(&iocp->FreeQ)) {
653     		int req_offset;
654     
655     		mf = iocp->FreeQ.head;
656     		Q_DEL_ITEM(&mf->u.frame.linkage);
657     		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;	/* byte */
658     		req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
659     								/* u16! */
660     		mf->u.frame.hwhdr.msgctxu.fld.req_idx =
661     				cpu_to_le16(req_offset / iocp->req_sz);
662     		mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
663     	}
664     	spin_unlock_irqrestore(&iocp->FreeQlock, flags);
665     	dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
666     			iocp->name, handle, iocid, mf));
667     	return mf;
668     }
669     
670     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
671     /**
672      *	mpt_put_msg_frame - Send a protocol specific MPT request frame
673      *	to a IOC.
674      *	@handle: Handle of registered MPT protocol driver
675      *	@iocid: IOC unique identifier (integer)
676      *	@mf: Pointer to MPT request frame
677      *
678      *	This routine posts a MPT request frame to the request post FIFO of a
679      *	specific MPT adapter.
680      */
681     void
682     mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
683     {
684     	MPT_ADAPTER *iocp;
685     
686     	iocp = mpt_adapters[iocid];
687     	if (iocp != NULL) {
688     		dma_addr_t mf_dma_addr;
689     		int req_offset;
690     
691     		/* ensure values are reset properly! */
692     		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;		/* byte */
693     		req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
694     									/* u16! */
695     		mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz);
696     		mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
697     
698     #ifdef MPT_DEBUG_MSG_FRAME
699     		{
700     			u32	*m = mf->u.frame.hwhdr.__hdr;
701     			int	 i, n;
702     
703     			printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
704     					iocp->name, m);
705     			n = iocp->req_sz/4 - 1;
706     			while (m[n] == 0)
707     				n--;
708     			for (i=0; i<=n; i++) {
709     				if (i && ((i%8)==0))
710     					printk("\n" KERN_INFO " ");
711     				printk(" %08x", le32_to_cpu(m[i]));
712     			}
713     			printk("\n");
714     		}
715     #endif
716     
717     		mf_dma_addr = iocp->req_frames_dma + req_offset;
718     		CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);
719     	}
720     }
721     
722     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
723     /**
724      *	mpt_free_msg_frame - Place MPT request frame back on FreeQ.
725      *	@handle: Handle of registered MPT protocol driver
726      *	@iocid: IOC unique identifier (integer)
727      *	@mf: Pointer to MPT request frame
728      *
729      *	This routine places a MPT request frame back on the MPT adapter's
730      *	FreeQ.
731      */
732     void
733     mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
734     {
735     	MPT_ADAPTER *iocp;
736     	unsigned long flags;
737     
738     	iocp = mpt_adapters[iocid];
739     	if (iocp != NULL) {
740     		/*  Put Request back on FreeQ!  */
741     		spin_lock_irqsave(&iocp->FreeQlock, flags);
742     		Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
743     		spin_unlock_irqrestore(&iocp->FreeQlock, flags);
744     	}
745     }
746     
747     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
748     /**
749      *	mpt_send_handshake_request - Send MPT request via doorbell
750      *	handshake method.
751      *	@handle: Handle of registered MPT protocol driver
752      *	@iocid: IOC unique identifier (integer)
753      *	@reqBytes: Size of the request in bytes
754      *	@req: Pointer to MPT request frame
755      *
756      *	This routine is used exclusively by mptscsih to send MptScsiTaskMgmt
757      *	requests since they are required to be sent via doorbell handshake.
758      *
759      *	NOTE: It is the callers responsibility to byte-swap fields in the
760      *	request which are greater than 1 byte in size.
761      *
762      *	Returns 0 for success, non-zero for failure.
763      */
764     int
765     mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req)
766     {
767     	MPT_ADAPTER	*iocp;
768     	int		 r = 0;
769     
770     	iocp = mpt_adapters[iocid];
771     	if (iocp != NULL) {
772     		u8		*req_as_bytes;
773     		u32		 ioc_raw_state;
774     		int		 i;
775     
776     		/* YIKES!  We already know something is amiss.
777     		 * Do upfront check on IOC state.
778     		 */
779     		ioc_raw_state = GetIocState(iocp, 0);
780     		if ((ioc_raw_state & MPI_DOORBELL_ACTIVE) ||
781     		    ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL)) {
782     			printk(KERN_WARNING MYNAM ": %s: Bad IOC state (%08x) WARNING!\n",
783     					iocp->name, ioc_raw_state);
784     			if ((r = mpt_do_ioc_recovery(iocp, MPT_HOSTEVENT_IOC_RECOVER)) != 0) {
785     				printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
786     						r, iocp->name);
787     				return r;
788     			}
789     		}
790     
791     		/*
792     		 * Emulate what mpt_put_msg_frame() does /wrt to sanity
793     		 * setting cb_idx/req_idx.  But ONLY if this request
794     		 * is in proper (pre-alloc'd) request buffer range...
795     		 */
796     		i = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req);
797     		if (reqBytes >= 12 && i >= 0 && i < iocp->req_depth) {
798     			MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
799     			mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(i);
800     			mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
801     		}
802     
803     		/* Make sure there are no doorbells */
804     		CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
805     
806     		CHIPREG_WRITE32(&iocp->chip->Doorbell,
807     				((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
808     				 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
809     
810     		/* Wait for IOC doorbell int */
811     		if ((i = WaitForDoorbellInt(iocp, 2)) < 0) {
812     			return i;
813     		}
814     
815     		dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
816     				iocp->name, i));
817     
818     		CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
819     
820     		if ((r = WaitForDoorbellAck(iocp, 1)) < 0) {
821     			return -2;
822     		}
823     
824     		/* Send request via doorbell handshake */
825     		req_as_bytes = (u8 *) req;
826     		for (i = 0; i < reqBytes/4; i++) {
827     			u32 word;
828     
829     			word = ((req_as_bytes[(i*4) + 0] <<  0) |
830     				(req_as_bytes[(i*4) + 1] <<  8) |
831     				(req_as_bytes[(i*4) + 2] << 16) |
832     				(req_as_bytes[(i*4) + 3] << 24));
833     			CHIPREG_WRITE32(&iocp->chip->Doorbell, word);
834     			if ((r = WaitForDoorbellAck(iocp, 1)) < 0) {
835     				r = -3;
836     				break;
837     			}
838     		}
839     
840     		if ((r = WaitForDoorbellInt(iocp, 2)) >= 0)
841     			r = 0;
842     		else
843     			r = -4;
844     
845     		/* Make sure there are no doorbells */
846     		CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
847     	}
848     
849     	return r;
850     }
851     
852     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
853     /**
854      *	mpt_adapter_find_first - Find first MPT adapter pointer.
855      *
856      *	Returns first MPT adapter pointer or %NULL if no MPT adapters
857      *	are present.
858      */
859     MPT_ADAPTER *
860     mpt_adapter_find_first(void)
861     {
862     	MPT_ADAPTER *this = NULL;
863     
864     	if (! Q_IS_EMPTY(&MptAdapters))
865     		this = MptAdapters.head;
866     
867     	return this;
868     }
869     
870     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
871     /**
872      * 	mpt_adapter_find_next - Find next MPT adapter pointer.
873      * 	@prev: Pointer to previous MPT adapter
874      *
875      *	Returns next MPT adapter pointer or %NULL if there are no more.
876      */
877     MPT_ADAPTER *
878     mpt_adapter_find_next(MPT_ADAPTER *prev)
879     {
880     	MPT_ADAPTER *next = NULL;
881     
882     	if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head))
883     		next = prev->forw;
884     
885     	return next;
886     }
887     
888     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
889     /**
890      *	mpt_pci_scan - Scan PCI devices for MPT adapters.
891      *
892      *	Returns count of MPT adapters found, keying off of PCI vendor and
893      *	device_id's.
894      */
895     int __init
896     mpt_pci_scan(void)
897     {
898     	struct pci_dev *pdev;
899     	struct pci_dev *pdev2;
900     	int found = 0;
901     	int count = 0;
902     	int r;
903     
904     	dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n"));
905     
906     	/*
907     	 *  NOTE: The 929 (I believe) will appear as 2 separate PCI devices,
908     	 *  one for each channel.
909     	 */
910     	pci_for_each_dev(pdev) {
911     		pdev2 = NULL;
912     		if (pdev->vendor != 0x1000)
913     			continue;
914     
915     		if ((pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC909) &&
916     		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929) &&
917     		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919) &&
918     #if 0
919     		    /* FIXME! C103x family */
920     		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) &&
921     		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030_ZC) &&
922     		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1035) &&
923     #endif
924     		    1) {
925     			dprintk((KERN_INFO MYNAM ": Skipping LSI device=%04xh\n", pdev->device));
926     			continue;
927     		}
928     
929     		/* GRRRRR
930     		 * 929 dual function devices may be presented in Func 1,0 order,
931     		 * but we'd really really rather have them in Func 0,1 order.
932     		 * Do some kind of look ahead here...
933     		 */
934     		if (pdev->devfn & 1) {
935     			pdev2 = pci_peek_next_dev(pdev);
936     			if (pdev2 && (pdev2->vendor == 0x1000) &&
937     			    (PCI_SLOT(pdev2->devfn) == PCI_SLOT(pdev->devfn)) &&
938     			    (pdev2->device == MPI_MANUFACTPAGE_DEVICEID_FC929) &&
939     			    (pdev2->bus->number == pdev->bus->number) &&
940     			    !(pdev2->devfn & 1)) {
941     				dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n",
942     			 		pdev2->bus->number, pdev2->devfn, pdev2->class, pdev2->device));
943     				found++;
944     				if ((r = mpt_adapter_install(pdev2)) == 0)
945     					count++;
946     			} else {
947     				pdev2 = NULL;
948     			}
949     		}
950     
951     		dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n",
952     			 pdev->bus->number, pdev->devfn, pdev->class, pdev->device));
953     		found++;
954     		if ((r = mpt_adapter_install(pdev)) == 0)
955     			count++;
956     
957     		if (pdev2)
958     			pdev = pdev2;
959     	}
960     
961     	printk(KERN_INFO MYNAM ": %d MPT adapter%s found, %d installed.\n",
962     		 found, (found==1) ? "" : "s", count);
963     
964     	if (!found || !count) {
965     		fusion_exit();
966     		return -ENODEV;
967     	}
968     
969     #ifdef CONFIG_PROC_FS
970     	if (procmpt_create() != 0)
971     		printk(KERN_WARNING MYNAM ": WARNING! - %s creation failed!\n",
972     				MPT_PROCFS_MPTBASEDIR);
973     #endif
974     
975     	return count;
976     }
977     
978     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
979     /**
980      *	mpt_verify_adapter - Given a unique IOC identifier, set pointer to
981      *	the associated MPT adapter structure.
982      *	@iocid: IOC unique identifier (integer)
983      *	@iocpp: Pointer to pointer to IOC adapter
984      *
985      *	Returns iocid and sets iocpp.
986      */
987     int
988     mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
989     {
990     	MPT_ADAPTER *p;
991     
992     	*iocpp = NULL;
993     	if (iocid >= MPT_MAX_ADAPTERS)
994     		return -1;
995     
996     	p = mpt_adapters[iocid];
997     	if (p == NULL)
998     		return -1;
999     
1000     	*iocpp = p;
1001     	return iocid;
1002     }
1003     
1004     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1005     /**
1006      *	mpt_adapter_install - Install a PCI intelligent MPT adapter.
1007      *	@pdev: Pointer to pci_dev structure
1008      *
1009      *	This routine performs all the steps necessary to bring the IOC of
1010      *	a MPT adapter to a OPERATIONAL state.  This includes registering
1011      *	memory regions, registering the interrupt, and allocating request
1012      *	and reply memory pools.
1013      *
1014      *	This routine also pre-fetches the LAN MAC address of a Fibre Channel
1015      *	MPT adapter.
1016      *
1017      *	Returns 0 for success, non-zero for failure.
1018      *
1019      *	TODO: Add support for polled controllers
1020      */
1021     static int __init
1022     mpt_adapter_install(struct pci_dev *pdev)
1023     {
1024     	MPT_ADAPTER	*ioc;
1025     	char		*myname;
1026     	u8		*mem;
1027     	unsigned long	 mem_phys;
1028     	unsigned long	 port;
1029     	u32		 msize;
1030     	u32		 psize;
1031     	int		 i;
1032     	int		 r = -ENODEV;
1033     	int		 len;
1034     
1035     	ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_KERNEL);
1036     	if (ioc == NULL) {
1037     		printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1038     		return -ENOMEM;
1039     	}
1040     	memset(ioc, 0, sizeof(*ioc));
1041     	ioc->req_sz = MPT_REQ_SIZE;			/* avoid div by zero! */
1042     	ioc->alloc_total = sizeof(MPT_ADAPTER);
1043     
1044     	ioc->pcidev = pdev;
1045     
1046     	/* Find lookup slot. */
1047     	for (i=0; i < MPT_MAX_ADAPTERS; i++) {
1048     		if (mpt_adapters[i] == NULL) {
1049     			ioc->id = i;		/* Assign adapter unique id (lookup) */
1050     			break;
1051     		}
1052     	}
1053     	if (i == MPT_MAX_ADAPTERS) {
1054     		printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", i);
1055     		kfree(ioc);
1056     		return -ENFILE;
1057     	}
1058     
1059     	mem_phys = msize = 0;
1060     	port = psize = 0;
1061     	for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {
1062     		if (pdev->PCI_BASEADDR_FLAGS(i) & PCI_BASE_ADDRESS_SPACE_IO) {
1063     			/* Get I/O space! */
1064     			port = pdev->PCI_BASEADDR_START(i);
1065     			psize = PCI_BASEADDR_SIZE(pdev,i);
1066     		} else {
1067     			/* Get memmap */
1068     			mem_phys = pdev->PCI_BASEADDR_START(i);
1069     			msize = PCI_BASEADDR_SIZE(pdev,i);
1070     			break;
1071     		}
1072     	}
1073     	ioc->mem_size = msize;
1074     
1075     	if (i == DEVICE_COUNT_RESOURCE) {
1076     		printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1077     		kfree(ioc);
1078     		return -EINVAL;
1079     	}
1080     
1081     	dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1082     	dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1083     	dprintk((KERN_INFO MYNAM ": Using %s register access method\n", PortIo ? "PortIo" : "MemMap"));
1084     
1085     	mem = NULL;
1086     	if (! PortIo) {
1087     		/* Get logical ptr for PciMem0 space */
1088     		/*mem = ioremap(mem_phys, msize);*/
1089     		mem = ioremap(mem_phys, 0x100);
1090     		if (mem == NULL) {
1091     			printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1092     			kfree(ioc);
1093     			return -EINVAL;
1094     		}
1095     		ioc->memmap = mem;
1096     	}
1097     	dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1098     
1099     	if (PortIo) {
1100     		u8 *pmem = (u8*)port;
1101     		ioc->mem_phys = port;
1102     		ioc->chip = (SYSIF_REGS*)pmem;
1103     	} else {
1104     		ioc->mem_phys = mem_phys;
1105     		ioc->chip = (SYSIF_REGS*)mem;
1106     	}
1107     
1108     	ioc->chip_type = FCUNK;
1109     	if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1110     		ioc->chip_type = FC909;
1111     		ioc->prod_name = "LSIFC909";
1112     	}
1113     	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1114     		ioc->chip_type = FC929;
1115     		ioc->prod_name = "LSIFC929";
1116     	}
1117     	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1118     		ioc->chip_type = FC919;
1119     		ioc->prod_name = "LSIFC919";
1120     	}
1121     #if 0
1122     	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_53C1030) {
1123     		ioc->chip_type = C1030;
1124     		ioc->prod_name = "LSI53C1030";
1125     	}
1126     #endif
1127     
1128     	myname = "iocN";
1129     	len = strlen(myname);
1130     	memcpy(ioc->name, myname, len+1);
1131     	ioc->name[len-1] = '0' + ioc->id;
1132     
1133     	Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
1134     	spin_lock_init(&ioc->FreeQlock);
1135     
1136     	/* Disable all! */
1137     	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1138     	ioc->active = 0;
1139     	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1140     
1141     	ioc->pci_irq = -1;
1142     	if (pdev->irq) {
1143     		r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1144     
1145     		if (r < 0) {
1146     			printk(KERN_ERR MYNAM ": %s: ERROR - Unable to allocate interrupt %d!\n",
1147     					ioc->name, pdev->irq);
1148     			iounmap(mem);
1149     			kfree(ioc);
1150     			return -EBUSY;
1151     		}
1152     
1153     		ioc->pci_irq = pdev->irq;
1154     
1155     		pci_set_master(pdev);			/* ?? */
1156     
1157     		dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
1158     	}
1159     
1160     	/* tack onto tail of our MPT adapter list */
1161     	Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER);
1162     
1163     	/* Set lookup ptr. */
1164     	mpt_adapters[ioc->id] = ioc;
1165     
1166     	/* NEW!  20010220 -sralston
1167     	 * Check for "929 bound ports" to reduce redundant resets.
1168     	 */
1169     	if (ioc->chip_type == FC929)
1170     		mpt_detect_929_bound_ports(ioc, pdev);
1171     
1172     	if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) {
1173     		printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n",
1174     				ioc->name, r);
1175     	}
1176     
1177     	return r;
1178     }
1179     
1180     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1181     /**
1182      *	mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1183      *	@ioc: Pointer to MPT adapter structure
1184      *	@reason: Event word / reason
1185      *
1186      *	This routine performs all the steps necessary to bring the IOC
1187      *	to a OPERATIONAL state.
1188      *
1189      *	This routine also pre-fetches the LAN MAC address of a Fibre Channel
1190      *	MPT adapter.
1191      *
1192      *	Returns 0 for success.
1193      */
1194     static int
1195     mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason)
1196     {
1197     	int	 hard_reset_done = 0;
1198     	int	 alt_ioc_ready = 0;
1199     	int	 hard;
1200     	int	 r;
1201     	int	 i;
1202     	int	 handlers;
1203     
1204     	printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1205     			ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1206     
1207     	/* Disable reply interrupts */
1208     	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1209     	ioc->active = 0;
1210     	/* NOTE: Access to IOC's request FreeQ is now blocked! */
1211     
1212     // FIXME? Cleanup all IOC requests here! (or below?)
1213     // But watch out for event associated request?
1214     
1215     	hard = HardReset;
1216     	if (ioc->alt_ioc && (reason == MPT_HOSTEVENT_IOC_BRINGUP))
1217     		hard = 0;
1218     
1219     	if ((hard_reset_done = MakeIocReady(ioc, hard)) < 0) {
1220     		printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1221     				ioc->name);
1222     		return -1;
1223     	}
1224     
1225     // NEW!
1226     #if 0						// Kiss-of-death!?!
1227     	if (ioc->alt_ioc) {
1228     // Grrr... Hold off any alt-IOC interrupts (and events) while
1229     // handshaking to <this> IOC, needed because?
1230     		/* Disable alt-IOC's reply interrupts for a bit ... */
1231     		alt_ioc_intmask = CHIPREG_READ32(&ioc->alt_ioc->chip->IntMask);
1232     		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1233     		ioc->alt_ioc->active = 0;
1234     		/* NOTE: Access to alt-IOC's request FreeQ is now blocked! */
1235     	}
1236     #endif
1237     
1238     	if (hard_reset_done && ioc->alt_ioc) {
1239     		if ((r = MakeIocReady(ioc->alt_ioc, 0)) == 0)
1240     			alt_ioc_ready = 1;
1241     		else
1242     			printk(KERN_WARNING MYNAM ": alt-%s: (%d) Not ready WARNING!\n",
1243     					ioc->alt_ioc->name, r);
1244     	}
1245     
1246     	if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1247     		/* Get IOC facts! */
1248     		if ((r = GetIocFacts(ioc)) != 0)
1249     			return -2;
1250     		MptDisplayIocCapabilities(ioc);
1251     	}
1252     
1253     	/*
1254     	 * Call each currently registered protocol IOC reset handler
1255     	 * with pre-reset indication.
1256     	 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1257     	 * MptResetHandlers[] registered yet.
1258     	 */
1259     	if (hard_reset_done) {
1260     		r = handlers = 0;
1261     		for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
1262     			if (MptResetHandlers[i]) {
1263     				dprintk((KERN_INFO MYNAM ": %s: Calling IOC pre_reset handler #%d\n",
1264     						ioc->name, i));
1265     				r += (*(MptResetHandlers[i]))(ioc, MPT_IOC_PRE_RESET);
1266     				handlers++;
1267     
1268     				if (alt_ioc_ready) {
1269     					dprintk((KERN_INFO MYNAM ": %s: Calling alt-IOC pre_reset handler #%d\n",
1270     							ioc->alt_ioc->name, i));
1271     					r += (*(MptResetHandlers[i]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
1272     					handlers++;
1273     				}
1274     			}
1275     		}
1276     		/* FIXME?  Examine results here? */
1277     	}
1278     
1279     	// May need to check/upload firmware & data here!
1280     
1281     	if ((r = SendIocInit(ioc)) != 0)
1282     		return -3;
1283     // NEW!
1284     	if (alt_ioc_ready) {
1285     		if ((r = SendIocInit(ioc->alt_ioc)) != 0) {
1286     			alt_ioc_ready = 0;
1287     			printk(KERN_WARNING MYNAM ": alt-%s: (%d) init failure WARNING!\n",
1288     					ioc->alt_ioc->name, r);
1289     		}
1290     	}
1291     
1292     	/*
1293     	 * Call each currently registered protocol IOC reset handler
1294     	 * with post-reset indication.
1295     	 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1296     	 * MptResetHandlers[] registered yet.
1297     	 */
1298     	if (hard_reset_done) {
1299     		r = handlers = 0;
1300     		for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
1301     			if (MptResetHandlers[i]) {
1302     				dprintk((KERN_INFO MYNAM ": %s: Calling IOC post_reset handler #%d\n",
1303     						ioc->name, i));
1304     				r += (*(MptResetHandlers[i]))(ioc, MPT_IOC_POST_RESET);
1305     				handlers++;
1306     
1307     				if (alt_ioc_ready) {
1308     					dprintk((KERN_INFO MYNAM ": %s: Calling alt-IOC post_reset handler #%d\n",
1309     							ioc->alt_ioc->name, i));
1310     					r += (*(MptResetHandlers[i]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
1311     					handlers++;
1312     				}
1313     			}
1314     		}
1315     		/* FIXME?  Examine results here? */
1316     	}
1317     
1318     	/*
1319     	 * Prime reply & request queues!
1320     	 * (mucho alloc's)
1321     	 */
1322     	if ((r = PrimeIocFifos(ioc)) != 0)
1323     		return -4;
1324     // NEW!
1325     	if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1326     		printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1327     				ioc->alt_ioc->name, r);
1328     	}
1329     
1330     // FIXME! Cleanup all IOC (and alt-IOC?) requests here!
1331     
1332     	if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1333     	    (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1334     		/*
1335     		 *  Pre-fetch the ports LAN MAC address!
1336     		 *  (LANPage1_t stuff)
1337     		 */
1338     		(void) GetLanConfigPages(ioc);
1339     #ifdef MPT_DEBUG
1340     		{
1341     			u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1342     			dprintk((KERN_INFO MYNAM ": %s: LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1343     					ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1344     		}
1345     #endif
1346     	}
1347     
1348     	/* Enable! (reply interrupt) */
1349     	CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1350     	ioc->active = 1;
1351     
1352     // NEW!
1353     #if 0						// Kiss-of-death!?!
1354     	if (alt_ioc_ready && (r==0)) {
1355     		/* (re)Enable alt-IOC! (reply interrupt) */
1356     		dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1357     				ioc->alt_ioc->name));
1358     		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
1359     		ioc->alt_ioc->active = 1;
1360     	}
1361     #endif
1362     
1363     	/* NEW!  20010120 -sralston
1364     	 *  Enable MPT base driver management of EventNotification
1365     	 *  and EventAck handling.
1366     	 */
1367     	if (!ioc->facts.EventState)
1368     		(void) SendEventNotification(ioc, 1);	/* 1=Enable EventNotification */
1369     // NEW!
1370     // FIXME!?!
1371     //	if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) {
1372     //		(void) SendEventNotification(ioc->alt_ioc, 1);	/* 1=Enable EventNotification */
1373     //	}
1374     
1375     	return 0;
1376     }
1377     
1378     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1379     /*
1380      *	mpt_detect_929_bound_ports - Search for PCI bus/dev_function
1381      *	which matches PCI bus/dev_function (+/-1) for newly discovered 929.
1382      *	@ioc: Pointer to MPT adapter structure
1383      *	@pdev: Pointer to (struct pci_dev) structure
1384      *
1385      *	If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1386      *	using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1387      */
1388     static void
1389     mpt_detect_929_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1390     {
1391     	MPT_ADAPTER *ioc_srch = mpt_adapter_find_first();
1392     	unsigned int match_lo, match_hi;
1393     
1394     	match_lo = pdev->devfn-1;
1395     	match_hi = pdev->devfn+1;
1396     	dprintk((KERN_INFO MYNAM ": %s: PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
1397     			ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi));
1398     
1399     	while (ioc_srch != NULL) {
1400     		struct pci_dev *_pcidev = ioc_srch->pcidev;
1401     
1402     		if ( (_pcidev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) &&
1403     		     (_pcidev->bus->number == pdev->bus->number) &&
1404     		     (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
1405     			/* Paranoia checks */
1406     			if (ioc->alt_ioc != NULL) {
1407     				printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1408     						ioc->name, ioc->alt_ioc->name);
1409     				break;
1410     			} else if (ioc_srch->alt_ioc != NULL) {
1411     				printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1412     						ioc_srch->name, ioc_srch->alt_ioc->name);
1413     				break;
1414     			}
1415     			dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1416     					ioc->name, ioc_srch->name));
1417     			ioc_srch->alt_ioc = ioc;
1418     			ioc->alt_ioc = ioc_srch;
1419     			ioc->sod_reset = ioc->alt_ioc->sod_reset;
1420     			ioc->last_kickstart = ioc->alt_ioc->last_kickstart;
1421     			break;
1422     		}
1423     		ioc_srch = mpt_adapter_find_next(ioc_srch);
1424     	}
1425     }
1426     
1427     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1428     /*
1429      *	mpt_adapter_disable - Disable misbehaving MPT adapter.
1430      *	@this: Pointer to MPT adapter structure
1431      *	@free: Free up alloc'd reply, request, etc.
1432      */
1433     static void
1434     mpt_adapter_disable(MPT_ADAPTER *this, int freeup)
1435     {
1436     	if (this != NULL) {
1437     		int sz;
1438     
1439     		/* Disable the FW */
1440     		if (SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET) != 0)
1441     			(void) KickStart(this, 1);
1442     
1443     		/* Disable adapter interrupts! */
1444     		CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
1445     		this->active = 0;
1446     		/* Clear any lingering interrupt */
1447     		CHIPREG_WRITE32(&this->chip->IntStatus, 0);
1448     
1449     		if (freeup && this->reply_alloc != NULL) {
1450     			sz = (this->reply_sz * this->reply_depth) + 128;
1451     			pci_free_consistent(this->pcidev, sz,
1452     					this->reply_alloc, this->reply_alloc_dma);
1453     			this->reply_frames = NULL;
1454     			this->reply_alloc = NULL;
1455     			this->alloc_total -= sz;
1456     		}
1457     
1458     		if (freeup && this->req_alloc != NULL) {
1459     			sz = (this->req_sz * this->req_depth) + 128;
1460     			/*
1461     			 *  Rounding UP to nearest 4-kB boundary here...
1462     			 */
1463     			sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
1464     			pci_free_consistent(this->pcidev, sz,
1465     					this->req_alloc, this->req_alloc_dma);
1466     			this->req_frames = NULL;
1467     			this->req_alloc = NULL;
1468     			this->alloc_total -= sz;
1469     		}
1470     
1471     		if (freeup && this->sense_buf_pool != NULL) {
1472     			sz = (this->req_depth * 256);
1473     			pci_free_consistent(this->pcidev, sz,
1474     					this->sense_buf_pool, this->sense_buf_pool_dma);
1475     			this->sense_buf_pool = NULL;
1476     			this->alloc_total -= sz;
1477     		}
1478     	}
1479     }
1480     
1481     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1482     /*
1483      *	mpt_adapter_dispose - Free all resources associated with a MPT
1484      *	adapter.
1485      *	@this: Pointer to MPT adapter structure
1486      *
1487      *	This routine unregisters h/w resources and frees all alloc'd memory
1488      *	associated with a MPT adapter structure.
1489      */
1490     static void
1491     mpt_adapter_dispose(MPT_ADAPTER *this)
1492     {
1493     	if (this != NULL) {
1494     		int sz_first, sz_last;
1495     
1496     		sz_first = this->alloc_total;
1497     
1498     		mpt_adapter_disable(this, 1);
1499     
1500     		if (this->pci_irq != -1) {
1501     			free_irq(this->pci_irq, this);
1502     			this->pci_irq = -1;
1503     		}
1504     
1505     		if (this->memmap != NULL)
1506     			iounmap((u8 *) this->memmap);
1507     
1508     #if defined(CONFIG_MTRR) && 0
1509     		if (this->mtrr_reg > 0) {
1510     			mtrr_del(this->mtrr_reg, 0, 0);
1511     			dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name));
1512     		}
1513     #endif
1514     
1515     		/*  Zap the adapter lookup ptr!  */
1516     		mpt_adapters[this->id] = NULL;
1517     
1518     		sz_last = this->alloc_total;
1519     		dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
1520     				this->name, sz_first-sz_last+(int)sizeof(*this), sz_first));
1521     		kfree(this);
1522     	}
1523     }
1524     
1525     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1526     /*
1527      *	MptDisplayIocCapabilities - Disply IOC's capacilities.
1528      *	@ioc: Pointer to MPT adapter structure
1529      */
1530     static void
1531     MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
1532     {
1533     	int i = 0;
1534     
1535     	printk(KERN_INFO "%s: ", ioc->name);
1536     	if (ioc->prod_name && strlen(ioc->prod_name) > 3)
1537     		printk("%s: ", ioc->prod_name+3);
1538     	printk("Capabilities={");
1539     
1540     	if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
1541     		printk("Initiator");
1542     		i++;
1543     	}
1544     
1545     	if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
1546     		printk("%sTarget", i ? "," : "");
1547     		i++;
1548     	}
1549     
1550     	if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
1551     		printk("%sLAN", i ? "," : "");
1552     		i++;
1553     	}
1554     
1555     #if 0
1556     	/*
1557     	 *  This would probably evoke more questions than it's worth
1558     	 */
1559     	if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
1560     		printk("%sLogBusAddr", i ? "," : "");
1561     		i++;
1562     	}
1563     #endif
1564     
1565     	printk("}\n");
1566     }
1567     
1568     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1569     /*
1570      *	MakeIocReady - Get IOC to a READY state, using KickStart if needed.
1571      *	@ioc: Pointer to MPT_ADAPTER structure
1572      *	@kick: Force hard KickStart of IOC
1573      *
1574      *	Returns 0 for already-READY, 1 for hard reset success,
1575      *	else negative for failure.
1576      */
1577     static int
1578     MakeIocReady(MPT_ADAPTER *ioc, int force)
1579     {
1580     	u32	 ioc_state;
1581     	int	 statefault = 0;
1582     	int 	 cntdn;
1583     	int	 hard_reset_done = 0;
1584     	int	 r;
1585     	int	 i;
1586     
1587     	/* Get current [raw] IOC state  */
1588     	ioc_state = GetIocState(ioc, 0);
1589     	dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
1590     
1591     	/*
1592     	 *	Check to see if IOC got left/stuck in doorbell handshake
1593     	 *	grip of death.  If so, hard reset the IOC.
1594     	 */
1595     	if (ioc_state & MPI_DOORBELL_ACTIVE) {
1596     		statefault = 1;
1597     		printk(KERN_WARNING MYNAM ": %s: Uh-oh, unexpected doorbell active!\n",
1598     				ioc->name);
1599     	}
1600     
1601     	/* Is it already READY? */
1602     	if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
1603     		return 0;
1604     
1605     	/*
1606     	 *	Check to see if IOC is in FAULT state.
1607     	 */
1608     	if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
1609     		statefault = 2;
1610     		printk(KERN_WARNING MYNAM ": %s: Uh-oh, IOC is in FAULT state!!!\n",
1611     				ioc->name);
1612     		printk(KERN_WARNING "           FAULT code = %04xh\n",
1613     				ioc_state & MPI_DOORBELL_DATA_MASK);
1614     	}
1615     
1616     	/*
1617     	 *	Hmmm...  Did it get left operational?
1618     	 */
1619     	if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
1620     		statefault = 3;
1621     		dprintk((KERN_WARNING MYNAM ": %s: Hmmm... IOC operational unexpected\n",
1622     				ioc->name));
1623     	}
1624     
1625     	hard_reset_done = KickStart(ioc, statefault||force);
1626     	if (hard_reset_done < 0)
1627     		return -1;
1628     
1629     	/*
1630     	 *  Loop here waiting for IOC to come READY.
1631     	 */
1632     	i = 0;
1633     	cntdn = HZ * 15;
1634     	while ((ioc_state = GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
1635     		if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
1636     			/*
1637     			 *  BIOS or previous driver load left IOC in OP state.
1638     			 *  Reset messaging FIFOs.
1639     			 */
1640     			if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET)) != 0) {
1641     				printk(KERN_ERR MYNAM ": %s: ERROR - IOC msg unit reset failed!\n", ioc->name);
1642     				return -2;
1643     			}
1644     		} else if (ioc_state == MPI_IOC_STATE_RESET) {
1645     			/*
1646     			 *  Something is wrong.  Try to get IOC back
1647     			 *  to a known state.
1648     			 */
1649     			if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET)) != 0) {
1650     				printk(KERN_ERR MYNAM ": %s: ERROR - IO unit reset failed!\n", ioc->name);
1651     				return -3;
1652     			}
1653     		}
1654     
1655     		i++; cntdn--;
1656     		if (!cntdn) {
1657     			printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
1658     					ioc->name, (i+5)/HZ);
1659     			return -ETIME;
1660     		}
1661     
1662     		current->state = TASK_INTERRUPTIBLE;
1663     		schedule_timeout(1);
1664     	}
1665     
1666     	if (statefault < 3) {
1667     		printk(KERN_WARNING MYNAM ": %s: Whew!  Recovered from %s\n",
1668     				ioc->name,
1669     				statefault==1 ? "stuck handshake" : "IOC FAULT");
1670     	}
1671     
1672     	return hard_reset_done;
1673     }
1674     
1675     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1676     /*
1677      *	GetIocState - Get the current state of a MPT adapter.
1678      *	@ioc: Pointer to MPT_ADAPTER structure
1679      *	@cooked: Request raw or cooked IOC state
1680      *
1681      *	Returns all IOC Doorbell register bits if cooked==0, else just the
1682      *	Doorbell bits in MPI_IOC_STATE_MASK.
1683      */
1684     static u32
1685     GetIocState(MPT_ADAPTER *ioc, int cooked)
1686     {
1687     	u32 s, sc;
1688     
1689     	/*  Get!  */
1690     	s = CHIPREG_READ32(&ioc->chip->Doorbell);
1691     	dprintk((KERN_INFO MYNAM ": %s: raw state = %08x\n", ioc->name, s));
1692     	sc = s & MPI_IOC_STATE_MASK;
1693     
1694     	/*  Save!  */
1695     	ioc->last_state = sc;
1696     
1697     	return cooked ? sc : s;
1698     }
1699     
1700     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1701     /*
1702      *	GetIocFacts - Send IOCFacts request to MPT adapter.
1703      *	@ioc: Pointer to MPT_ADAPTER structure
1704      *
1705      *	Returns 0 for success, non-zero for failure.
1706      */
1707     static int
1708     GetIocFacts(MPT_ADAPTER *ioc)
1709     {
1710     	IOCFacts_t		 get_facts;
1711     	IOCFactsReply_t		*facts;
1712     	int			 r;
1713     	int			 req_sz;
1714     	int			 reply_sz;
1715     	u32			 status;
1716     
1717     	/* IOC *must* NOT be in RESET state! */
1718     	if (ioc->last_state == MPI_IOC_STATE_RESET) {
1719     		printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
1720     				ioc->name,
1721     				ioc->last_state );
1722     		return -44;
1723     	}
1724     
1725     	facts = &ioc->facts;
1726     
1727     	/* Destination (reply area)... */
1728     	reply_sz = sizeof(*facts);
1729     	memset(facts, 0, reply_sz);
1730     
1731     	/* Request area (get_facts on the stack right now!) */
1732     	req_sz = sizeof(get_facts);
1733     	memset(&get_facts, 0, req_sz);
1734     
1735     	get_facts.Function = MPI_FUNCTION_IOC_FACTS;
1736     	/* Assert: All other get_facts fields are zero! */
1737     
1738     	dprintk((KERN_INFO MYNAM ": %s: Sending get IocFacts request\n", ioc->name));
1739     
1740     	/* No non-zero fields in the get_facts request are greater than
1741     	 * 1 byte in size, so we can just fire it off as is.
1742     	 */
1743     	r = HandShakeReqAndReply(ioc,
1744     			req_sz, (u32*)&get_facts,
1745     			reply_sz, (u16*)facts, 3);
1746     	if (r != 0)
1747     		return r;
1748     
1749     	/*
1750     	 * Now byte swap (GRRR) the necessary fields before any further
1751     	 * inspection of reply contents.
1752     	 *
1753     	 * But need to do some sanity checks on MsgLength (byte) field
1754     	 * to make sure we don't zero IOC's req_sz!
1755     	 */
1756     	/* Did we get a valid reply? */
1757     	if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
1758     		/*
1759     		 * If not been here, done that, save off first WhoInit value
1760     		 */
1761     		if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
1762     			ioc->FirstWhoInit = facts->WhoInit;
1763     
1764     		facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
1765     		facts->MsgContext = le32_to_cpu(facts->MsgContext);
1766     		facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
1767     		facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
1768     		status = facts->IOCStatus & MPI_IOCSTATUS_MASK;
1769     		/* CHECKME! IOCStatus, IOCLogInfo */
1770     
1771     		facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
1772     		facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
1773     		facts->FWVersion = le16_to_cpu(facts->FWVersion);
1774     		facts->ProductID = le16_to_cpu(facts->ProductID);
1775     		facts->CurrentHostMfaHighAddr =
1776     				le32_to_cpu(facts->CurrentHostMfaHighAddr);
1777     		facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
1778     		facts->CurrentSenseBufferHighAddr =
1779     				le32_to_cpu(facts->CurrentSenseBufferHighAddr);
1780     		facts->CurReplyFrameSize =
1781     				le16_to_cpu(facts->CurReplyFrameSize);
1782     
1783     		/*
1784     		 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
1785     		 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
1786     		 * to 14 in MPI-1.01.0x.
1787     		 */
1788     		if (facts->MsgLength >= sizeof(IOCFactsReply_t)/sizeof(u32) && facts->MsgVersion > 0x0100) {
1789     			facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
1790     			facts->DataImageSize = le32_to_cpu(facts->DataImageSize);
1791     		}
1792     
1793     		if (facts->RequestFrameSize) {
1794     			/*
1795     			 * Set values for this IOC's REQUEST queue size & depth...
1796     			 */
1797     			ioc->req_sz = MIN(MPT_REQ_SIZE, facts->RequestFrameSize * 4);
1798     
1799     			/*
1800     			 *  Set values for this IOC's REPLY queue size & depth...
1801     			 *
1802     			 * BUG? FIX?  20000516 -nromer & sralston 
1803     			 *  GRRR...  The following did not translate well from MPI v0.09:
1804     			 *	ioc->reply_sz = MIN(MPT_REPLY_SIZE, facts->ReplySize * 4);
1805     			 *  to 0.10:
1806     			 *	ioc->reply_sz = MIN(MPT_REPLY_SIZE, facts->BlockSize * 4);
1807     			 *  Was trying to minimally optimize to smallest possible reply size
1808     			 *  (and greatly reduce kmalloc size).  But LAN may need larger reply?
1809     			 *
1810     			 *  So for now, just set reply size to request size.  FIXME?
1811     			 */
1812     			ioc->reply_sz = ioc->req_sz;
1813     		} else {
1814     			/*  Something is wrong!  */
1815     			printk(KERN_ERR MYNAM ": %s: ERROR - IOC reported invalid 0 request size!\n",
1816     					ioc->name);
1817     			ioc->req_sz = MPT_REQ_SIZE;
1818     			ioc->reply_sz = MPT_REPLY_SIZE;
1819     			return -55;
1820     		}
1821     		ioc->req_depth = MIN(MPT_REQ_DEPTH, facts->GlobalCredits);
1822     		ioc->reply_depth = MIN(MPT_REPLY_DEPTH, facts->ReplyQueueDepth);
1823     
1824     		dprintk((KERN_INFO MYNAM ": %s: reply_sz=%3d, reply_depth=%4d\n",
1825     				ioc->name, ioc->reply_sz, ioc->reply_depth));
1826     		dprintk((KERN_INFO MYNAM ": %s: req_sz  =%3d, req_depth  =%4d\n",
1827     				ioc->name, ioc->req_sz, ioc->req_depth));
1828     
1829     		/* Get port facts! */
1830     		if ( (r = GetPortFacts(ioc, 0)) != 0 )
1831     			return r;
1832     	} else {
1833     		printk(KERN_ERR MYNAM ": %s: ERROR - Invalid IOC facts reply!\n",
1834     				ioc->name);
1835     		return -66;
1836     	}
1837     
1838     	return 0;
1839     }
1840     
1841     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1842     /*
1843      *	GetPortFacts - Send PortFacts request to MPT adapter.
1844      *	@ioc: Pointer to MPT_ADAPTER structure
1845      *	@portnum: Port number
1846      *
1847      *	Returns 0 for success, non-zero for failure.
1848      */
1849     static int
1850     GetPortFacts(MPT_ADAPTER *ioc, int portnum)
1851     {
1852     	PortFacts_t		 get_pfacts;
1853     	PortFactsReply_t	*pfacts;
1854     	int			 i;
1855     	int			 req_sz;
1856     	int			 reply_sz;
1857     
1858     	/* IOC *must* NOT be in RESET state! */
1859     	if (ioc->last_state == MPI_IOC_STATE_RESET) {
1860     		printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
1861     				ioc->name,
1862     				ioc->last_state );
1863     		return -4;
1864     	}
1865     
1866     	pfacts = &ioc->pfacts[portnum];
1867     
1868     	/* Destination (reply area)...  */
1869     	reply_sz = sizeof(*pfacts);
1870     	memset(pfacts, 0, reply_sz);
1871     
1872     	/* Request area (get_pfacts on the stack right now!) */
1873     	req_sz = sizeof(get_pfacts);
1874     	memset(&get_pfacts, 0, req_sz);
1875     
1876     	get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
1877     	get_pfacts.PortNumber = portnum;
1878     	/* Assert: All other get_pfacts fields are zero! */
1879     
1880     	dprintk((KERN_INFO MYNAM ": %s: Sending get PortFacts(%d) request\n",
1881     			ioc->name, portnum));
1882     
1883     	/* No non-zero fields in the get_pfacts request are greater than
1884     	 * 1 byte in size, so we can just fire it off as is.
1885     	 */
1886     	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&get_pfacts,
1887     				reply_sz, (u16*)pfacts, 3);
1888     	if (i != 0)
1889     		return i;
1890     
1891     	/* Did we get a valid reply? */
1892     
1893     	/* Now byte swap the necessary fields in the response. */
1894     	pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
1895     	pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
1896     	pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
1897     	pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
1898     	pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
1899     	pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
1900     	pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
1901     	pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
1902     	pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
1903     
1904     	return 0;
1905     }
1906     
1907     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1908     /*
1909      *	SendIocInit - Send IOCInit request to MPT adapter.
1910      *	@ioc: Pointer to MPT_ADAPTER structure
1911      *
1912      *	Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
1913      *
1914      *	Returns 0 for success, non-zero for failure.
1915      */
1916     static int
1917     SendIocInit(MPT_ADAPTER *ioc)
1918     {
1919     	IOCInit_t		 ioc_init;
1920     	MPIDefaultReply_t	 init_reply;
1921     	u32			 state;
1922     	int			 r;
1923     	int			 count;
1924     	int			 cntdn;
1925     
1926     	memset(&ioc_init, 0, sizeof(ioc_init));
1927     	memset(&init_reply, 0, sizeof(init_reply));
1928     
1929     	ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
1930     /*	ioc_init.ChainOffset = 0;			*/
1931     	ioc_init.Function = MPI_FUNCTION_IOC_INIT;
1932     /*	ioc_init.Flags = 0;				*/
1933     
1934     	/*ioc_init.MaxDevices = 16;*/
1935     	ioc_init.MaxDevices = 255;
1936     /*	ioc_init.MaxBuses = 16;				*/
1937     	ioc_init.MaxBuses = 1;
1938     
1939     /*	ioc_init.MsgFlags = 0;				*/
1940     /*	ioc_init.MsgContext = cpu_to_le32(0x00000000);	*/
1941     	ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);	/* in BYTES */
1942     	ioc_init.HostMfaHighAddr = cpu_to_le32(0);	/* Say we 32-bit! for now */
1943     
1944     	dprintk((KERN_INFO MYNAM ": %s: Sending IOCInit (req @ %p)\n", ioc->name, &ioc_init));
1945     
1946     	r = HandShakeReqAndReply(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
1947     			sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10);
1948     	if (r != 0)
1949     		return r;
1950     
1951     	/* No need to byte swap the multibyte fields in the reply
1952     	 * since we don't even look at it's contents.
1953     	 */
1954     
1955     	if ((r = SendPortEnable(ioc, 0)) != 0)
1956     		return r;
1957     
1958     	/* YIKES!  SUPER IMPORTANT!!!
1959     	 *  Poll IocState until _OPERATIONAL while IOC is doing
1960     	 *  LoopInit and TargetDiscovery!
1961     	 */
1962     	count = 0;
1963     	cntdn = HZ * 60;					/* chg'd from 30 to 60 seconds */
1964     	state = GetIocState(ioc, 1);
1965     	while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
1966     		current->state = TASK_INTERRUPTIBLE;
1967     		schedule_timeout(1);
1968     
1969     		if (!cntdn) {
1970     			printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_OP state timeout(%d)!\n",
1971     					ioc->name, (count+5)/HZ);
1972     			return -9;
1973     		}
1974     
1975     		state = GetIocState(ioc, 1);
1976     		count++;
1977     	}
1978     	dhsprintk((KERN_INFO MYNAM ": %s: INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
1979     			ioc->name, count));
1980     
1981     	return r;
1982     }
1983     
1984     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1985     /*
1986      *	SendPortEnable - Send PortEnable request to MPT adapter port.
1987      *	@ioc: Pointer to MPT_ADAPTER structure
1988      *	@portnum: Port number to enable
1989      *
1990      *	Send PortEnable to bring IOC to OPERATIONAL state.
1991      *
1992      *	Returns 0 for success, non-zero for failure.
1993      */
1994     static int
1995     SendPortEnable(MPT_ADAPTER *ioc, int portnum)
1996     {
1997     	PortEnable_t		 port_enable;
1998     	MPIDefaultReply_t	 reply_buf;
1999     	int	 i;
2000     	int	 req_sz;
2001     	int	 reply_sz;
2002     
2003     	/*  Destination...  */
2004     	reply_sz = sizeof(MPIDefaultReply_t);
2005     	memset(&reply_buf, 0, reply_sz);
2006     
2007     	req_sz = sizeof(PortEnable_t);
2008     	memset(&port_enable, 0, req_sz);
2009     
2010     	port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2011     	port_enable.PortNumber = portnum;
2012     /*	port_enable.ChainOffset = 0;		*/
2013     /*	port_enable.MsgFlags = 0;		*/
2014     /*	port_enable.MsgContext = 0;		*/
2015     
2016     	dprintk((KERN_INFO MYNAM ": %s: Sending Port(%d)Enable (req @ %p)\n",
2017     			ioc->name, portnum, &port_enable));
2018     
2019     	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&port_enable,
2020     			reply_sz, (u16*)&reply_buf, 65);
2021     	if (i != 0)
2022     		return i;
2023     
2024     	/* We do not even look at the reply, so we need not
2025     	 * swap the multi-byte fields.
2026     	 */
2027     
2028     	return 0;
2029     }
2030     
2031     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2032     /*
2033      *	KickStart - Perform hard reset of MPT adapter.
2034      *	@ioc: Pointer to MPT_ADAPTER structure
2035      *	@force: Force hard reset
2036      *
2037      *	This routine places MPT adapter in diagnostic mode via the
2038      *	WriteSequence register, and then performs a hard reset of adapter
2039      *	via the Diagnostic register.
2040      *
2041      *	Returns 0 for soft reset success, 1 for hard reset success,
2042      *	else a negative value for failure.
2043      */
2044     static int
2045     KickStart(MPT_ADAPTER *ioc, int force)
2046     {
2047     	int hard_reset_done = 0;
2048     	u32 ioc_state;
2049     	int cnt = 0;
2050     
2051     	dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
2052     
2053     	hard_reset_done = mpt_fc9x9_reset(ioc, force);
2054     #if 0
2055     	if (ioc->chip_type == FC909 || ioc->chip-type == FC919) {
2056     		hard_reset_done = mpt_fc9x9_reset(ioc, force);
2057     	} else if (ioc->chip_type == FC929) {
2058     		unsigned long delta;
2059     
2060     		delta = jiffies - ioc->last_kickstart;
2061     		dprintk((KERN_INFO MYNAM ": %s: 929 KickStart, last=%ld, delta = %ld\n",
2062     				ioc->name, ioc->last_kickstart, delta));
2063     		if ((ioc->sod_reset == 0) || (delta >= 10*HZ))
2064     			hard_reset_done = mpt_fc9x9_reset(ioc, ignore);
2065     		else {
2066     			dprintk((KERN_INFO MYNAM ": %s: Skipping KickStart (delta=%ld)!\n",
2067     					ioc->name, delta));
2068     			return 0;
2069     		}
2070     	/* TODO! Add C1030!
2071     	} else if (ioc->chip_type == C1030) {
2072     	 */
2073     	} else {
2074     		printk(KERN_ERR MYNAM ": %s: ERROR - Bad chip_type (0x%x)\n",
2075     				ioc->name, ioc->chip_type);
2076     		return -5;
2077     	}
2078     #endif
2079     
2080     	if (hard_reset_done < 0)
2081     		return hard_reset_done;
2082     
2083     	dprintk((KERN_INFO MYNAM ": %s: Diagnostic reset successful\n",
2084     			ioc->name));
2085     
2086     	for (cnt=0; cnt<HZ*20; cnt++) {
2087     		if ((ioc_state = GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) {
2088     			dprintk((KERN_INFO MYNAM ": %s: KickStart successful! (cnt=%d)\n",
2089     					ioc->name, cnt));
2090     			return hard_reset_done;
2091     		}
2092     		/* udelay(10000) ? */
2093     		current->state = TASK_INTERRUPTIBLE;
2094     		schedule_timeout(1);
2095     	}
2096     
2097     	printk(KERN_ERR MYNAM ": %s: ERROR - Failed to come READY after reset!\n",
2098     			ioc->name);
2099     	return -1;
2100     }
2101     
2102     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2103     /*
2104      *	mpt_fc9x9_reset - Perform hard reset of FC9x9 adapter.
2105      *	@ioc: Pointer to MPT_ADAPTER structure
2106      *
2107      *	This routine places FC9x9 adapter in diagnostic mode via the
2108      *	WriteSequence register, and then performs a hard reset of adapter
2109      *	via the Diagnostic register.
2110      *
2111      *	Returns 0 for success, non-zero for failure.
2112      */
2113     static int
2114     mpt_fc9x9_reset(MPT_ADAPTER *ioc, int ignore)
2115     {
2116     	u32 diag0val;
2117     	int hard_reset_done = 0;
2118     
2119     	/* Use "Diagnostic reset" method! (only thing available!) */
2120     
2121     	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2122     #ifdef MPT_DEBUG
2123     {
2124     	u32 diag1val = 0;
2125     	if (ioc->alt_ioc)
2126     		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
2127     	dprintk((KERN_INFO MYNAM ": %s: DBG1: diag0=%08x, diag1=%08x\n",
2128     			ioc->name, diag0val, diag1val));
2129     }
2130     #endif
2131     	if (diag0val & MPI_DIAG_DRWE) {
2132     		dprintk((KERN_INFO MYNAM ": %s: DiagWriteEn bit already set\n",
2133     				ioc->name));
2134     	} else {
2135     		/* Write magic sequence to WriteSequence register */
2136     		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2137     		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2138     		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2139     		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2140     		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2141     		dprintk((KERN_INFO MYNAM ": %s: Wrote magic DiagWriteEn sequence [spot#1]\n",
2142     				ioc->name));
2143     	}
2144     
2145     	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2146     #ifdef MPT_DEBUG
2147     {
2148     	u32 diag1val = 0;
2149     	if (ioc->alt_ioc)
2150     		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
2151     	dprintk((KERN_INFO MYNAM ": %s: DbG2: diag0=%08x, diag1=%08x\n",
2152     			ioc->name, diag0val, diag1val));
2153     }
2154     #endif
2155     	if (!ignore && (diag0val & MPI_DIAG_RESET_HISTORY)) {
2156     		dprintk((KERN_INFO MYNAM ": %s: Skipping due to ResetHistory bit set!\n",
2157     				ioc->name));
2158     	} else {
2159     		/*
2160     		 * Now hit the reset bit in the Diagnostic register
2161     		 * (THE BIG HAMMER!)
2162     		 */
2163     		CHIPREG_WRITE32(&ioc->chip->Diagnostic, MPI_DIAG_RESET_ADAPTER);
2164     		hard_reset_done = 1;
2165     		dprintk((KERN_INFO MYNAM ": %s: Diagnostic reset performed\n",
2166     				ioc->name));
2167     
2168     		/* want udelay(100) */
2169     		current->state = TASK_INTERRUPTIBLE;
2170     		schedule_timeout(1);
2171     
2172     		/* Write magic sequence to WriteSequence register */
2173     		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2174     		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2175     		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2176     		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2177     		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2178     		dprintk((KERN_INFO MYNAM ": %s: Wrote magic DiagWriteEn sequence [spot#2]\n",
2179     				ioc->name));
2180     	}
2181     
2182     	/* Clear RESET_HISTORY bit! */
2183     	CHIPREG_WRITE32(&ioc->chip->Diagnostic, 0x0);
2184     
2185     	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2186     #ifdef MPT_DEBUG
2187     {
2188     	u32 diag1val = 0;
2189     	if (ioc->alt_ioc)
2190     		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
2191     	dprintk((KERN_INFO MYNAM ": %s: DbG3: diag0=%08x, diag1=%08x\n",
2192     			ioc->name, diag0val, diag1val));
2193     }
2194     #endif
2195     	if (diag0val & MPI_DIAG_RESET_HISTORY) {
2196     		printk(KERN_WARNING MYNAM ": %s: WARNING - ResetHistory bit failed to clear!\n",
2197     				ioc->name);
2198     	}
2199     
2200     	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2201     #ifdef MPT_DEBUG
2202     {
2203     	u32 diag1val = 0;
2204     	if (ioc->alt_ioc)
2205     		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
2206     	dprintk((KERN_INFO MYNAM ": %s: DbG4: diag0=%08x, diag1=%08x\n",
2207     			ioc->name, diag0val, diag1val));
2208     }
2209     #endif
2210     	if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
2211     		printk(KERN_ERR MYNAM ": %s: ERROR - Diagnostic reset FAILED! (%02xh)\n",
2212     				ioc->name, diag0val);
2213     		return -3;
2214     	}
2215     
2216     	/*
2217     	 * Reset flag that says we've enabled event notification
2218     	 */
2219     	ioc->facts.EventState = 0;
2220     
2221     	/* NEW!  20010220 -sralston
2222     	 * Try to avoid redundant resets of the 929.
2223     	 */
2224     	ioc->sod_reset++;
2225     	ioc->last_kickstart = jiffies;
2226     	if (ioc->alt_ioc) {
2227     		ioc->alt_ioc->sod_reset = ioc->sod_reset;
2228     		ioc->alt_ioc->last_kickstart = ioc->last_kickstart;
2229     	}
2230     
2231     	return hard_reset_done;
2232     }
2233     
2234     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2235     /*
2236      *	SendIocReset - Send IOCReset request to MPT adapter.
2237      *	@ioc: Pointer to MPT_ADAPTER structure
2238      *	@reset_type: reset type, expected values are
2239      *	%MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
2240      *
2241      *	Send IOCReset request to the MPT adapter.
2242      *
2243      *	Returns 0 for success, non-zero for failure.
2244      */
2245     static int
2246     SendIocReset(MPT_ADAPTER *ioc, u8 reset_type)
2247     {
2248     	int r;
2249     
2250     	dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
2251     			ioc->name, reset_type));
2252     	CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
2253     	if ((r = WaitForDoorbellAck(ioc, 2)) < 0)
2254     		return r;
2255     
2256     	/* TODO!
2257     	 *  Cleanup all event stuff for this IOC; re-issue EventNotification
2258     	 *  request if needed.
2259     	 */
2260     	if (ioc->facts.Function)
2261     		ioc->facts.EventState = 0;
2262     
2263     	return 0;
2264     }
2265     
2266     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2267     /*
2268      *	PrimeIocFifos - Initialize IOC request and reply FIFOs.
2269      *	@ioc: Pointer to MPT_ADAPTER structure
2270      *
2271      *	This routine allocates memory for the MPT reply and request frame
2272      *	pools, and primes the IOC reply FIFO with reply frames.
2273      *
2274      *	Returns 0 for success, non-zero for failure.
2275      */
2276     static int
2277     PrimeIocFifos(MPT_ADAPTER *ioc)
2278     {
2279     	MPT_FRAME_HDR *mf;
2280     	unsigned long b;
2281     	dma_addr_t aligned_mem_dma;
2282     	u8 *mem, *aligned_mem;
2283     	int i, sz;
2284     
2285     	/*  Prime reply FIFO...  */
2286     
2287     	if (ioc->reply_frames == NULL) {
2288     		sz = (ioc->reply_sz * ioc->reply_depth) + 128;
2289     		mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->reply_alloc_dma);
2290     		if (mem == NULL)
2291     			goto out_fail;
2292     
2293     		memset(mem, 0, sz);
2294     		ioc->alloc_total += sz;
2295     		ioc->reply_alloc = mem;
2296     		dprintk((KERN_INFO MYNAM ": %s.reply_alloc  @ %p[%08x], sz=%d bytes\n",
2297     			 ioc->name, mem, ioc->reply_alloc_dma, sz));
2298     
2299     		b = (unsigned long) mem;
2300     		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
2301     		aligned_mem = (u8 *) b;
2302     		ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem;
2303     		ioc->reply_frames_dma =
2304     			(ioc->reply_alloc_dma + (aligned_mem - mem));
2305     		aligned_mem_dma = ioc->reply_frames_dma;
2306     		dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%08x]\n",
2307     			 ioc->name, aligned_mem, aligned_mem_dma));
2308     
2309     		for (i = 0; i < ioc->reply_depth; i++) {
2310     			/*  Write each address to the IOC!  */
2311     			CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma);
2312     			aligned_mem_dma += ioc->reply_sz;
2313     		}
2314     	}
2315     
2316     
2317     	/*  Request FIFO - WE manage this!  */
2318     
2319     	if (ioc->req_frames == NULL) {
2320     		sz = (ioc->req_sz * ioc->req_depth) + 128;
2321     		/*
2322     		 *  Rounding UP to nearest 4-kB boundary here...
2323     		 */
2324     		sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
2325     
2326     		mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->req_alloc_dma);
2327     		if (mem == NULL)
2328     			goto out_fail;
2329     
2330     		memset(mem, 0, sz);
2331     		ioc->alloc_total += sz;
2332     		ioc->req_alloc = mem;
2333     		dprintk((KERN_INFO MYNAM ": %s.req_alloc    @ %p[%08x], sz=%d bytes\n",
2334     			 ioc->name, mem, ioc->req_alloc_dma, sz));
2335     
2336     		b = (unsigned long) mem;
2337     		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
2338     		aligned_mem = (u8 *) b;
2339     		ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem;
2340     		ioc->req_frames_dma =
2341     			(ioc->req_alloc_dma + (aligned_mem - mem));
2342     		aligned_mem_dma = ioc->req_frames_dma;
2343     
2344     		dprintk((KERN_INFO MYNAM ": %s.req_frames   @ %p[%08x]\n",
2345     			 ioc->name, aligned_mem, aligned_mem_dma));
2346     
2347     		for (i = 0; i < ioc->req_depth; i++) {
2348     			mf = (MPT_FRAME_HDR *) aligned_mem;
2349     
2350     			/*  Queue REQUESTs *internally*!  */
2351     			Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
2352     			aligned_mem += ioc->req_sz;
2353     		}
2354     
2355     #if defined(CONFIG_MTRR) && 0
2356     		/*
2357     		 *  Enable Write Combining MTRR for IOC's memory region.
2358     		 *  (at least as much as we can; "size and base must be
2359     		 *  multiples of 4 kiB"
2360     		 */
2361     		ioc->mtrr_reg = mtrr_add(ioc->req_alloc_dma,
2362     					 sz,
2363     					 MTRR_TYPE_WRCOMB, 1);
2364     		dprintk((KERN_INFO MYNAM ": %s: MTRR region registered (base:size=%08x:%x)\n",
2365     				ioc->name, ioc->req_alloc_dma,
2366     				sz ));
2367     #endif
2368     
2369     	}
2370     
2371     	if (ioc->sense_buf_pool == NULL) {
2372     		sz = (ioc->req_depth * 256);
2373     		ioc->sense_buf_pool =
2374     				pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
2375     		if (ioc->sense_buf_pool == NULL)
2376     			goto out_fail;
2377     
2378     		ioc->alloc_total += sz;
2379     	}
2380     
2381     	return 0;
2382     
2383     out_fail:
2384     	if (ioc->reply_alloc != NULL) {
2385     		sz = (ioc->reply_sz * ioc->reply_depth) + 128;
2386     		pci_free_consistent(ioc->pcidev,
2387     				sz,
2388     				ioc->reply_alloc, ioc->reply_alloc_dma);
2389     		ioc->reply_frames = NULL;
2390     		ioc->reply_alloc = NULL;
2391     		ioc->alloc_total -= sz;
2392     	}
2393     	if (ioc->req_alloc != NULL) {
2394     		sz = (ioc->req_sz * ioc->req_depth) + 128;
2395     		/*
2396     		 *  Rounding UP to nearest 4-kB boundary here...
2397     		 */
2398     		sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
2399     		pci_free_consistent(ioc->pcidev,
2400     				sz,
2401     				ioc->req_alloc, ioc->req_alloc_dma);
2402     #if defined(CONFIG_MTRR) && 0
2403     		if (ioc->mtrr_reg > 0) {
2404     			mtrr_del(ioc->mtrr_reg, 0, 0);
2405     			dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n",
2406     					ioc->name));
2407     		}
2408     #endif
2409     		ioc->req_frames = NULL;
2410     		ioc->req_alloc = NULL;
2411     		ioc->alloc_total -= sz;
2412     	}
2413     	if (ioc->sense_buf_pool != NULL) {
2414     		sz = (ioc->req_depth * 256);
2415     		pci_free_consistent(ioc->pcidev,
2416     				sz,
2417     				ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2418     		ioc->sense_buf_pool = NULL;
2419     	}
2420     	return -1;
2421     }
2422     
2423     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2424     /*
2425      *	HandShakeReqAndReply - Send MPT request to and receive reply from
2426      *	IOC via doorbell handshake method.
2427      *	@ioc: Pointer to MPT_ADAPTER structure
2428      *	@reqBytes: Size of the request in bytes
2429      *	@req: Pointer to MPT request frame
2430      *	@replyBytes: Expected size of the reply in bytes
2431      *	@u16reply: Pointer to area where reply should be written
2432      *	@maxwait: Max wait time for a reply (in seconds)
2433      *
2434      *	NOTES: It is the callers responsibility to byte-swap fields in the
2435      *	request which are greater than 1 byte in size.  It is also the
2436      *	callers responsibility to byte-swap response fields which are
2437      *	greater than 1 byte in size.
2438      *
2439      *	Returns 0 for success, non-zero for failure.
2440      */
2441     static int
2442     HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait)
2443     {
2444     	MPIDefaultReply_t *mptReply;
2445     	int failcnt = 0;
2446     	int t;
2447     
2448     	/*
2449     	 * Get ready to cache a handshake reply
2450     	 */
2451     	ioc->hs_reply_idx = 0;
2452     	mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
2453     	mptReply->MsgLength = 0;
2454     
2455     	/*
2456     	 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
2457     	 * then tell IOC that we want to handshake a request of N words.
2458     	 * (WRITE u32val to Doorbell reg).
2459     	 */
2460     	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2461     	CHIPREG_WRITE32(&ioc->chip->Doorbell,
2462     			((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
2463     			 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
2464     
2465     	/*
2466     	 * Wait for IOC's doorbell handshake int
2467     	 */
2468     	if ((t = WaitForDoorbellInt(ioc, 2)) < 0)
2469     		failcnt++;
2470     
2471     	dhsprintk((KERN_INFO MYNAM ": %s: HandShake request start, WaitCnt=%d%s\n",
2472     			ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
2473     
2474     	/*
2475     	 * Clear doorbell int (WRITE 0 to IntStatus reg),
2476     	 * then wait for IOC to ACKnowledge that it's ready for
2477     	 * our handshake request.
2478     	 */
2479     	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2480     	if (!failcnt && (t = WaitForDoorbellAck(ioc, 2)) < 0)
2481     		failcnt++;
2482     
2483     	if (!failcnt) {
2484     		int	 i;
2485     		u8	*req_as_bytes = (u8 *) req;
2486     
2487     		/*
2488     		 * Stuff request words via doorbell handshake,
2489     		 * with ACK from IOC for each.
2490     		 */
2491     		for (i = 0; !failcnt && i < reqBytes/4; i++) {
2492     			u32 word = ((req_as_bytes[(i*4) + 0] <<  0) |
2493     				    (req_as_bytes[(i*4) + 1] <<  8) |
2494     				    (req_as_bytes[(i*4) + 2] << 16) |
2495     				    (req_as_bytes[(i*4) + 3] << 24));
2496     
2497     			CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
2498     			if ((t = WaitForDoorbellAck(ioc, 2)) < 0)
2499     				failcnt++;
2500     		}
2501     
2502     		dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
2503     		DBG_DUMP_REQUEST_FRAME_HDR(req)
2504     
2505     		dhsprintk((KERN_INFO MYNAM ": %s: HandShake request post done, WaitCnt=%d%s\n",
2506     				ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
2507     
2508     		/*
2509     		 * Wait for completion of doorbell handshake reply from the IOC
2510     		 */
2511     		if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait)) < 0)
2512     			failcnt++;
2513     
2514     		/*
2515     		 * Copy out the cached reply...
2516     		 */
2517     		for(i=0; i < MIN(replyBytes/2,mptReply->MsgLength*2); i++)
2518     			u16reply[i] = ioc->hs_reply[i];
2519     	} else {
2520     		return -99;
2521     	}
2522     
2523     	return -failcnt;
2524     }
2525     
2526     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2527     /*
2528      *	WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
2529      *	in it's IntStatus register.
2530      *	@ioc: Pointer to MPT_ADAPTER structure
2531      *	@howlong: How long to wait (in seconds)
2532      *
2533      *	This routine waits (up to ~2 seconds max) for IOC doorbell
2534      *	handshake ACKnowledge.
2535      *
2536      *	Returns a negative value on failure, else wait loop count.
2537      */
2538     static int
2539     WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong)
2540     {
2541     	int cntdn = HZ * howlong;
2542     	int count = 0;
2543     	u32 intstat;
2544     
2545     	while (--cntdn) {
2546     		intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
2547     		if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
2548     			break;
2549     		current->state = TASK_INTERRUPTIBLE;
2550     		schedule_timeout(1);
2551     		count++;
2552     	}
2553     
2554     	if (cntdn) {
2555     		dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell ACK (cnt=%d)\n",
2556     				ioc->name, count));
2557     		return count;
2558     	}
2559     
2560     	printk(KERN_ERR MYNAM ": %s: ERROR - Doorbell ACK timeout(%d)!\n",
2561     			ioc->name, (count+5)/HZ);
2562     	return -1;
2563     }
2564     
2565     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2566     /*
2567      *	WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
2568      *	in it's IntStatus register.
2569      *	@ioc: Pointer to MPT_ADAPTER structure
2570      *	@howlong: How long to wait (in seconds)
2571      *
2572      *	This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
2573      *
2574      *	Returns a negative value on failure, else wait loop count.
2575      */
2576     static int
2577     WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong)
2578     {
2579     	int cntdn = HZ * howlong;
2580     	int count = 0;
2581     	u32 intstat;
2582     
2583     	while (--cntdn) {
2584     		intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
2585     		if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
2586     			break;
2587     		current->state = TASK_INTERRUPTIBLE;
2588     		schedule_timeout(1);
2589     		count++;
2590     	}
2591     
2592     	if (cntdn) {
2593     		dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell INT (cnt=%d)\n",
2594     				ioc->name, count));
2595     		return count;
2596     	}
2597     
2598     	printk(KERN_ERR MYNAM ": %s: ERROR - Doorbell INT timeout(%d)!\n",
2599     			ioc->name, (count+5)/HZ);
2600     	return -1;
2601     }
2602     
2603     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2604     /*
2605      *	WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
2606      *	@ioc: Pointer to MPT_ADAPTER structure
2607      *	@howlong: How long to wait (in seconds)
2608      *
2609      *	This routine polls the IOC for a handshake reply, 16 bits at a time.
2610      *	Reply is cached to IOC private area large enough to hold a maximum
2611      *	of 128 bytes of reply data.
2612      *
2613      *	Returns a negative value on failure, else size of reply in WORDS.
2614      */
2615     static int
2616     WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong)
2617     {
2618     	int u16cnt = 0;
2619     	int failcnt = 0;
2620     	int t;
2621     	u16 *hs_reply = ioc->hs_reply;
2622      	volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
2623     	u16 hword;
2624     
2625     	hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
2626     
2627     	/*
2628     	 * Get first two u16's so we can look at IOC's intended reply MsgLength
2629     	 */
2630     	u16cnt=0;
2631     	if ((t = WaitForDoorbellInt(ioc, howlong)) < 0) {
2632     		failcnt++;
2633     	} else {
2634     		hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
2635     		CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2636     		if ((t = WaitForDoorbellInt(ioc, 2)) < 0)
2637     			failcnt++;
2638     		else {
2639     			hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
2640     			CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2641     		}
2642     	}
2643     
2644     	dhsprintk((KERN_INFO MYNAM ": %s: First handshake reply word=%08x%s\n",
2645     			ioc->name, le32_to_cpu(*(u32 *)hs_reply),
2646     			failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
2647     
2648     	/*
2649     	 * If no error (and IOC said MsgLength is > 0), piece together
2650     	 * reply 16 bits at a time.
2651     	 */
2652     	for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
2653     		if ((t = WaitForDoorbellInt(ioc, 2)) < 0)
2654     			failcnt++;
2655     		hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
2656     		/* don't overflow our IOC hs_reply[] buffer! */
2657     		if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
2658     			hs_reply[u16cnt] = hword;
2659     		CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2660     	}
2661     
2662     	if (!failcnt && (t = WaitForDoorbellInt(ioc, 2)) < 0)
2663     		failcnt++;
2664     	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2665     
2666     	if (failcnt) {
2667     		printk(KERN_ERR MYNAM ": %s: ERROR - Handshake reply failure!\n",
2668     				ioc->name);
2669     		return -failcnt;
2670     	}
2671     #if 0
2672     	else if (u16cnt != (2 * mptReply->MsgLength)) {
2673     		return -101;
2674     	}
2675     	else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
2676     		return -102;
2677     	}
2678     #endif
2679     
2680     	dmfprintk((KERN_INFO MYNAM ": %s: Got Handshake reply:\n", ioc->name));
2681     	DBG_DUMP_REPLY_FRAME(mptReply)
2682     
2683     	dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell REPLY (sz=%d)\n",
2684     			ioc->name, u16cnt/2));
2685     	return u16cnt/2;
2686     }
2687     
2688     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2689     /*
2690      *	GetLanConfigPages - Fetch LANConfig pages.
2691      *	@ioc: Pointer to MPT_ADAPTER structure
2692      *
2693      *	Returns 0 for success, non-zero for failure.
2694      */
2695     static int
2696     GetLanConfigPages(MPT_ADAPTER *ioc)
2697     {
2698     	Config_t		 config_req;
2699     	ConfigReply_t		 config_reply;
2700     	LANPage0_t		*page0;
2701     	dma_addr_t		 page0_dma;
2702     	LANPage1_t		*page1;
2703     	dma_addr_t		 page1_dma;
2704     	int			 i;
2705     	int			 req_sz;
2706     	int			 reply_sz;
2707     	int			 data_sz;
2708     
2709     /* LANPage0 */
2710     	/*  Immediate destination (reply area)...  */
2711     	reply_sz = sizeof(config_reply);
2712     	memset(&config_reply, 0, reply_sz);
2713     
2714     	/*  Ultimate destination...  */
2715     	page0 = &ioc->lan_cnfg_page0;
2716     	data_sz = sizeof(*page0);
2717     	memset(page0, 0, data_sz);
2718     
2719     	/*  Request area (config_req on the stack right now!)  */
2720     	req_sz = sizeof(config_req);
2721     	memset(&config_req, 0, req_sz);
2722     	config_req.Function = MPI_FUNCTION_CONFIG;
2723     	config_req.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2724     	/*	config_req.Header.PageVersion = 0;	*/
2725     	/*	config_req.Header.PageLength = 0;	*/
2726     	config_req.Header.PageNumber = 0;
2727     	config_req.Header.PageType = MPI_CONFIG_PAGETYPE_LAN;
2728     	/*	config_req.PageAddress = 0;		*/
2729     	config_req.PageBufferSGE.u.Simple.FlagsLength = cpu_to_le32(
2730     			((MPI_SGE_FLAGS_LAST_ELEMENT |
2731     			  MPI_SGE_FLAGS_END_OF_BUFFER |
2732     			  MPI_SGE_FLAGS_END_OF_LIST |
2733     			  MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2734     			  MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2735     			  MPI_SGE_FLAGS_32_BIT_ADDRESSING |
2736     			  MPI_SGE_FLAGS_32_BIT_CONTEXT) << MPI_SGE_FLAGS_SHIFT) |
2737     			(u32)data_sz
2738     	);
2739     	page0_dma = pci_map_single(ioc->pcidev, page0, data_sz, PCI_DMA_FROMDEVICE);
2740     	config_req.PageBufferSGE.u.Simple.u.Address32 = cpu_to_le32(page0_dma);
2741     
2742     	dprintk((KERN_INFO MYNAM ": %s: Sending Config request LAN_PAGE_0\n",
2743     			ioc->name));
2744     
2745     	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&config_req,
2746     				reply_sz, (u16*)&config_reply, 3);
2747     	pci_unmap_single(ioc->pcidev, page0_dma, data_sz, PCI_DMA_FROMDEVICE);
2748     	if (i != 0)
2749     		return i;
2750     
2751     	/*  Now byte swap the necessary LANPage0 fields  */
2752     
2753     /* LANPage1 */
2754     	/*  Immediate destination (reply area)...  */
2755     	reply_sz = sizeof(config_reply);
2756     	memset(&config_reply, 0, reply_sz);
2757     
2758     	/*  Ultimate destination...  */
2759     	page1 = &ioc->lan_cnfg_page1;
2760     	data_sz = sizeof(*page1);
2761     	memset(page1, 0, data_sz);
2762     
2763     	/*  Request area (config_req on the stack right now!)  */
2764     	req_sz = sizeof(config_req);
2765     	memset(&config_req, 0, req_sz);
2766     	config_req.Function = MPI_FUNCTION_CONFIG;
2767     	config_req.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2768     	/*	config_req.Header.PageVersion = 0;	*/
2769     	/*	config_req.Header.PageLength = 0;	*/
2770     	config_req.Header.PageNumber = 1;
2771     	config_req.Header.PageType = MPI_CONFIG_PAGETYPE_LAN;
2772     	/*	config_req.PageAddress = 0;		*/
2773     	config_req.PageBufferSGE.u.Simple.FlagsLength = cpu_to_le32(
2774     			((MPI_SGE_FLAGS_LAST_ELEMENT |
2775     			  MPI_SGE_FLAGS_END_OF_BUFFER |
2776     			  MPI_SGE_FLAGS_END_OF_LIST |
2777     			  MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2778     			  MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2779     			  MPI_SGE_FLAGS_32_BIT_ADDRESSING |
2780     			  MPI_SGE_FLAGS_32_BIT_CONTEXT) << MPI_SGE_FLAGS_SHIFT) |
2781     			(u32)data_sz
2782     	);
2783     	page1_dma = pci_map_single(ioc->pcidev, page1, data_sz, PCI_DMA_FROMDEVICE);
2784     	config_req.PageBufferSGE.u.Simple.u.Address32 = cpu_to_le32(page1_dma);
2785     
2786     	dprintk((KERN_INFO MYNAM ": %s: Sending Config request LAN_PAGE_1\n",
2787     			ioc->name));
2788     
2789     	i = HandShakeReqAndReply(ioc, req_sz, (u32*)&config_req,
2790     				reply_sz, (u16*)&config_reply, 3);
2791     	pci_unmap_single(ioc->pcidev, page1_dma, data_sz, PCI_DMA_FROMDEVICE);
2792     	if (i != 0)
2793     		return i;
2794     
2795     	/*  Now byte swap the necessary LANPage1 fields  */
2796     
2797     	return 0;
2798     }
2799     
2800     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2801     /**
2802      *	SendEventNotification - Send EventNotification (on or off) request
2803      *	to MPT adapter.
2804      *	@ioc: Pointer to MPT_ADAPTER structure
2805      *	@EvSwitch: Event switch flags
2806      */
2807     static int
2808     SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
2809     {
2810     	EventNotification_t	*evnp;
2811     
2812     	evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc->id);
2813     	if (evnp == NULL) {
2814     		dprintk((KERN_WARNING MYNAM ": %s: WARNING - Unable to allocate a event request frame!\n",
2815     				ioc->name));
2816     		return 0;
2817     	}
2818     	memset(evnp, 0, sizeof(*evnp));
2819     
2820     	dprintk((KERN_INFO MYNAM ": %s: Sending EventNotification(%d)\n", ioc->name, EvSwitch));
2821     
2822     	evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
2823     	evnp->ChainOffset = 0;
2824     	evnp->MsgFlags = 0;
2825     	evnp->Switch = EvSwitch;
2826     
2827     	mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)evnp);
2828     
2829     	return 0;
2830     }
2831     
2832     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2833     /**
2834      *	SendEventAck - Send EventAck request to MPT adapter.
2835      *	@ioc: Pointer to MPT_ADAPTER structure
2836      *	@evnp: Pointer to original EventNotification request
2837      */
2838     static int
2839     SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
2840     {
2841     	EventAck_t	*pAck;
2842     
2843     	if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
2844     		printk(KERN_WARNING MYNAM ": %s: WARNING - Unable to allocate event ACK request frame!\n",
2845     				ioc->name);
2846     		return -1;
2847     	}
2848     	memset(pAck, 0, sizeof(*pAck));
2849     
2850     	dprintk((KERN_INFO MYNAM ": %s: Sending EventAck\n", ioc->name));
2851     
2852     	pAck->Function     = MPI_FUNCTION_EVENT_ACK;
2853     	pAck->ChainOffset  = 0;
2854     	pAck->MsgFlags     = 0;
2855     	pAck->Event        = evnp->Event;
2856     	pAck->EventContext = evnp->EventContext;
2857     
2858     	mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)pAck);
2859     
2860     	return 0;
2861     }
2862     
2863     #ifdef CONFIG_PROC_FS		/* { */
2864     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2865     /*
2866      *	procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
2867      */
2868     
2869     #define PROC_MPT_READ_RETURN(page,start,off,count,eof,len) \
2870     { \
2871     	len -= off;			\
2872     	if (len < count) {		\
2873     		*eof = 1;		\
2874     		if (len <= 0)		\
2875     			return 0;	\
2876     	} else				\
2877     		len = count;		\
2878     	*start = page + off;		\
2879     	return len;			\
2880     }
2881     
2882     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2883     /*
2884      *	procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
2885      *
2886      *	Returns 0 for success, non-zero for failure.
2887      */
2888     static int
2889     procmpt_create(void)
2890     {
2891     	MPT_ADAPTER *ioc;
2892     	struct proc_dir_entry *ent;
2893     	int errcnt = 0;
2894     
2895     	/*
2896     	 * 	BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
2897     	 * 	(single level) to multi level (e.g. "driver/message/fusion")
2898     	 * 	something here needs to change.  -sralston
2899     	 */
2900     	procmpt_root_dir = CREATE_PROCDIR_ENTRY(MPT_PROCFS_MPTBASEDIR, NULL);
2901     	if (procmpt_root_dir == NULL)
2902     		return -ENOTDIR;
2903     
2904     	if ((ioc = mpt_adapter_find_first()) != NULL) {
2905     		ent = create_proc_read_entry(MPT_PROCFS_SUMMARY_NODE, 0, NULL, procmpt_read_summary, NULL);
2906     		if (ent == NULL) {
2907     			printk(KERN_WARNING MYNAM ": WARNING - Could not create %s entry!\n",
2908     					MPT_PROCFS_SUMMARY_PATHNAME);
2909     			errcnt++;
2910     		}
2911     	}
2912     
2913     	while (ioc != NULL) {
2914     		char pname[32];
2915     		int namelen;
2916     		/*
2917     		 *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
2918     		 */
2919     		namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
2920     		if ((ent = CREATE_PROCDIR_ENTRY(pname, NULL)) != NULL) {
2921     			/*
2922     			 *  And populate it with: "summary" and "dbg" file entries.
2923     			 */
2924     			(void) sprintf(pname+namelen, "/summary");
2925     			ent = create_proc_read_entry(pname, 0, NULL, procmpt_read_summary, ioc);
2926     			if (ent == NULL) {
2927     				errcnt++;
2928     				printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
2929     						ioc->name, pname);
2930     			}
2931     //#ifdef MPT_DEBUG
2932     			/* DEBUG aid! */
2933     			(void) sprintf(pname+namelen, "/dbg");
2934     			ent = create_proc_read_entry(pname, 0, NULL, procmpt_read_dbg, ioc);
2935     			if (ent == NULL) {
2936     				errcnt++;
2937     				printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
2938     						ioc->name, pname);
2939     			}
2940     //#endif
2941     		} else {
2942     			errcnt++;
2943     			printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
2944     					ioc->name, pname);
2945     
2946     		}
2947     
2948     		ioc = mpt_adapter_find_next(ioc);
2949     	}
2950     
2951     	if (errcnt) {
2952     //		remove_proc_entry("mpt", 0);
2953     		return -ENOTDIR;
2954     	}
2955     
2956     	return 0;
2957     }
2958     
2959     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2960     /*
2961      *	procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
2962      *
2963      *	Returns 0 for success, non-zero for failure.
2964      */
2965     static int
2966     procmpt_destroy(void)
2967     {
2968     	MPT_ADAPTER *ioc;
2969     
2970     	if (!procmpt_root_dir)
2971     		return 0;
2972     
2973     	/*
2974     	 * 	BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
2975     	 * 	(single level) to multi level (e.g. "driver/message/fusion")
2976     	 * 	something here needs to change.  -sralston
2977     	 */
2978     
2979     	ioc = mpt_adapter_find_first();
2980     	if (ioc != NULL) {
2981     		remove_proc_entry(MPT_PROCFS_SUMMARY_NODE, 0);
2982     	}
2983     
2984     	while (ioc != NULL) {
2985     		char pname[32];
2986     		int namelen;
2987     		/*
2988     		 *  Tear down each "/proc/mpt/iocN" subdirectory.
2989     		 */
2990     		namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
2991     		(void) sprintf(pname+namelen, "/summary");
2992     		remove_proc_entry(pname, 0);
2993     //#ifdef MPT_DEBUG
2994     		(void) sprintf(pname+namelen, "/dbg");
2995     		remove_proc_entry(pname, 0);
2996     //#endif
2997     		(void) sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
2998     		remove_proc_entry(pname, 0);
2999     
3000     		ioc = mpt_adapter_find_next(ioc);
3001     	}
3002     
3003     	if (atomic_read((atomic_t *)&procmpt_root_dir->count) == 0) {
3004     		remove_proc_entry(MPT_PROCFS_MPTBASEDIR, 0);
3005     		procmpt_root_dir = NULL;
3006     		return 0;
3007     	}
3008     
3009     	return -1;
3010     }
3011     
3012     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3013     /**
3014      *	procmpt_read_summary - Handle read request from /proc/mpt/summary
3015      *	or from /proc/mpt/iocN/summary.
3016      *	@page: Pointer to area to write information
3017      *	@start: Pointer to start pointer
3018      *	@off: Offset to start writing
3019      *	@count: 
3020      *	@eof: Pointer to EOF integer
3021      *	@data: Pointer 
3022      *
3023      *	Returns numbers of characters written to process performing the read.
3024      */
3025     static int
3026     procmpt_read_summary(char *page, char **start, off_t off, int count, int *eof, void *data)
3027     {
3028     	MPT_ADAPTER *ioc;
3029     	char *out = page;
3030     	int len;
3031     
3032     	if (data == NULL)
3033     		ioc = mpt_adapter_find_first();
3034     	else
3035     		ioc = data;
3036     
3037     // Too verbose!
3038     //	out += sprintf(out, "Attached Fusion MPT I/O Controllers:%s\n", ioc ? "" : " none");
3039     
3040     	while (ioc) {
3041     		int	more = 0;
3042     
3043     // Too verbose!
3044     //		mpt_print_ioc_facts(ioc, out, &more, 0);
3045     		mpt_print_ioc_summary(ioc, out, &more, 0, 1);
3046     
3047     		out += more;
3048     		if ((out-page) >= count) {
3049     			break;
3050     		}
3051     
3052     		if (data == NULL)
3053     			ioc = mpt_adapter_find_next(ioc);
3054     		else
3055     			ioc = NULL;				/* force exit for iocN */
3056     	}
3057     	len = out - page;
3058     
3059     	PROC_MPT_READ_RETURN(page,start,off,count,eof,len);
3060     }
3061     
3062     // debug aid!
3063     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3064     /**
3065      *	procmpt_read_dbg - Handle read request from /proc/mpt/iocN/dbg.
3066      *	@page: Pointer to area to write information
3067      *	@start: Pointer to start pointer
3068      *	@off: Offset to start writing
3069      *	@count: 
3070      *	@eof: Pointer to EOF integer
3071      *	@data: Pointer 
3072      *
3073      *	Returns numbers of characters written to process performing the read.
3074      */
3075     static int
3076     procmpt_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data)
3077     {
3078     	MPT_ADAPTER *ioc;
3079     	char *out = page;
3080     	int len;
3081     
3082     	ioc = data;
3083     
3084     	while (ioc) {
3085     		int	more = 0;
3086     
3087     		mpt_print_ioc_facts(ioc, out, &more, 0);
3088     
3089     		out += more;
3090     		if ((out-page) >= count) {
3091     			break;
3092     		}
3093     		ioc = NULL;
3094     	}
3095     	len = out - page;
3096     
3097     	PROC_MPT_READ_RETURN(page,start,off,count,eof,len);
3098     }
3099     #endif		/* CONFIG_PROC_FS } */
3100     
3101     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3102     static void
3103     mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
3104     {
3105     	if ((ioc->facts.FWVersion & 0xF000) == 0xE000)
3106     		sprintf(buf, " (Exp %02d%02d)",
3107     			(ioc->facts.FWVersion & 0x0F00) >> 8,	/* Month */
3108     			ioc->facts.FWVersion & 0x001F);		/* Day */
3109     	else
3110     		buf[0] ='\0';
3111     
3112     	/* insider hack! */
3113     	if (ioc->facts.FWVersion & 0x0080) {
3114     		strcat(buf, " [MDBG]");
3115     	}
3116     }
3117     
3118     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3119     /**
3120      *	mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
3121      *	@ioc: Pointer to MPT_ADAPTER structure
3122      *	@buffer: Pointer to buffer where IOC summary info should be written
3123      *	@size: Pointer to number of bytes we wrote (set by this routine)
3124      *	@len: Offset at which to start writing in buffer
3125      *	@showlan: Display LAN stuff?
3126      *
3127      * 	This routine writes (english readable) ASCII text, which represents
3128      * 	a summary of IOC information, to a buffer.
3129      */
3130     void
3131     mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
3132     {
3133     	char expVer[32];
3134     	int y;
3135     
3136     	mpt_get_fw_exp_ver(expVer, ioc);
3137     
3138     	/*
3139     	 *  Shorter summary of attached ioc's...
3140     	 */
3141     	y = sprintf(buffer+len, "%s: %s, %s%04xh%s, Ports=%d, MaxQ=%d",
3142     			ioc->name,
3143     			ioc->prod_name,
3144     			MPT_FW_REV_MAGIC_ID_STRING,	/* "FwRev=" or somesuch */
3145     			ioc->facts.FWVersion,
3146     			expVer,
3147     			ioc->facts.NumberOfPorts,
3148     			ioc->req_depth);
3149     
3150     	if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
3151     		u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
3152     		y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
3153     			a[5], a[4], a[3], a[2], a[1], a[0]);
3154     	}
3155     
3156     	if (ioc->pci_irq < 100)
3157     		y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
3158     
3159     	if (!ioc->active)
3160     		y += sprintf(buffer+len+y, " (disabled)");
3161     
3162     	y += sprintf(buffer+len+y, "\n");
3163     
3164     	*size = y;
3165     }
3166     
3167     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3168     /**
3169      *	mpt_print_ioc_facts - Write ASCII summary of IOC facts to a buffer.
3170      *	@ioc: Pointer to MPT_ADAPTER structure
3171      *	@buffer: Pointer to buffer where IOC facts should be written
3172      *	@size: Pointer to number of bytes we wrote (set by this routine)
3173      *	@len: Offset at which to start writing in buffer
3174      *
3175      * 	This routine writes (english readable) ASCII text, which represents
3176      * 	a summary of the IOC facts, to a buffer.
3177      */
3178     void
3179     mpt_print_ioc_facts(MPT_ADAPTER *ioc, char *buffer, int *size, int len)
3180     {
3181     	char expVer[32];
3182     	char iocName[16];
3183     	int sz;
3184     	int y;
3185     	int p;
3186     
3187     	mpt_get_fw_exp_ver(expVer, ioc);
3188     
3189     	strcpy(iocName, ioc->name);
3190     	y = sprintf(buffer+len, "%s:\n", iocName);
3191     
3192     	y += sprintf(buffer+len+y, "  ProductID = 0x%04x\n", ioc->facts.ProductID);
3193     	for (p=0; p < ioc->facts.NumberOfPorts; p++) {
3194     		y += sprintf(buffer+len+y, "  PortNumber = %d (of %d)\n",
3195     			p+1,
3196     			ioc->facts.NumberOfPorts);
3197     		if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
3198     			u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
3199     			y += sprintf(buffer+len+y, "  LanAddr = 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
3200     				a[5], a[4], a[3], a[2], a[1], a[0]);
3201     		}
3202     	}
3203     	y += sprintf(buffer+len+y, "  FWVersion = 0x%04x%s\n", ioc->facts.FWVersion, expVer);
3204     	y += sprintf(buffer+len+y, "  MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
3205     	y += sprintf(buffer+len+y, "  FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
3206     	y += sprintf(buffer+len+y, "  EventState = 0x%02x\n", ioc->facts.EventState);
3207     	y += sprintf(buffer+len+y, "  CurrentHostMfaHighAddr = 0x%08x\n",
3208     		 	ioc->facts.CurrentHostMfaHighAddr);
3209     	y += sprintf(buffer+len+y, "  CurrentSenseBufferHighAddr = 0x%08x\n",
3210     			ioc->facts.CurrentSenseBufferHighAddr);
3211     	y += sprintf(buffer+len+y, "  MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
3212     	y += sprintf(buffer+len+y, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
3213     
3214     	y += sprintf(buffer+len+y, "  RequestFrames @ 0x%p (Dma @ 0x%08x)\n",
3215     					ioc->req_alloc, ioc->req_alloc_dma);
3216     	/*
3217     	 *  Rounding UP to nearest 4-kB boundary here...
3218     	 */
3219     	sz = (ioc->req_sz * ioc->req_depth) + 128;
3220     	sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
3221     	y += sprintf(buffer+len+y, "    {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
3222     					ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
3223     	y += sprintf(buffer+len+y, "    {MaxReqSz=%d}   {MaxReqDepth=%d}\n",
3224     					4*ioc->facts.RequestFrameSize,
3225     					ioc->facts.GlobalCredits);
3226     
3227     	y += sprintf(buffer+len+y, "  ReplyFrames   @ 0x%p (Dma @ 0x%08x)\n",
3228     					ioc->reply_alloc, ioc->reply_alloc_dma);
3229     	sz = (ioc->reply_sz * ioc->reply_depth) + 128;
3230     	y += sprintf(buffer+len+y, "    {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
3231     					ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
3232     	y += sprintf(buffer+len+y, "    {MaxRepSz=%d}   {MaxRepDepth=%d}\n",
3233     					ioc->facts.CurReplyFrameSize,
3234     					ioc->facts.ReplyQueueDepth);
3235     
3236     	*size = y;
3237     }
3238     
3239     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3240     static char *
3241     EventDescriptionStr(u8 event, u32 evData0)
3242     {
3243     	char *ds = NULL;
3244     
3245     	switch(event) {
3246     	case MPI_EVENT_NONE:
3247     		ds = "None";
3248     		break;
3249     	case MPI_EVENT_LOG_DATA:
3250     		ds = "Log Data";
3251     		break;
3252     	case MPI_EVENT_STATE_CHANGE:
3253     		ds = "State Change";
3254     		break;
3255     	case MPI_EVENT_UNIT_ATTENTION:
3256     		ds = "Unit Attention";
3257     		break;
3258     	case MPI_EVENT_IOC_BUS_RESET:
3259     		ds = "IOC Bus Reset";
3260     		break;
3261     	case MPI_EVENT_EXT_BUS_RESET:
3262     		ds = "External Bus Reset";
3263     		break;
3264     	case MPI_EVENT_RESCAN:
3265     		ds = "Bus Rescan Event"; 
3266     		/* Ok, do we need to do anything here? As far as
3267     		   I can tell, this is when a new device gets added
3268     		   to the loop. */
3269     		break;
3270     	case MPI_EVENT_LINK_STATUS_CHANGE:
3271     		if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
3272     			ds = "Link Status(FAILURE) Change";
3273     		else
3274     			ds = "Link Status(ACTIVE) Change";
3275     		break;
3276     	case MPI_EVENT_LOOP_STATE_CHANGE:
3277     		if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
3278     			ds = "Loop State(LIP) Change";
3279     		else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
3280     			ds = "Loop State(LPE) Change";			/* ??? */
3281     		else
3282     			ds = "Loop State(LPB) Change";			/* ??? */
3283     		break;
3284     	case MPI_EVENT_LOGOUT:
3285     		ds = "Logout";
3286     		break;
3287     	case MPI_EVENT_EVENT_CHANGE:
3288     		if (evData0)
3289     			ds = "Events(ON) Change";
3290     		else
3291     			ds = "Events(OFF) Change";
3292     		break;
3293     	/*
3294     	 *  MPT base "custom" events may be added here...
3295     	 */
3296     	default:
3297     		ds = "Unknown";
3298     		break;
3299     	}
3300     	return ds;
3301     }
3302     
3303     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3304     /**
3305      *	ProcessEventNotification - Route a received EventNotificationReply to
3306      *	all currently regeistered event handlers.
3307      *	@ioc: Pointer to MPT_ADAPTER structure
3308      *	@pEventReply: Pointer to EventNotification reply frame
3309      *	@evHandlers: Pointer to integer, number of event handlers
3310      *
3311      *	Returns sum of event handlers return values.
3312      */
3313     static int
3314     ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
3315     {
3316     	u16 evDataLen;
3317     	u32 evData0 = 0;
3318     //	u32 evCtx;
3319     	int i;
3320     	int r = 0;
3321     	int handlers = 0;
3322     	char *evStr;
3323     	u8 event;
3324     
3325     	/*
3326     	 *  Do platform normalization of values
3327     	 */
3328     	event = le32_to_cpu(pEventReply->Event) & 0xFF;
3329     //	evCtx = le32_to_cpu(pEventReply->EventContext);
3330     	evDataLen = le16_to_cpu(pEventReply->EventDataLength);
3331     	if (evDataLen) {
3332     		evData0 = le32_to_cpu(pEventReply->Data[0]);
3333     	}
3334     
3335     	evStr = EventDescriptionStr(event, evData0);
3336     	dprintk((KERN_INFO MYNAM ": %s: MPT event (%s=%02Xh) detected!\n",
3337     			ioc->name,
3338     			evStr,
3339     			event));
3340     
3341     #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
3342     	printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
3343     	for (i = 0; i < evDataLen; i++)
3344     		printk(" %08x", le32_to_cpu(pEventReply->Data[i]));
3345     	printk("\n");
3346     #endif
3347     
3348     	/*
3349     	 *  Do general / base driver event processing
3350     	 */
3351     	switch(event) {
3352     	case MPI_EVENT_NONE:			/* 00 */
3353     	case MPI_EVENT_LOG_DATA:		/* 01 */
3354     	case MPI_EVENT_STATE_CHANGE:		/* 02 */
3355     	case MPI_EVENT_UNIT_ATTENTION:		/* 03 */
3356     	case MPI_EVENT_IOC_BUS_RESET:		/* 04 */
3357     	case MPI_EVENT_EXT_BUS_RESET:		/* 05 */
3358     	case MPI_EVENT_RESCAN:			/* 06 */
3359     	case MPI_EVENT_LINK_STATUS_CHANGE:	/* 07 */
3360     	case MPI_EVENT_LOOP_STATE_CHANGE:	/* 08 */
3361     	case MPI_EVENT_LOGOUT:			/* 09 */
3362     	default:
3363     		break;
3364     	case MPI_EVENT_EVENT_CHANGE:		/* 0A */
3365     		if (evDataLen) {
3366     			u8 evState = evData0 & 0xFF;
3367     
3368     			/* CHECKME! What if evState unexpectedly says OFF (0)? */
3369     
3370     			/* Update EventState field in cached IocFacts */
3371     			if (ioc->facts.Function) {
3372     				ioc->facts.EventState = evState;
3373     			}
3374     		}
3375     		break;
3376     	}
3377     
3378     	/*
3379     	 *  Call each currently registered protocol event handler.
3380     	 */
3381     	for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
3382     		if (MptEvHandlers[i]) {
3383     			dprintk((KERN_INFO MYNAM ": %s: Routing Event to event handler #%d\n",
3384     					ioc->name, i));
3385     			r += (*(MptEvHandlers[i]))(ioc, pEventReply);
3386     			handlers++;
3387     		}
3388     	}
3389     	/* FIXME?  Examine results here? */
3390     
3391     	/*
3392     	 *  If needed, send (a single) EventAck.
3393     	 */
3394     	if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
3395     		if ((i = SendEventAck(ioc, pEventReply)) != 0) {
3396     		}
3397     	}
3398     
3399     	*evHandlers = handlers;
3400     	return r;
3401     }
3402     
3403     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3404     /*
3405      *	mpt_fc_log_info - Log information returned from Fibre Channel IOC.
3406      *	@ioc: Pointer to MPT_ADAPTER structure
3407      *	@log_info: U32 LogInfo reply word from the IOC
3408      *
3409      *	Refer to lsi/fc_log.h.
3410      */
3411     static void
3412     mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
3413     {
3414     	static char *subcl_str[8] = {
3415     		"FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
3416     		"FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
3417     	};
3418     	char *desc = "unknown";
3419     	u8 subcl = (log_info >> 24) & 0x7;
3420     	u32 SubCl = log_info & 0x27000000;
3421     
3422     	switch(log_info) {
3423     /* FCP Initiator */
3424         	case MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME:
3425     		desc = "Received an out of order frame - unsupported";
3426     		break;
3427     	case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME:
3428     		desc = "Bad start of frame primative";
3429     		break;
3430     	case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME:
3431     		desc = "Bad end of frame primative";
3432     		break;
3433     	case MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN:
3434     		desc = "Receiver hardware detected overrun";
3435     		break;
3436     	case MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER:
3437     		desc = "Other errors caught by IOC which require retries";
3438     		break;
3439     	case MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD:
3440     		desc = "Main processor could not initialize sub-processor";
3441     		break;
3442     /* FC Target */
3443     	case MPI_IOCLOGINFO_FC_TARGET_NO_PDISC:
3444     		desc = "Not sent because we are waiting for a PDISC from the initiator";
3445     		break;
3446     	case MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN:
3447     		desc = "Not sent because we are not logged in to the remote node";
3448     		break;
3449     	case MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP:
3450     		desc = "Data Out, Auto Response, not sent due to a LIP";
3451     		break;
3452     	case MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP:
3453     		desc = "Data In, Auto Response, not sent due to a LIP";
3454     		break;
3455     	case MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA:
3456     		desc = "Data In, Auto Response, missing data frames";
3457     		break;
3458     	case MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP:
3459     		desc = "Data Out, No Response, not sent due to a LIP";
3460     		break;
3461     	case MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP:
3462     		desc = "Auto-response after a write not sent due to a LIP";
3463     		break;
3464     	case MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP:
3465     		desc = "Data In, No Response, not completed due to a LIP";
3466     		break;
3467     	case MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA:
3468     		desc = "Data In, No Response, missing data frames";
3469     		break;
3470     	case MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP:
3471     		desc = "Manual Response not sent due to a LIP";
3472     		break;
3473     	case MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3:
3474     		desc = "Not sent because remote node does not support Class 3";
3475     		break;
3476     	case MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID:
3477     		desc = "Not sent because login to remote node not validated";
3478     		break;
3479     	case MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND:
3480     		desc = "Cleared from the outbound after a logout";
3481     		break;
3482     	case MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN:
3483     		desc = "Cleared waiting for data after a logout";
3484     		break;
3485     /* LAN */
3486     	case MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING:
3487     		desc = "Transaction Context Sgl Missing";
3488     		break;
3489     	case MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE:
3490     		desc = "Transaction Context found before an EOB";
3491     		break;
3492     	case MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET:
3493     		desc = "Transaction Context value has reserved bits set";
3494     		break;
3495     	case MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG:
3496     		desc = "Invalid SGL Flags";
3497     		break;
3498     /* FC Link */
3499     	case MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT:
3500     		desc = "Loop initialization timed out";
3501     		break;
3502     	case MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED:
3503     		desc = "Another system controller already initialized the loop";
3504     		break;
3505     	case MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED:
3506     		desc = "Not synchronized to signal or still negotiating (possible cable problem)";
3507     		break;
3508     	case MPI_IOCLOGINFO_FC_LINK_CRC_ERROR:
3509     		desc = "CRC check detected error on received frame";
3510     		break;
3511     	}
3512     
3513     	printk(KERN_INFO MYNAM ": %s: LogInfo(0x%08x): SubCl={%s}",
3514     			ioc->name, log_info, subcl_str[subcl]);
3515     	if (SubCl == MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET)
3516     		printk(", byte_offset=%d\n", log_info & MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET);
3517     	else if (SubCl == MPI_IOCLOGINFO_FC_STATE_CHANGE)
3518     		printk("\n");		/* StateChg in LogInfo & 0x00FFFFFF, above */
3519     	else
3520     		printk("\n" KERN_INFO " %s\n", desc);
3521     }
3522     
3523     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3524     /*
3525      *	mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
3526      *	@ioc: Pointer to MPT_ADAPTER structure
3527      *	@mr: Pointer to MPT reply frame
3528      *	@log_info: U32 LogInfo word from the IOC
3529      *
3530      *	Refer to lsi/sp_log.h.
3531      */
3532     static void
3533     mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
3534     {
3535     	/* FIXME! */
3536     	printk(KERN_INFO MYNAM ": %s: LogInfo(0x%08x)\n", ioc->name, log_info);
3537     }
3538     
3539     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3540     /**
3541      *	mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI
3542      *	OpCode strings from the (optional) isense module.
3543      *	@ascqTable: Pointer to ASCQ_Table_t structure
3544      *	@ascqtbl_sz: Number of entries in ASCQ_Table
3545      *	@opsTable: Pointer to array of SCSI OpCode strings (char pointers)
3546      *
3547      *	Specialized driver registration routine for the isense driver.
3548      */
3549     int
3550     mpt_register_ascqops_strings(/*ASCQ_Table_t*/void *ascqTable, int ascqtbl_sz, const char **opsTable)
3551     {
3552     	int r = 0;
3553     
3554     	if (ascqTable && ascqtbl_sz && opsTable) {
3555     		mpt_v_ASCQ_TablePtr = ascqTable;
3556     		mpt_ASCQ_TableSz = ascqtbl_sz;
3557     		mpt_ScsiOpcodesPtr = opsTable;
3558     		printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n");
3559     		r = 1;
3560     	}
3561     	MOD_INC_USE_COUNT;
3562     	return r;
3563     }
3564     
3565     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3566     /**
3567      *	mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI
3568      *	OpCode strings from the isense driver.
3569      *
3570      *	Specialized driver deregistration routine for the isense driver.
3571      */
3572     void
3573     mpt_deregister_ascqops_strings(void)
3574     {
3575     	mpt_v_ASCQ_TablePtr = NULL;
3576     	mpt_ASCQ_TableSz = 0;
3577     	mpt_ScsiOpcodesPtr = NULL;
3578     	printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
3579     	MOD_DEC_USE_COUNT;
3580     }
3581     
3582     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3583     
3584     EXPORT_SYMBOL(mpt_register);
3585     EXPORT_SYMBOL(mpt_deregister);
3586     EXPORT_SYMBOL(mpt_event_register);
3587     EXPORT_SYMBOL(mpt_event_deregister);
3588     EXPORT_SYMBOL(mpt_reset_register);
3589     EXPORT_SYMBOL(mpt_reset_deregister);
3590     EXPORT_SYMBOL(mpt_get_msg_frame);
3591     EXPORT_SYMBOL(mpt_put_msg_frame);
3592     EXPORT_SYMBOL(mpt_free_msg_frame);
3593     EXPORT_SYMBOL(mpt_send_handshake_request);
3594     EXPORT_SYMBOL(mpt_adapter_find_first);
3595     EXPORT_SYMBOL(mpt_adapter_find_next);
3596     EXPORT_SYMBOL(mpt_verify_adapter);
3597     EXPORT_SYMBOL(mpt_print_ioc_summary);
3598     EXPORT_SYMBOL(mpt_lan_index);
3599     EXPORT_SYMBOL(mpt_stm_index);
3600     
3601     EXPORT_SYMBOL(mpt_register_ascqops_strings);
3602     EXPORT_SYMBOL(mpt_deregister_ascqops_strings);
3603     EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr);
3604     EXPORT_SYMBOL(mpt_ASCQ_TableSz);
3605     EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
3606     
3607     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3608     /**
3609      *	fusion_init - Fusion MPT base driver initialization routine.
3610      *
3611      *	Returns 0 for success, non-zero for failure.
3612      */
3613     int __init fusion_init(void)
3614     {
3615     	int i;
3616     
3617     	if (FusionInitCalled++) {
3618     		dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n"));
3619     		return 0;
3620     	}
3621     
3622     	show_mptmod_ver(my_NAME, my_VERSION);
3623     	printk(KERN_INFO COPYRIGHT "\n");
3624     
3625     	Q_INIT(&MptAdapters, MPT_ADAPTER);			/* set to empty */
3626     	for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
3627     		MptCallbacks[i] = NULL;
3628     		MptDriverClass[i] = MPTUNKNOWN_DRIVER;
3629     		MptEvHandlers[i] = NULL;
3630     		MptResetHandlers[i] = NULL;
3631     	}
3632     
3633     	/* NEW!  20010120 -sralston
3634     	 *  Register ourselves (mptbase) in order to facilitate
3635     	 *  EventNotification handling.
3636     	 */
3637     	mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
3638     
3639     	if ((i = mpt_pci_scan()) < 0)
3640     		return i;
3641     
3642     	return 0;
3643     }
3644     
3645     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3646     /**
3647      *	fusion_exit - Perform driver unload cleanup.
3648      *
3649      *	This routine frees all resources associated with each MPT adapter
3650      *	and removes all %MPT_PROCFS_MPTBASEDIR entries.
3651      */
3652     static void fusion_exit(void)
3653     {
3654     	MPT_ADAPTER *this;
3655     
3656     	dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
3657     
3658     	/* Whups?  20010120 -sralston
3659     	 *  Moved this *above* removal of all MptAdapters!
3660     	 */
3661     #ifdef CONFIG_PROC_FS
3662     	procmpt_destroy();
3663     #endif
3664     
3665     	while (! Q_IS_EMPTY(&MptAdapters)) {
3666     		this = MptAdapters.head;
3667     		Q_DEL_ITEM(this);
3668     		mpt_adapter_dispose(this);
3669     	}
3670     }
3671     
3672     /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3673     
3674     module_init(fusion_init);
3675     module_exit(fusion_exit);
3676