This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / 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  *      A special thanks to Pamela Delaney (LSI Logic) for tons of work
24  *      and countless enhancements while adding support for the 1030
25  *      chip family.  Pam has been instrumental in the development of
26  *      of the 2.xx.xx series fusion drivers, and her contributions are
27  *      far too numerous to hope to list in one place.
28  *
29  *      All manner of help from Stephen Shirron (LSI Logic):
30  *      low-level FC analysis, debug + various fixes in FCxx firmware,
31  *      initial port to alpha platform, various driver code optimizations,
32  *      being a faithful sounding board on all sorts of issues & ideas,
33  *      etc.
34  *
35  *      A huge debt of gratitude is owed to David S. Miller (DaveM)
36  *      for fixing much of the stupid and broken stuff in the early
37  *      driver while porting to sparc64 platform.  THANK YOU!
38  *
39  *      Special thanks goes to the I2O LAN driver people at the
40  *      University of Helsinki, who, unbeknownst to them, provided
41  *      the inspiration and initial structure for this driver.
42  *
43  *      A really huge debt of gratitude is owed to Eddie C. Dost
44  *      for gobs of hard work fixing and optimizing LAN code.
45  *      THANK YOU!
46  *
47  *  Copyright (c) 1999-2004 LSI Logic Corporation
48  *  Originally By: Steven J. Ralston
49  *  (mailto:sjralston1@netscape.net)
50  *  (mailto:mpt_linux_developer@lsil.com)
51  *
52  *  $Id: mptbase.c,v 1.126 2002/12/16 15:28:45 pdelaney Exp $
53  */
54 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
55 /*
56     This program is free software; you can redistribute it and/or modify
57     it under the terms of the GNU General Public License as published by
58     the Free Software Foundation; version 2 of the License.
59
60     This program is distributed in the hope that it will be useful,
61     but WITHOUT ANY WARRANTY; without even the implied warranty of
62     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
63     GNU General Public License for more details.
64
65     NO WARRANTY
66     THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
67     CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
68     LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
69     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
70     solely responsible for determining the appropriateness of using and
71     distributing the Program and assumes all risks associated with its
72     exercise of rights under this Agreement, including but not limited to
73     the risks and costs of program errors, damage to or loss of data,
74     programs or equipment, and unavailability or interruption of operations.
75
76     DISCLAIMER OF LIABILITY
77     NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
78     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
79     DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
80     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
81     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
82     USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
83     HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
84
85     You should have received a copy of the GNU General Public License
86     along with this program; if not, write to the Free Software
87     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
88 */
89 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
90
91 #include <linux/config.h>
92 #include <linux/version.h>
93 #include <linux/kernel.h>
94 #include <linux/module.h>
95 #include <linux/errno.h>
96 #include <linux/init.h>
97 #include <linux/slab.h>
98 #include <linux/types.h>
99 #include <linux/pci.h>
100 #include <linux/kdev_t.h>
101 #include <linux/blkdev.h>
102 #include <linux/delay.h>
103 #include <linux/interrupt.h>            /* needed for in_interrupt() proto */
104 #include <asm/io.h>
105 #ifdef CONFIG_MTRR
106 #include <asm/mtrr.h>
107 #endif
108 #ifdef __sparc__
109 #include <asm/irq.h>                    /* needed for __irq_itoa() proto */
110 #endif
111
112 #include "mptbase.h"
113
114 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
115 #define my_NAME         "Fusion MPT base driver"
116 #define my_VERSION      MPT_LINUX_VERSION_COMMON
117 #define MYNAM           "mptbase"
118
119 MODULE_AUTHOR(MODULEAUTHOR);
120 MODULE_DESCRIPTION(my_NAME);
121 MODULE_LICENSE("GPL");
122
123 /*
124  *  cmd line parameters
125  */
126 #ifdef MFCNT
127 static int mfcounter = 0;
128 #define PRINT_MF_COUNT 20000
129 #endif
130
131 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
132 /*
133  *  Public data...
134  */
135 int mpt_lan_index = -1;
136 int mpt_stm_index = -1;
137
138 struct proc_dir_entry *mpt_proc_root_dir;
139
140 DmpServices_t *DmpService;
141
142 void *mpt_v_ASCQ_TablePtr;
143 const char **mpt_ScsiOpcodesPtr;
144 int mpt_ASCQ_TableSz;
145
146
147 #define WHOINIT_UNKNOWN         0xAA
148
149 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
150 /*
151  *  Private data...
152  */
153                                         /* Adapter lookup table */
154        MPT_ADAPTER              *mpt_adapters[MPT_MAX_ADAPTERS];
155 static MPT_ADAPTER_TRACKER       MptAdapters;
156                                         /* Callback lookup table */
157 static MPT_CALLBACK              MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
158                                         /* Protocol driver class lookup table */
159 static int                       MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
160                                         /* Event handler lookup table */
161 static MPT_EVHANDLER             MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
162                                         /* Reset handler lookup table */
163 static MPT_RESETHANDLER          MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
164 static struct mpt_pci_driver    *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
165
166 static int      FusionInitCalled = 0;
167 static int      mpt_base_index = -1;
168 static int      last_drv_idx = -1;
169 static int      isense_idx = -1;
170
171 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
172
173 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
174 /*
175  *  Forward protos...
176  */
177 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
178 static int      mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
179
180 static int      mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
181 static void     mpt_detect_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);
182 static void     mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup);
183 static void     mpt_adapter_dispose(MPT_ADAPTER *ioc);
184
185 static void     MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
186 static int      MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
187 //static u32    mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
188 static int      GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
189 static int      GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
190 static int      SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
191 static int      SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
192 static int      mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
193 static int      mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag);
194 static int      mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
195 static int      KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
196 static int      SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
197 static int      PrimeIocFifos(MPT_ADAPTER *ioc);
198 static int      WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
199 static int      WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
200 static int      WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
201 static int      GetLanConfigPages(MPT_ADAPTER *ioc);
202 static int      GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
203 static int      GetIoUnitPage2(MPT_ADAPTER *ioc);
204 static int      mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
205 static int      mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
206 static void     mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
207 static void     mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
208 static void     mpt_timer_expired(unsigned long data);
209 static int      SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
210 static int      SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
211
212 #ifdef CONFIG_PROC_FS
213 static int      procmpt_create(void);
214 static int      procmpt_destroy(void);
215 static int      procmpt_summary_read(char *buf, char **start, off_t offset,
216                                 int request, int *eof, void *data);
217 static int      procmpt_version_read(char *buf, char **start, off_t offset,
218                                 int request, int *eof, void *data);
219 static int      procmpt_iocinfo_read(char *buf, char **start, off_t offset,
220                                 int request, int *eof, void *data);
221 #endif
222 static void     mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
223
224 //int           mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
225 static int      ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
226 static void     mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
227 static void     mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
228 static void     mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
229
230 /* module entry point */
231 static int  __devinit mptbase_probe (struct pci_dev *, const struct pci_device_id *);
232 static void __devexit mptbase_remove(struct pci_dev *);
233 static void mptbase_shutdown(struct device * );
234 static int  __init    fusion_init  (void);
235 static void __exit    fusion_exit  (void);
236
237 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
238 /*
239  *  more Private data...
240  */
241 #ifdef CONFIG_PROC_FS
242 struct _mpt_proc_list {
243         const char      *name;
244         int             (*f)(char *, char **, off_t, int, int *, void *);
245 } mpt_proc_list[] = {
246         { "summary", procmpt_summary_read},
247         { "version", procmpt_version_read},
248 };
249 #define MPT_PROC_ENTRIES (sizeof(mpt_proc_list)/sizeof(mpt_proc_list[0]))
250
251 struct _mpt_ioc_proc_list {
252         const char      *name;
253         int             (*f)(char *, char **, off_t, int, int *, void *);
254 } mpt_ioc_proc_list[] = {
255         { "info", procmpt_iocinfo_read},
256         { "summary", procmpt_summary_read},
257 };
258 #define MPT_IOC_PROC_ENTRIES (sizeof(mpt_ioc_proc_list)/sizeof(mpt_ioc_proc_list[0]))
259
260 #endif
261
262 /****************************************************************************
263  * Supported hardware
264  */
265
266 static struct pci_device_id mptbase_pci_table[] = {
267         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
268                 PCI_ANY_ID, PCI_ANY_ID },
269         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
270                 PCI_ANY_ID, PCI_ANY_ID },
271         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
272                 PCI_ANY_ID, PCI_ANY_ID },
273         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
274                 PCI_ANY_ID, PCI_ANY_ID },
275         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
276                 PCI_ANY_ID, PCI_ANY_ID },
277         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
278                 PCI_ANY_ID, PCI_ANY_ID },
279         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
280                 PCI_ANY_ID, PCI_ANY_ID },
281         {0}     /* Terminating entry */
282 };
283 MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
284
285 #define CHIPREG_READ32(addr)            readl(addr)
286 #define CHIPREG_WRITE32(addr,val)       writel(val, addr)
287 #define CHIPREG_PIO_WRITE32(addr,val)   outl(val, (unsigned long)addr)
288 #define CHIPREG_PIO_READ32(addr)        inl((unsigned long)addr)
289
290 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
291 /*
292  *      mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
293  *      @irq: irq number (not used)
294  *      @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
295  *      @r: pt_regs pointer (not used)
296  *
297  *      This routine is registered via the request_irq() kernel API call,
298  *      and handles all interrupts generated from a specific MPT adapter
299  *      (also referred to as a IO Controller or IOC).
300  *      This routine must clear the interrupt from the adapter and does
301  *      so by reading the reply FIFO.  Multiple replies may be processed
302  *      per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
303  *      which is currently set to 32 in mptbase.h.
304  *
305  *      This routine handles register-level access of the adapter but
306  *      dispatches (calls) a protocol-specific callback routine to handle
307  *      the protocol-specific details of the MPT request completion.
308  */
309 static irqreturn_t
310 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
311 {
312         MPT_ADAPTER     *ioc;
313         MPT_FRAME_HDR   *mf;
314         MPT_FRAME_HDR   *mr;
315         u32              pa;
316         int              req_idx;
317         int              cb_idx;
318         int              type;
319         int              freeme;
320
321         ioc = bus_id;
322
323 #ifdef MPT_DEBUG_IRQ
324         /*
325          * Verify ioc pointer is ok
326          */
327         {
328                 MPT_ADAPTER     *iocCmp;
329                 iocCmp = mpt_adapter_find_first();
330                 while ((ioc != iocCmp)  && iocCmp)
331                         iocCmp = mpt_adapter_find_next(iocCmp);
332
333                 if (!iocCmp) {
334                         printk(KERN_WARNING "mpt_interrupt: Invalid ioc!\n");
335                         return IRQ_NONE;
336                 }
337         }
338 #endif
339
340         /*
341          *  Drain the reply FIFO!
342          *
343          * NOTES: I've seen up to 10 replies processed in this loop, so far...
344          * Update: I've seen up to 9182 replies processed in this loop! ??
345          * Update: Limit ourselves to processing max of N replies
346          *      (bottom of loop).
347          */
348         while (1) {
349
350                 if ((pa = CHIPREG_READ32(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)
351                         return IRQ_HANDLED;
352
353                 cb_idx = 0;
354                 freeme = 0;
355
356                 /*
357                  *  Check for non-TURBO reply!
358                  */
359                 if (pa & MPI_ADDRESS_REPLY_A_BIT) {
360                         u32 reply_dma_low;
361                         u16 ioc_stat;
362
363                         /* non-TURBO reply!  Hmmm, something may be up...
364                          *  Newest turbo reply mechanism; get address
365                          *  via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
366                          */
367
368                         /* Map DMA address of reply header to cpu address.
369                          * pa is 32 bits - but the dma address may be 32 or 64 bits
370                          * get offset based only only the low addresses
371                          */
372                         reply_dma_low = (pa = (pa << 1));
373                         mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
374                                          (reply_dma_low - ioc->reply_frames_low_dma));
375
376                         req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
377                         cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
378                         mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
379
380                         dprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p\n",
381                                         ioc->name, mr));
382                         DBG_DUMP_REPLY_FRAME(mr)
383
384                         /* NEW!  20010301 -sralston
385                          *  Check/log IOC log info
386                          */
387                         ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
388                         if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
389                                 u32      log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
390                                 if ((int)ioc->chip_type <= (int)FC929)
391                                         mpt_fc_log_info(ioc, log_info);
392                                 else
393                                         mpt_sp_log_info(ioc, log_info);
394                         }
395                         if (ioc_stat & MPI_IOCSTATUS_MASK) {
396                                 if ((int)ioc->chip_type <= (int)FC929)
397                                                 ;
398                                 else
399                                         mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
400                         }
401                 } else {
402                         /*
403                          *  Process turbo (context) reply...
404                          */
405                         dirqprintk((MYIOC_s_INFO_FMT "Got TURBO reply(=%08x)\n", ioc->name, pa));
406                         type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
407                         if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
408                                 cb_idx = mpt_stm_index;
409                                 mf = NULL;
410                                 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
411                         } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
412                                 cb_idx = mpt_lan_index;
413                                 /*
414                                  * BUG FIX!  20001218 -sralston
415                                  *  Blind set of mf to NULL here was fatal
416                                  *  after lan_reply says "freeme"
417                                  *  Fix sort of combined with an optimization here;
418                                  *  added explicit check for case where lan_reply
419                                  *  was just returning 1 and doing nothing else.
420                                  *  For this case skip the callback, but set up
421                                  *  proper mf value first here:-)
422                                  */
423                                 if ((pa & 0x58000000) == 0x58000000) {
424                                         req_idx = pa & 0x0000FFFF;
425                                         mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
426                                         freeme = 1;
427                                         /*
428                                          *  IMPORTANT!  Invalidate the callback!
429                                          */
430                                         cb_idx = 0;
431                                 } else {
432                                         mf = NULL;
433                                 }
434                                 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
435                         } else {
436                                 req_idx = pa & 0x0000FFFF;
437                                 cb_idx = (pa & 0x00FF0000) >> 16;
438                                 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
439                                 mr = NULL;
440                         }
441                         pa = 0;                                 /* No reply flush! */
442                 }
443
444 #ifdef MPT_DEBUG_IRQ
445                 if ((int)ioc->chip_type > (int)FC929) {
446                         /* Verify mf, mr are reasonable.
447                          */
448                         if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
449                                 || (mf < ioc->req_frames)) ) {
450                                 printk(MYIOC_s_WARN_FMT
451                                         "mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx);
452                                 cb_idx = 0;
453                                 pa = 0;
454                                 freeme = 0;
455                         }
456                         if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth))
457                                 || (mr < ioc->reply_frames)) ) {
458                                 printk(MYIOC_s_WARN_FMT
459                                         "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr);
460                                 cb_idx = 0;
461                                 pa = 0;
462                                 freeme = 0;
463                         }
464                         if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) {
465                                 printk(MYIOC_s_WARN_FMT
466                                         "mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx);
467                                 cb_idx = 0;
468                                 pa = 0;
469                                 freeme = 0;
470                         }
471                 }
472 #endif
473
474                 /*  Check for (valid) IO callback!  */
475                 if (cb_idx) {
476                         /*  Do the callback!  */
477                         freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);
478                 }
479
480                 if (pa) {
481                         /*  Flush (non-TURBO) reply with a WRITE!  */
482                         CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
483                 }
484
485                 if (freeme) {
486                         unsigned long flags;
487
488                         /*  Put Request back on FreeQ!  */
489                         spin_lock_irqsave(&ioc->FreeQlock, flags);
490                         Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
491 #ifdef MFCNT
492                         ioc->mfcnt--;
493 #endif
494                         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
495                 }
496
497                 mb();
498         }       /* drain reply FIFO */
499
500         return IRQ_HANDLED;
501 }
502
503 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
504 /*
505  *      mpt_base_reply - MPT base driver's callback routine; all base driver
506  *      "internal" request/reply processing is routed here.
507  *      Currently used for EventNotification and EventAck handling.
508  *      @ioc: Pointer to MPT_ADAPTER structure
509  *      @mf: Pointer to original MPT request frame
510  *      @reply: Pointer to MPT reply frame (NULL if TurboReply)
511  *
512         *       Returns 1 indicating original alloc'd request frame ptr
513  *      should be freed, or 0 if it shouldn't.
514  */
515 static int
516 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
517 {
518         int freereq = 1;
519         u8 func;
520
521         dprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
522
523         if ((mf == NULL) ||
524             (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
525                 printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n",
526                                 ioc->name, (void *)mf);
527                 return 1;
528         }
529
530         if (reply == NULL) {
531                 dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n",
532                                 ioc->name));
533                 return 1;
534         }
535
536         if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
537                 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
538                 DBG_DUMP_REQUEST_FRAME_HDR(mf)
539         }
540
541         func = reply->u.hdr.Function;
542         dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
543                         ioc->name, func));
544
545         if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
546                 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
547                 int evHandlers = 0;
548                 int results;
549
550                 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
551                 if (results != evHandlers) {
552                         /* CHECKME! Any special handling needed here? */
553                         dprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
554                                         ioc->name, evHandlers, results));
555                 }
556
557                 /*
558                  *      Hmmm...  It seems that EventNotificationReply is an exception
559                  *      to the rule of one reply per request.
560                  */
561                 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
562                         freereq = 0;
563
564 #ifdef CONFIG_PROC_FS
565 //              LogEvent(ioc, pEvReply);
566 #endif
567
568         } else if (func == MPI_FUNCTION_EVENT_ACK) {
569                 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
570                                 ioc->name));
571         } else if (func == MPI_FUNCTION_CONFIG ||
572                    func == MPI_FUNCTION_TOOLBOX) {
573                 CONFIGPARMS *pCfg;
574                 unsigned long flags;
575
576                 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
577                                 ioc->name, mf, reply));
578
579                 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
580
581                 if (pCfg) {
582                         /* disable timer and remove from linked list */
583                         del_timer(&pCfg->timer);
584
585                         spin_lock_irqsave(&ioc->FreeQlock, flags);
586                         Q_DEL_ITEM(&pCfg->linkage);
587                         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
588
589                         /*
590                          *      If IOC Status is SUCCESS, save the header
591                          *      and set the status code to GOOD.
592                          */
593                         pCfg->status = MPT_CONFIG_ERROR;
594                         if (reply) {
595                                 ConfigReply_t   *pReply = (ConfigReply_t *)reply;
596                                 u16              status;
597
598                                 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
599                                 dcprintk((KERN_NOTICE "  IOCStatus=%04xh, IOCLogInfo=%08xh\n",
600                                      status, le32_to_cpu(pReply->IOCLogInfo)));
601
602                                 pCfg->status = status;
603                                 if (status == MPI_IOCSTATUS_SUCCESS) {
604                                         pCfg->hdr->PageVersion = pReply->Header.PageVersion;
605                                         pCfg->hdr->PageLength = pReply->Header.PageLength;
606                                         pCfg->hdr->PageNumber = pReply->Header.PageNumber;
607                                         pCfg->hdr->PageType = pReply->Header.PageType;
608                                 }
609                         }
610
611                         /*
612                          *      Wake up the original calling thread
613                          */
614                         pCfg->wait_done = 1;
615                         wake_up(&mpt_waitq);
616                 }
617         } else {
618                 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
619                                 ioc->name, func);
620         }
621
622         /*
623          *      Conditionally tell caller to free the original
624          *      EventNotification/EventAck/unexpected request frame!
625          */
626         return freereq;
627 }
628
629 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
630 /**
631  *      mpt_register - Register protocol-specific main callback handler.
632  *      @cbfunc: callback function pointer
633  *      @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
634  *
635  *      This routine is called by a protocol-specific driver (SCSI host,
636  *      LAN, SCSI target) to register it's reply callback routine.  Each
637  *      protocol-specific driver must do this before it will be able to
638  *      use any IOC resources, such as obtaining request frames.
639  *
640  *      NOTES: The SCSI protocol driver currently calls this routine thrice
641  *      in order to register separate callbacks; one for "normal" SCSI IO;
642  *      one for MptScsiTaskMgmt requests; one for Scan/DV requests.
643  *
644  *      Returns a positive integer valued "handle" in the
645  *      range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
646  *      Any non-positive return value (including zero!) should be considered
647  *      an error by the caller.
648  */
649 int
650 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
651 {
652         int i;
653
654         last_drv_idx = -1;
655
656 #ifndef MODULE
657         /*
658          *  Handle possibility of the mptscsih_detect() routine getting
659          *  called *before* fusion_init!
660          */
661         if (!FusionInitCalled) {
662                 dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n"));
663                 /*
664                  *  NOTE! We'll get recursion here, as fusion_init()
665                  *  calls mpt_register()!
666                  */
667                 fusion_init();
668                 FusionInitCalled++;
669         }
670 #endif
671
672         /*
673          *  Search for empty callback slot in this order: {N,...,7,6,5,...,1}
674          *  (slot/handle 0 is reserved!)
675          */
676         for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
677                 if (MptCallbacks[i] == NULL) {
678                         MptCallbacks[i] = cbfunc;
679                         MptDriverClass[i] = dclass;
680                         MptEvHandlers[i] = NULL;
681                         last_drv_idx = i;
682                         break;
683                 }
684         }
685
686         return last_drv_idx;
687 }
688
689 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
690 /**
691  *      mpt_deregister - Deregister a protocol drivers resources.
692  *      @cb_idx: previously registered callback handle
693  *
694  *      Each protocol-specific driver should call this routine when it's
695  *      module is unloaded.
696  */
697 void
698 mpt_deregister(int cb_idx)
699 {
700         if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
701                 MptCallbacks[cb_idx] = NULL;
702                 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
703                 MptEvHandlers[cb_idx] = NULL;
704
705                 last_drv_idx++;
706                 if (isense_idx != -1 && isense_idx <= cb_idx)
707                         isense_idx++;
708         }
709 }
710
711 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
712 /**
713  *      mpt_event_register - Register protocol-specific event callback
714  *      handler.
715  *      @cb_idx: previously registered (via mpt_register) callback handle
716  *      @ev_cbfunc: callback function
717  *
718  *      This routine can be called by one or more protocol-specific drivers
719  *      if/when they choose to be notified of MPT events.
720  *
721  *      Returns 0 for success.
722  */
723 int
724 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
725 {
726         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
727                 return -1;
728
729         MptEvHandlers[cb_idx] = ev_cbfunc;
730         return 0;
731 }
732
733 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
734 /**
735  *      mpt_event_deregister - Deregister protocol-specific event callback
736  *      handler.
737  *      @cb_idx: previously registered callback handle
738  *
739  *      Each protocol-specific driver should call this routine
740  *      when it does not (or can no longer) handle events,
741  *      or when it's module is unloaded.
742  */
743 void
744 mpt_event_deregister(int cb_idx)
745 {
746         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
747                 return;
748
749         MptEvHandlers[cb_idx] = NULL;
750 }
751
752 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
753 /**
754  *      mpt_reset_register - Register protocol-specific IOC reset handler.
755  *      @cb_idx: previously registered (via mpt_register) callback handle
756  *      @reset_func: reset function
757  *
758  *      This routine can be called by one or more protocol-specific drivers
759  *      if/when they choose to be notified of IOC resets.
760  *
761  *      Returns 0 for success.
762  */
763 int
764 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
765 {
766         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
767                 return -1;
768
769         MptResetHandlers[cb_idx] = reset_func;
770         return 0;
771 }
772
773 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
774 /**
775  *      mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
776  *      @cb_idx: previously registered callback handle
777  *
778  *      Each protocol-specific driver should call this routine
779  *      when it does not (or can no longer) handle IOC reset handling,
780  *      or when it's module is unloaded.
781  */
782 void
783 mpt_reset_deregister(int cb_idx)
784 {
785         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
786                 return;
787
788         MptResetHandlers[cb_idx] = NULL;
789 }
790
791 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
792 /**
793  *      mpt_device_driver_register - Register device driver hooks
794  */
795 int
796 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
797 {
798         MPT_ADAPTER     *ioc;
799         int             error=0;
800
801         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
802                 error= -EINVAL;
803                 return error;
804         }
805
806         MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
807
808         /* call per pci device probe entry point */
809         for(ioc = mpt_adapter_find_first(); ioc != NULL;
810           ioc = mpt_adapter_find_next(ioc)) {
811                 if(dd_cbfunc->probe) {
812                         error = dd_cbfunc->probe(ioc->pcidev,
813                           ioc->pcidev->driver->id_table);
814                         if(error != 0)
815                                 return error;
816                 }
817          }
818
819         return error;
820 }
821
822 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
823 /**
824  *      mpt_device_driver_deregister - DeRegister device driver hooks
825  */
826 void
827 mpt_device_driver_deregister(int cb_idx)
828 {
829         if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
830                 return;
831
832         MptDeviceDriverHandlers[cb_idx] = NULL;
833 }
834
835
836 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
837 /**
838  *      mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
839  *      allocated per MPT adapter.
840  *      @handle: Handle of registered MPT protocol driver
841  *      @iocid: IOC unique identifier (integer)
842  *
843  *      Returns pointer to a MPT request frame or %NULL if none are available
844  *      or IOC is not active.
845  */
846 MPT_FRAME_HDR*
847 mpt_get_msg_frame(int handle, int iocid)
848 {
849         MPT_FRAME_HDR *mf;
850         MPT_ADAPTER *iocp;
851         unsigned long flags;
852
853         /* validate handle and ioc identifier */
854         iocp = mpt_adapters[iocid];
855
856 #ifdef MFCNT
857         if (!iocp->active)
858                 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
859 #endif
860
861         /* If interrupts are not attached, do not return a request frame */
862         if (!iocp->active)
863                 return NULL;
864
865         spin_lock_irqsave(&iocp->FreeQlock, flags);
866         if (! Q_IS_EMPTY(&iocp->FreeQ)) {
867                 int req_offset;
868
869                 mf = iocp->FreeQ.head;
870                 Q_DEL_ITEM(&mf->u.frame.linkage);
871                 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;  /* byte */
872                 req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
873                                                                 /* u16! */
874                 mf->u.frame.hwhdr.msgctxu.fld.req_idx =
875                                 cpu_to_le16(req_offset / iocp->req_sz);
876                 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
877 #ifdef MFCNT
878                 iocp->mfcnt++;
879 #endif
880         }
881         else
882                 mf = NULL;
883         spin_unlock_irqrestore(&iocp->FreeQlock, flags);
884
885 #ifdef MFCNT
886         if (mf == NULL)
887                 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", iocp->mfcnt, iocp->req_depth);
888         mfcounter++;
889         if (mfcounter == PRINT_MF_COUNT)
890                 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", iocp->mfcnt, iocp->req_depth);
891 #endif
892
893         dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
894                         iocp->name, handle, iocid, mf));
895         return mf;
896 }
897
898 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
899 /**
900  *      mpt_put_msg_frame - Send a protocol specific MPT request frame
901  *      to a IOC.
902  *      @handle: Handle of registered MPT protocol driver
903  *      @iocid: IOC unique identifier (integer)
904  *      @mf: Pointer to MPT request frame
905  *
906  *      This routine posts a MPT request frame to the request post FIFO of a
907  *      specific MPT adapter.
908  */
909 void
910 mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
911 {
912         MPT_ADAPTER *iocp;
913
914         iocp = mpt_adapters[iocid];
915         if (iocp != NULL) {
916                 u32 mf_dma_addr;
917                 int req_offset;
918
919                 /* ensure values are reset properly! */
920                 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;          /* byte */
921                 req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
922                                                                         /* u16! */
923                 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz);
924                 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
925
926 #ifdef MPT_DEBUG_MSG_FRAME
927                 {
928                         u32     *m = mf->u.frame.hwhdr.__hdr;
929                         int      ii, n;
930
931                         printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
932                                         iocp->name, m);
933                         n = iocp->req_sz/4 - 1;
934                         while (m[n] == 0)
935                                 n--;
936                         for (ii=0; ii<=n; ii++) {
937                                 if (ii && ((ii%8)==0))
938                                         printk("\n" KERN_INFO " ");
939                                 printk(" %08x", le32_to_cpu(m[ii]));
940                         }
941                         printk("\n");
942                 }
943 #endif
944
945                 mf_dma_addr = iocp->req_frames_low_dma + req_offset;
946                 CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);
947         } else {
948                 printk (KERN_ERR
949                     "mpt_put_msg_frame: Invalid iocid=%d\n", iocid);
950         }
951
952 }
953
954 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
955 /**
956  *      mpt_free_msg_frame - Place MPT request frame back on FreeQ.
957  *      @handle: Handle of registered MPT protocol driver
958  *      @iocid: IOC unique identifier (integer)
959  *      @mf: Pointer to MPT request frame
960  *
961  *      This routine places a MPT request frame back on the MPT adapter's
962  *      FreeQ.
963  */
964 void
965 mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
966 {
967         MPT_ADAPTER *iocp;
968         unsigned long flags;
969
970         iocp = mpt_adapters[iocid];
971         if (iocp != NULL) {
972                 /*  Put Request back on FreeQ!  */
973                 spin_lock_irqsave(&iocp->FreeQlock, flags);
974                 Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
975 #ifdef MFCNT
976                 iocp->mfcnt--;
977 #endif
978                 spin_unlock_irqrestore(&iocp->FreeQlock, flags);
979         }
980 }
981
982 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
983 /**
984  *      mpt_add_sge - Place a simple SGE at address pAddr.
985  *      @pAddr: virtual address for SGE
986  *      @flagslength: SGE flags and data transfer length
987  *      @dma_addr: Physical address
988  *
989  *      This routine places a MPT request frame back on the MPT adapter's
990  *      FreeQ.
991  */
992 void
993 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
994 {
995         if (sizeof(dma_addr_t) == sizeof(u64)) {
996                 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
997                 u32 tmp = dma_addr & 0xFFFFFFFF;
998
999                 pSge->FlagsLength = cpu_to_le32(flagslength);
1000                 pSge->Address.Low = cpu_to_le32(tmp);
1001                 tmp = (u32) ((u64)dma_addr >> 32);
1002                 pSge->Address.High = cpu_to_le32(tmp);
1003
1004         } else {
1005                 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
1006                 pSge->FlagsLength = cpu_to_le32(flagslength);
1007                 pSge->Address = cpu_to_le32(dma_addr);
1008         }
1009 }
1010
1011 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1012 /**
1013  *      mpt_add_chain - Place a chain SGE at address pAddr.
1014  *      @pAddr: virtual address for SGE
1015  *      @next: nextChainOffset value (u32's)
1016  *      @length: length of next SGL segment
1017  *      @dma_addr: Physical address
1018  *
1019  *      This routine places a MPT request frame back on the MPT adapter's
1020  *      FreeQ.
1021  */
1022 void
1023 mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
1024 {
1025         if (sizeof(dma_addr_t) == sizeof(u64)) {
1026                 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
1027                 u32 tmp = dma_addr & 0xFFFFFFFF;
1028
1029                 pChain->Length = cpu_to_le16(length);
1030                 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
1031
1032                 pChain->NextChainOffset = next;
1033
1034                 pChain->Address.Low = cpu_to_le32(tmp);
1035                 tmp = (u32) ((u64)dma_addr >> 32);
1036                 pChain->Address.High = cpu_to_le32(tmp);
1037         } else {
1038                 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
1039                 pChain->Length = cpu_to_le16(length);
1040                 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
1041                 pChain->NextChainOffset = next;
1042                 pChain->Address = cpu_to_le32(dma_addr);
1043         }
1044 }
1045
1046 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1047 /**
1048  *      mpt_send_handshake_request - Send MPT request via doorbell
1049  *      handshake method.
1050  *      @handle: Handle of registered MPT protocol driver
1051  *      @iocid: IOC unique identifier (integer)
1052  *      @reqBytes: Size of the request in bytes
1053  *      @req: Pointer to MPT request frame
1054  *      @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1055  *
1056  *      This routine is used exclusively to send MptScsiTaskMgmt
1057  *      requests since they are required to be sent via doorbell handshake.
1058  *
1059  *      NOTE: It is the callers responsibility to byte-swap fields in the
1060  *      request which are greater than 1 byte in size.
1061  *
1062  *      Returns 0 for success, non-zero for failure.
1063  */
1064 int
1065 mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req, int sleepFlag)
1066 {
1067         MPT_ADAPTER     *iocp;
1068         int              r = 0;
1069
1070         iocp = mpt_adapters[iocid];
1071         if (iocp != NULL) {
1072                 u8      *req_as_bytes;
1073                 int      ii;
1074
1075                 /* State is known to be good upon entering
1076                  * this function so issue the bus reset
1077                  * request.
1078                  */
1079
1080                 /*
1081                  * Emulate what mpt_put_msg_frame() does /wrt to sanity
1082                  * setting cb_idx/req_idx.  But ONLY if this request
1083                  * is in proper (pre-alloc'd) request buffer range...
1084                  */
1085                 ii = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req);
1086                 if (reqBytes >= 12 && ii >= 0 && ii < iocp->req_depth) {
1087                         MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
1088                         mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
1089                         mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
1090                 }
1091
1092                 /* Make sure there are no doorbells */
1093                 CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
1094
1095                 CHIPREG_WRITE32(&iocp->chip->Doorbell,
1096                                 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
1097                                  ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
1098
1099                 /* Wait for IOC doorbell int */
1100                 if ((ii = WaitForDoorbellInt(iocp, 5, sleepFlag)) < 0) {
1101                         return ii;
1102                 }
1103
1104                 /* Read doorbell and check for active bit */
1105                 if (!(CHIPREG_READ32(&iocp->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
1106                                 return -5;
1107
1108                 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
1109                                 iocp->name, ii));
1110
1111                 CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
1112
1113                 if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) {
1114                         return -2;
1115                 }
1116
1117                 /* Send request via doorbell handshake */
1118                 req_as_bytes = (u8 *) req;
1119                 for (ii = 0; ii < reqBytes/4; ii++) {
1120                         u32 word;
1121
1122                         word = ((req_as_bytes[(ii*4) + 0] <<  0) |
1123                                 (req_as_bytes[(ii*4) + 1] <<  8) |
1124                                 (req_as_bytes[(ii*4) + 2] << 16) |
1125                                 (req_as_bytes[(ii*4) + 3] << 24));
1126                         CHIPREG_WRITE32(&iocp->chip->Doorbell, word);
1127                         if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) {
1128                                 r = -3;
1129                                 break;
1130                         }
1131                 }
1132
1133                 if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0)
1134                         r = 0;
1135                 else
1136                         r = -4;
1137
1138                 /* Make sure there are no doorbells */
1139                 CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
1140         }
1141
1142         return r;
1143 }
1144
1145 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1146 /**
1147  *      mpt_adapter_find_first - Find first MPT adapter pointer.
1148  *
1149  *      Returns first MPT adapter pointer or %NULL if no MPT adapters
1150  *      are present.
1151  */
1152 MPT_ADAPTER *
1153 mpt_adapter_find_first(void)
1154 {
1155         MPT_ADAPTER *this;
1156
1157         if (! Q_IS_EMPTY(&MptAdapters))
1158                 this = MptAdapters.head;
1159         else
1160                 this = NULL;
1161
1162         return this;
1163 }
1164
1165 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1166 /**
1167  *      mpt_adapter_find_next - Find next MPT adapter pointer.
1168  *      @prev: Pointer to previous MPT adapter
1169  *
1170  *      Returns next MPT adapter pointer or %NULL if there are no more.
1171  */
1172 MPT_ADAPTER *
1173 mpt_adapter_find_next(MPT_ADAPTER *prev)
1174 {
1175         MPT_ADAPTER *next;
1176
1177         if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head))
1178                 next = prev->forw;
1179         else
1180                 next = NULL;
1181
1182         return next;
1183 }
1184
1185
1186 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1187 /**
1188  *      mpt_verify_adapter - Given a unique IOC identifier, set pointer to
1189  *      the associated MPT adapter structure.
1190  *      @iocid: IOC unique identifier (integer)
1191  *      @iocpp: Pointer to pointer to IOC adapter
1192  *
1193  *      Returns iocid and sets iocpp.
1194  */
1195 int
1196 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1197 {
1198         MPT_ADAPTER *p;
1199
1200         *iocpp = NULL;
1201         if (iocid >= MPT_MAX_ADAPTERS)
1202                 return -1;
1203
1204         p = mpt_adapters[iocid];
1205         if (p == NULL)
1206                 return -1;
1207
1208         *iocpp = p;
1209         return iocid;
1210 }
1211
1212 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1213 /*
1214  *      mptbase_probe - Install a PCI intelligent MPT adapter.
1215  *      @pdev: Pointer to pci_dev structure
1216  *
1217  *      This routine performs all the steps necessary to bring the IOC of
1218  *      a MPT adapter to a OPERATIONAL state.  This includes registering
1219  *      memory regions, registering the interrupt, and allocating request
1220  *      and reply memory pools.
1221  *
1222  *      This routine also pre-fetches the LAN MAC address of a Fibre Channel
1223  *      MPT adapter.
1224  *
1225  *      Returns 0 for success, non-zero for failure.
1226  *
1227  *      TODO: Add support for polled controllers
1228  */
1229 static int __devinit
1230 mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1231 {
1232         MPT_ADAPTER     *ioc;
1233         u8              *mem;
1234         unsigned long    mem_phys;
1235         unsigned long    port;
1236         u32              msize;
1237         u32              psize;
1238         int              ii;
1239         int              r = -ENODEV;
1240         u64              mask = 0xffffffffffffffffULL;
1241         u8               revision;
1242         u8               pcixcmd;
1243
1244         if (pci_enable_device(pdev))
1245                 return r;
1246         
1247         if (!pci_set_dma_mask(pdev, mask)) {
1248                 dprintk((KERN_INFO MYNAM
1249                         ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1250         } else if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {
1251                 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1252                 return r;
1253         }
1254
1255         if (!pci_set_consistent_dma_mask(pdev, mask))
1256                 dprintk((KERN_INFO MYNAM
1257                         ": Using 64 bit consistent mask\n"));
1258         else
1259                 dprintk((KERN_INFO MYNAM
1260                         ": Not using 64 bit consistent mask\n"));
1261
1262         ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1263         if (ioc == NULL) {
1264                 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1265                 return -ENOMEM;
1266         }
1267         memset(ioc, 0, sizeof(MPT_ADAPTER));
1268         ioc->alloc_total = sizeof(MPT_ADAPTER);
1269         ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;           /* avoid div by zero! */
1270         ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1271
1272         ioc->pcidev = pdev;
1273
1274         ioc->diagPending = 0;
1275         spin_lock_init(&ioc->diagLock);
1276
1277         /* Initialize the event logging.
1278          */
1279         ioc->eventTypes = 0;    /* None */
1280         ioc->eventContext = 0;
1281         ioc->eventLogSize = 0;
1282         ioc->events = NULL;
1283
1284 #ifdef MFCNT
1285         ioc->mfcnt = 0;
1286 #endif
1287
1288         ioc->cached_fw = NULL;
1289
1290         /* Initilize SCSI Config Data structure
1291          */
1292         memset(&ioc->spi_data, 0, sizeof(ScsiCfgData));
1293
1294         /* Initialize the running configQ head.
1295          */
1296         Q_INIT(&ioc->configQ, Q_ITEM);
1297
1298         /* Find lookup slot. */
1299         for (ii=0; ii < MPT_MAX_ADAPTERS; ii++) {
1300                 if (mpt_adapters[ii] == NULL) {
1301                         ioc->id = ii;           /* Assign adapter unique id (lookup) */
1302                         break;
1303                 }
1304         }
1305         if (ii == MPT_MAX_ADAPTERS) {
1306                 printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", ii);
1307                 kfree(ioc);
1308                 return -ENFILE;
1309         }
1310
1311         mem_phys = msize = 0;
1312         port = psize = 0;
1313         for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1314                 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1315                         /* Get I/O space! */
1316                         port = pci_resource_start(pdev, ii);
1317                         psize = pci_resource_len(pdev,ii);
1318                 } else {
1319                         /* Get memmap */
1320                         mem_phys = pci_resource_start(pdev, ii);
1321                         msize = pci_resource_len(pdev,ii);
1322                         break;
1323                 }
1324         }
1325         ioc->mem_size = msize;
1326
1327         if (ii == DEVICE_COUNT_RESOURCE) {
1328                 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1329                 kfree(ioc);
1330                 return -EINVAL;
1331         }
1332
1333         dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1334         dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1335
1336         mem = NULL;
1337         /* Get logical ptr for PciMem0 space */
1338         /*mem = ioremap(mem_phys, msize);*/
1339         mem = ioremap(mem_phys, 0x100);
1340         if (mem == NULL) {
1341                 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1342                 kfree(ioc);
1343                 return -EINVAL;
1344         }
1345         ioc->memmap = mem;
1346         dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1347
1348         dprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1349                         &ioc->facts, &ioc->pfacts[0]));
1350
1351         ioc->mem_phys = mem_phys;
1352         ioc->chip = (SYSIF_REGS*)mem;
1353
1354         /* Save Port IO values incase we need to do downloadboot */
1355         {
1356                 u8 *pmem = (u8*)port;
1357                 ioc->pio_mem_phys = port;
1358                 ioc->pio_chip = (SYSIF_REGS*)pmem;
1359         }
1360
1361         ioc->chip_type = FCUNK;
1362         if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1363                 ioc->chip_type = FC909;
1364                 ioc->prod_name = "LSIFC909";
1365         }
1366         if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1367                 ioc->chip_type = FC929;
1368                 ioc->prod_name = "LSIFC929";
1369         }
1370         else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1371                 ioc->chip_type = FC919;
1372                 ioc->prod_name = "LSIFC919";
1373         }
1374         else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1375                 ioc->chip_type = FC929X;
1376                 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1377                 if (revision < XL_929) {
1378                         ioc->prod_name = "LSIFC929X";
1379                         /* 929X Chip Fix. Set Split transactions level
1380                         * for PCIX. Set MOST bits to zero.
1381                         */
1382                         pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1383                         pcixcmd &= 0x8F;
1384                         pci_write_config_byte(pdev, 0x6a, pcixcmd);
1385                 } else {
1386                         ioc->prod_name = "LSIFC929XL";
1387                         /* 929XL Chip Fix. Set MMRBC to 0x08.
1388                         */
1389                         pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1390                         pcixcmd |= 0x08;
1391                         pci_write_config_byte(pdev, 0x6a, pcixcmd);
1392                 }
1393         }
1394         else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1395                 ioc->chip_type = FC919X;
1396                 ioc->prod_name = "LSIFC919X";
1397                 /* 919X Chip Fix. Set Split transactions level
1398                  * for PCIX. Set MOST bits to zero.
1399                  */
1400                 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1401                 pcixcmd &= 0x8F;
1402                 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1403         }
1404         else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1405                 ioc->chip_type = C1030;
1406                 ioc->prod_name = "LSI53C1030";
1407                 /* 1030 Chip Fix. Disable Split transactions
1408                  * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1409                  */
1410                 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1411                 if (revision < C0_1030) {
1412                         pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1413                         pcixcmd &= 0x8F;
1414                         pci_write_config_byte(pdev, 0x6a, pcixcmd);
1415                 }
1416         }
1417         else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1418                 ioc->chip_type = C1035;
1419                 ioc->prod_name = "LSI53C1035";
1420         }
1421
1422         sprintf(ioc->name, "ioc%d", ioc->id);
1423
1424         Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
1425         spin_lock_init(&ioc->FreeQlock);
1426
1427         /* Disable all! */
1428         CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1429         ioc->active = 0;
1430         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1431
1432         /* tack onto tail of our MPT adapter list */
1433         Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER);
1434
1435         /* Set lookup ptr. */
1436         mpt_adapters[ioc->id] = ioc;
1437
1438         ioc->pci_irq = -1;
1439         if (pdev->irq) {
1440                 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1441
1442                 if (r < 0) {
1443 #ifndef __sparc__
1444                         printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n",
1445                                         ioc->name, pdev->irq);
1446 #else
1447                         printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
1448                                         ioc->name, __irq_itoa(pdev->irq));
1449 #endif
1450                         Q_DEL_ITEM(ioc);
1451                         mpt_adapters[ioc->id] = NULL;
1452                         iounmap(mem);
1453                         kfree(ioc);
1454                         return -EBUSY;
1455                 }
1456
1457                 ioc->pci_irq = pdev->irq;
1458
1459                 pci_set_master(pdev);                   /* ?? */
1460                 pci_set_drvdata(pdev, ioc);
1461
1462 #ifndef __sparc__
1463                 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
1464 #else
1465                 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));
1466 #endif
1467         }
1468
1469         /* NEW!  20010220 -sralston
1470          * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1471          */
1472         if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030)
1473                         || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X))
1474                 mpt_detect_bound_ports(ioc, pdev);
1475
1476         if ((r = mpt_do_ioc_recovery(ioc,
1477           MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) {
1478                 printk(KERN_WARNING MYNAM
1479                   ": WARNING - %s did not initialize properly! (%d)\n",
1480                   ioc->name, r);
1481
1482                 Q_DEL_ITEM(ioc);
1483                 mpt_adapters[ioc->id] = NULL;
1484                 free_irq(ioc->pci_irq, ioc);
1485                 iounmap(mem);
1486                 kfree(ioc);
1487                 pci_set_drvdata(pdev, NULL);
1488                 return r;
1489         }
1490
1491         /* call per device driver probe entry point */
1492         for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1493                 if(MptDeviceDriverHandlers[ii] &&
1494                   MptDeviceDriverHandlers[ii]->probe) {
1495                         MptDeviceDriverHandlers[ii]->probe(pdev,id);
1496                 }
1497         }
1498
1499         return 0;
1500 }
1501
1502 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1503 /*
1504  *      mptbase_remove - Remove a PCI intelligent MPT adapter.
1505  *      @pdev: Pointer to pci_dev structure
1506  *
1507  */
1508
1509 static void __devexit
1510 mptbase_remove(struct pci_dev *pdev)
1511 {
1512         MPT_ADAPTER     *ioc = pci_get_drvdata(pdev);
1513         int ii;
1514
1515         /* call per device driver remove entry point */
1516         for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1517                 if(MptDeviceDriverHandlers[ii] &&
1518                   MptDeviceDriverHandlers[ii]->remove) {
1519                         MptDeviceDriverHandlers[ii]->remove(pdev);
1520                 }
1521         }
1522
1523         /* Disable interrupts! */
1524         CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1525
1526         ioc->active = 0;
1527         synchronize_irq(pdev->irq);
1528
1529         /* Clear any lingering interrupt */
1530         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1531
1532         CHIPREG_READ32(&ioc->chip->IntStatus);
1533
1534         Q_DEL_ITEM(ioc);
1535         mpt_adapter_dispose(ioc);
1536
1537         pci_set_drvdata(pdev, NULL);
1538 }
1539
1540 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1541 /*
1542  *      mptbase_shutdown -
1543  *
1544  */
1545 static void
1546 mptbase_shutdown(struct device * dev)
1547 {
1548         int ii;
1549
1550         /* call per device driver shutdown entry point */
1551         for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1552                 if(MptDeviceDriverHandlers[ii] &&
1553                   MptDeviceDriverHandlers[ii]->shutdown) {
1554                         MptDeviceDriverHandlers[ii]->shutdown(dev);
1555                 }
1556         }
1557
1558 }
1559
1560
1561 /**************************************************************************
1562  * Power Management
1563  */
1564 #ifdef CONFIG_PM
1565 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1566 /*
1567  *      mptbase_suspend - Fusion MPT base driver suspend routine.
1568  *
1569  *
1570  */
1571 static int
1572 mptbase_suspend(struct pci_dev *pdev, u32 state)
1573 {
1574         u32 device_state;
1575         MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1576         int ii;
1577
1578         switch(state)
1579         {
1580                 case 1: /* S1 */
1581                         device_state=1; /* D1 */;
1582                         break;
1583                 case 3: /* S3 */
1584                 case 4: /* S4 */
1585                         device_state=3; /* D3 */;
1586                         break;
1587                 default:
1588                         return -EAGAIN /*FIXME*/;
1589                         break;
1590         }
1591
1592         printk(MYIOC_s_INFO_FMT
1593         "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1594                 ioc->name, pdev, pci_name(pdev), device_state);
1595
1596         /* call per device driver suspend entry point */
1597         for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1598                 if(MptDeviceDriverHandlers[ii] &&
1599                   MptDeviceDriverHandlers[ii]->suspend) {
1600                         MptDeviceDriverHandlers[ii]->suspend(pdev, state);
1601                 }
1602         }
1603
1604         pci_save_state(pdev, ioc->PciState);
1605
1606         /* put ioc into READY_STATE */
1607         if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1608                 printk(MYIOC_s_ERR_FMT
1609                 "pci-suspend:  IOC msg unit reset failed!\n", ioc->name);
1610         }
1611
1612         /* disable interrupts */
1613         CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1614         ioc->active = 0;
1615
1616         /* Clear any lingering interrupt */
1617         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1618
1619         pci_disable_device(pdev);
1620         pci_set_power_state(pdev, device_state);
1621
1622         return 0;
1623 }
1624
1625 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1626 /*
1627  *      mptbase_resume - Fusion MPT base driver resume routine.
1628  *
1629  *
1630  */
1631 static int
1632 mptbase_resume(struct pci_dev *pdev)
1633 {
1634         MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1635         u32 device_state = pdev->current_state;
1636         int recovery_state;
1637         int ii;
1638
1639         printk(MYIOC_s_INFO_FMT
1640         "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1641                 ioc->name, pdev, pci_name(pdev), device_state);
1642
1643         pci_set_power_state(pdev, 0);
1644         pci_restore_state(pdev, ioc->PciState);
1645         pci_enable_device(pdev);
1646
1647         /* enable interrupts */
1648         CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1649         ioc->active = 1;
1650
1651         /* F/W not running */
1652         if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
1653                 /* enable domain validation flags */
1654                 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
1655                         ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
1656                 }
1657         }
1658
1659         printk(MYIOC_s_INFO_FMT
1660                 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1661                 ioc->name,
1662                 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1663                 CHIPREG_READ32(&ioc->chip->Doorbell));
1664
1665         /* bring ioc to operational state */
1666         if ((recovery_state = mpt_do_ioc_recovery(ioc,
1667             MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1668                 printk(MYIOC_s_INFO_FMT
1669                         "pci-resume: Cannot recover, error:[%x]\n",
1670                         ioc->name, recovery_state);
1671         } else {
1672                 printk(MYIOC_s_INFO_FMT
1673                         "pci-resume: success\n", ioc->name);
1674         }
1675
1676         /* call per device driver resume entry point */
1677         for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1678                 if(MptDeviceDriverHandlers[ii] &&
1679                   MptDeviceDriverHandlers[ii]->resume) {
1680                         MptDeviceDriverHandlers[ii]->resume(pdev);
1681                 }
1682         }
1683
1684         return 0;
1685 }
1686 #endif
1687
1688 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1689 /*
1690  *      mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1691  *      @ioc: Pointer to MPT adapter structure
1692  *      @reason: Event word / reason
1693  *      @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1694  *
1695  *      This routine performs all the steps necessary to bring the IOC
1696  *      to a OPERATIONAL state.
1697  *
1698  *      This routine also pre-fetches the LAN MAC address of a Fibre Channel
1699  *      MPT adapter.
1700  *
1701  *      Returns:
1702  *               0 for success
1703  *              -1 if failed to get board READY
1704  *              -2 if READY but IOCFacts Failed
1705  *              -3 if READY but PrimeIOCFifos Failed
1706  *              -4 if READY but IOCInit Failed
1707  */
1708 static int
1709 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1710 {
1711         int      hard_reset_done = 0;
1712         int      alt_ioc_ready = 0;
1713         int      hard;
1714         int      r;
1715         int      ii;
1716         int      handlers;
1717         int      ret = 0;
1718         int      reset_alt_ioc_active = 0;
1719
1720         printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1721                         ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1722
1723         /* Disable reply interrupts (also blocks FreeQ) */
1724         CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1725         ioc->active = 0;
1726
1727         if (ioc->alt_ioc) {
1728                 if (ioc->alt_ioc->active)
1729                         reset_alt_ioc_active = 1;
1730
1731                 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1732                 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1733                 ioc->alt_ioc->active = 0;
1734         }
1735
1736         hard = 1;
1737         if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1738                 hard = 0;
1739
1740         if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1741                 if (hard_reset_done == -4) {
1742                         printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1743                                         ioc->name);
1744
1745                         if (reset_alt_ioc_active && ioc->alt_ioc) {
1746                                 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1747                                 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1748                                                 ioc->alt_ioc->name));
1749                                 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
1750                                 ioc->alt_ioc->active = 1;
1751                         }
1752
1753                 } else {
1754                         printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1755                                         ioc->name);
1756                 }
1757                 return -1;
1758         }
1759
1760         /* hard_reset_done = 0 if a soft reset was performed
1761          * and 1 if a hard reset was performed.
1762          */
1763         if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1764                 if ((r = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1765                         alt_ioc_ready = 1;
1766                 else
1767                         printk(KERN_WARNING MYNAM
1768                                         ": alt-%s: (%d) Not ready WARNING!\n",
1769                                         ioc->alt_ioc->name, r);
1770         }
1771
1772         /* Get IOC facts! Allow 1 retry */
1773         if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0)
1774                 r = GetIocFacts(ioc, sleepFlag, reason);
1775
1776         if (r) {
1777                 ret = -2;
1778         } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1779                 MptDisplayIocCapabilities(ioc);
1780         }
1781
1782         if (alt_ioc_ready) {
1783                 if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1784                         /* Retry - alt IOC was initialized once
1785                          */
1786                         r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1787                 }
1788                 if (r) {
1789                         alt_ioc_ready = 0;
1790                         reset_alt_ioc_active = 0;
1791                 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1792                         MptDisplayIocCapabilities(ioc->alt_ioc);
1793                 }
1794         }
1795
1796         /* Prime reply & request queues!
1797          * (mucho alloc's) Must be done prior to
1798          * init as upper addresses are needed for init.
1799          * If fails, continue with alt-ioc processing
1800          */
1801         if ((ret == 0) && ((r = PrimeIocFifos(ioc)) != 0))
1802                 ret = -3;
1803
1804         /* May need to check/upload firmware & data here!
1805          * If fails, continue with alt-ioc processing
1806          */
1807         if ((ret == 0) && ((r = SendIocInit(ioc, sleepFlag)) != 0))
1808                 ret = -4;
1809 // NEW!
1810         if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1811                 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1812                                 ioc->alt_ioc->name, r);
1813                 alt_ioc_ready = 0;
1814                 reset_alt_ioc_active = 0;
1815         }
1816
1817         if (alt_ioc_ready) {
1818                 if ((r = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1819                         alt_ioc_ready = 0;
1820                         reset_alt_ioc_active = 0;
1821                         printk(KERN_WARNING MYNAM
1822                                 ": alt-%s: (%d) init failure WARNING!\n",
1823                                         ioc->alt_ioc->name, r);
1824                 }
1825         }
1826
1827         if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1828                 if (ioc->upload_fw) {
1829                         ddlprintk((MYIOC_s_INFO_FMT
1830                                 "firmware upload required!\n", ioc->name));
1831
1832                         /* Controller is not operational, cannot do upload
1833                          */
1834                         if (ret == 0) {
1835                                 r = mpt_do_upload(ioc, sleepFlag);
1836                                 if (r != 0)
1837                                         printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1838                         }
1839
1840                         /* Handle the alt IOC too */
1841                         if ((alt_ioc_ready) && (ioc->alt_ioc->upload_fw)){
1842                                 ddlprintk((MYIOC_s_INFO_FMT
1843                                         "Alt-ioc firmware upload required!\n",
1844                                         ioc->name));
1845                                 r = mpt_do_upload(ioc->alt_ioc, sleepFlag);
1846                                 if (r != 0)
1847                                         printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1848                         }
1849                 }
1850         }
1851
1852         if (ret == 0) {
1853                 /* Enable! (reply interrupt) */
1854                 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1855                 ioc->active = 1;
1856         }
1857
1858         if (reset_alt_ioc_active && ioc->alt_ioc) {
1859                 /* (re)Enable alt-IOC! (reply interrupt) */
1860                 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1861                                 ioc->alt_ioc->name));
1862                 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
1863                 ioc->alt_ioc->active = 1;
1864         }
1865
1866         /* NEW!  20010120 -sralston
1867          *  Enable MPT base driver management of EventNotification
1868          *  and EventAck handling.
1869          */
1870         if ((ret == 0) && (!ioc->facts.EventState))
1871                 (void) SendEventNotification(ioc, 1);   /* 1=Enable EventNotification */
1872
1873         if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1874                 (void) SendEventNotification(ioc->alt_ioc, 1);  /* 1=Enable EventNotification */
1875
1876         /* (Bugzilla:fibrebugs, #513)
1877          * Bug fix (part 2)!  20010905 -sralston
1878          *      Add additional "reason" check before call to GetLanConfigPages
1879          *      (combined with GetIoUnitPage2 call).  This prevents a somewhat
1880          *      recursive scenario; GetLanConfigPages times out, timer expired
1881          *      routine calls HardResetHandler, which calls into here again,
1882          *      and we try GetLanConfigPages again...
1883          */
1884         if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1885                 if ((int)ioc->chip_type <= (int)FC929) {
1886                         /*
1887                          *  Pre-fetch FC port WWN and stuff...
1888                          *  (FCPortPage0_t stuff)
1889                          */
1890                         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1891                                 (void) GetFcPortPage0(ioc, ii);
1892                         }
1893
1894                         if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1895                             (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1896                                 /*
1897                                  *  Pre-fetch the ports LAN MAC address!
1898                                  *  (LANPage1_t stuff)
1899                                  */
1900                                 (void) GetLanConfigPages(ioc);
1901 #ifdef MPT_DEBUG
1902                                 {
1903                                         u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1904                                         dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1905                                                         ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1906                                 }
1907 #endif
1908                         }
1909                 } else {
1910                         /* Get NVRAM and adapter maximums from SPP 0 and 2
1911                          */
1912                         mpt_GetScsiPortSettings(ioc, 0);
1913
1914                         /* Get version and length of SDP 1
1915                          */
1916                         mpt_readScsiDevicePageHeaders(ioc, 0);
1917
1918                         /* Find IM volumes
1919                          */
1920                         if (ioc->facts.MsgVersion >= 0x0102)
1921                                 mpt_findImVolumes(ioc);
1922
1923                         /* Check, and possibly reset, the coalescing value
1924                          */
1925                         mpt_read_ioc_pg_1(ioc);
1926
1927                         mpt_read_ioc_pg_4(ioc);
1928                 }
1929
1930                 GetIoUnitPage2(ioc);
1931         }
1932
1933         /*
1934          * Call each currently registered protocol IOC reset handler
1935          * with post-reset indication.
1936          * NOTE: If we're doing _IOC_BRINGUP, there can be no
1937          * MptResetHandlers[] registered yet.
1938          */
1939         if (hard_reset_done) {
1940                 r = handlers = 0;
1941                 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1942                         if ((ret == 0) && MptResetHandlers[ii]) {
1943                                 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1944                                                 ioc->name, ii));
1945                                 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
1946                                 handlers++;
1947                         }
1948
1949                         if (alt_ioc_ready && MptResetHandlers[ii]) {
1950                                 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1951                                                 ioc->name, ioc->alt_ioc->name, ii));
1952                                 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
1953                                 handlers++;
1954                         }
1955                 }
1956                 /* FIXME?  Examine results here? */
1957         }
1958
1959         return ret;
1960 }
1961
1962 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1963 /*
1964  *      mpt_detect_bound_ports - Search for PCI bus/dev_function
1965  *      which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1966  *      929X, 1030 or 1035.
1967  *      @ioc: Pointer to MPT adapter structure
1968  *      @pdev: Pointer to (struct pci_dev) structure
1969  *
1970  *      If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1971  *      using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1972  */
1973 static void
1974 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1975 {
1976         MPT_ADAPTER *ioc_srch = mpt_adapter_find_first();
1977         unsigned int match_lo, match_hi;
1978
1979         match_lo = pdev->devfn-1;
1980         match_hi = pdev->devfn+1;
1981         dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
1982                         ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi));
1983
1984         while (ioc_srch != NULL) {
1985                 struct pci_dev *_pcidev = ioc_srch->pcidev;
1986
1987                 if ((_pcidev->device == pdev->device) &&
1988                     (_pcidev->bus->number == pdev->bus->number) &&
1989                     (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
1990                         /* Paranoia checks */
1991                         if (ioc->alt_ioc != NULL) {
1992                                 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1993                                                 ioc->name, ioc->alt_ioc->name);
1994                                 break;
1995                         } else if (ioc_srch->alt_ioc != NULL) {
1996                                 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1997                                                 ioc_srch->name, ioc_srch->alt_ioc->name);
1998                                 break;
1999                         }
2000                         dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
2001                                         ioc->name, ioc_srch->name));
2002                         ioc_srch->alt_ioc = ioc;
2003                         ioc->alt_ioc = ioc_srch;
2004                         break;
2005                 }
2006                 ioc_srch = mpt_adapter_find_next(ioc_srch);
2007         }
2008 }
2009
2010 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2011 /*
2012  *      mpt_adapter_disable - Disable misbehaving MPT adapter.
2013  *      @this: Pointer to MPT adapter structure
2014  *      @free: Free up alloc'd reply, request, etc.
2015  */
2016 static void
2017 mpt_adapter_disable(MPT_ADAPTER *this, int freeup)
2018 {
2019         if (this != NULL) {
2020                 int sz=0;
2021                 u32 state;
2022                 int ret;
2023
2024                 /* Disable the FW */
2025                 state = mpt_GetIocState(this, 1);
2026                 if (state == MPI_IOC_STATE_OPERATIONAL) {
2027                         SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP);
2028                 }
2029
2030                 if (this->cached_fw != NULL) {
2031                         ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n"));
2032
2033                         if ((ret = mpt_downloadboot(this, NO_SLEEP)) < 0) {
2034                                 printk(KERN_WARNING MYNAM
2035                                         ": firmware downloadboot failure (%d)!\n", ret);
2036                         }
2037                 }
2038
2039                 /* Disable adapter interrupts! */
2040                 CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
2041                 this->active = 0;
2042                 /* Clear any lingering interrupt */
2043                 CHIPREG_WRITE32(&this->chip->IntStatus, 0);
2044
2045                 if (freeup && this->fifo_pool != NULL) {
2046                         pci_free_consistent(this->pcidev,
2047                                 this->fifo_pool_sz,
2048                                 this->fifo_pool, this->fifo_pool_dma);
2049                         this->reply_frames = NULL;
2050                         this->reply_alloc = NULL;
2051                         this->req_frames = NULL;
2052                         this->req_alloc = NULL;
2053                         this->chain_alloc = NULL;
2054                         this->fifo_pool = NULL;
2055                         this->alloc_total -= this->fifo_pool_sz;
2056                 }
2057                 if (freeup && this->sense_buf_pool != NULL) {
2058                         sz = (this->req_depth * MPT_SENSE_BUFFER_ALLOC);
2059                         pci_free_consistent(this->pcidev, sz,
2060                                         this->sense_buf_pool, this->sense_buf_pool_dma);
2061                         this->sense_buf_pool = NULL;
2062                         this->alloc_total -= sz;
2063                 }
2064
2065                 if (freeup && this->events != NULL){
2066                         sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2067                         kfree(this->events);
2068                         this->events = NULL;
2069                         this->alloc_total -= sz;
2070                 }
2071
2072                 if (freeup && this->cached_fw != NULL) {
2073                         int ii = 0;
2074
2075                         while ((ii < this->num_fw_frags) && (this->cached_fw[ii]!= NULL)) {
2076                                 sz = this->cached_fw[ii]->size;
2077                                 pci_free_consistent(this->pcidev, sz,
2078                                         this->cached_fw[ii]->fw, this->cached_fw[ii]->fw_dma);
2079                                 this->cached_fw[ii]->fw = NULL;
2080                                 this->alloc_total -= sz;
2081
2082                                 kfree(this->cached_fw[ii]);
2083                                 this->cached_fw[ii] = NULL;
2084                                 this->alloc_total -= sizeof(fw_image_t);
2085
2086                                 ii++;
2087                         }
2088
2089                         kfree(this->cached_fw);
2090                         this->cached_fw = NULL;
2091                         sz = this->num_fw_frags * sizeof(void *);
2092                         this->alloc_total -= sz;
2093                 }
2094
2095                 if (freeup && this->spi_data.nvram != NULL) {
2096                         kfree(this->spi_data.nvram);
2097                         this->spi_data.nvram = NULL;
2098                 }
2099
2100                 if (freeup && this->spi_data.pIocPg3 != NULL) {
2101                         kfree(this->spi_data.pIocPg3);
2102                         this->spi_data.pIocPg3 = NULL;
2103                 }
2104
2105                 if (freeup && this->spi_data.pIocPg4 != NULL) {
2106                         sz = this->spi_data.IocPg4Sz;
2107                         pci_free_consistent(this->pcidev, sz,
2108                                 this->spi_data.pIocPg4,
2109                                 this->spi_data.IocPg4_dma);
2110                         this->spi_data.pIocPg4 = NULL;
2111                         this->alloc_total -= sz;
2112                 }
2113         }
2114 }
2115
2116 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2117 /*
2118  *      mpt_adapter_dispose - Free all resources associated with a MPT
2119  *      adapter.
2120  *      @this: Pointer to MPT adapter structure
2121  *
2122  *      This routine unregisters h/w resources and frees all alloc'd memory
2123  *      associated with a MPT adapter structure.
2124  */
2125 static void
2126 mpt_adapter_dispose(MPT_ADAPTER *this)
2127 {
2128         if (this != NULL) {
2129                 int sz_first, sz_last;
2130
2131                 sz_first = this->alloc_total;
2132
2133                 if (this->alt_ioc != NULL) {
2134                         this->alt_ioc->alt_ioc = NULL;
2135                         this->alt_ioc = NULL;
2136                 }
2137
2138                 mpt_adapter_disable(this, 1);
2139
2140                 if (this->pci_irq != -1) {
2141                         free_irq(this->pci_irq, this);
2142                         this->pci_irq = -1;
2143                 }
2144
2145                 if (this->memmap != NULL)
2146                         iounmap((u8 *) this->memmap);
2147
2148 #if defined(CONFIG_MTRR) && 0
2149                 if (this->mtrr_reg > 0) {
2150                         mtrr_del(this->mtrr_reg, 0, 0);
2151                         dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name));
2152                 }
2153 #endif
2154
2155                 /*  Zap the adapter lookup ptr!  */
2156                 mpt_adapters[this->id] = NULL;
2157
2158                 sz_last = this->alloc_total;
2159                 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2160                                 this->name, sz_first-sz_last+(int)sizeof(*this), sz_first));
2161                 kfree(this);
2162         }
2163 }
2164
2165 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2166 /*
2167  *      MptDisplayIocCapabilities - Disply IOC's capacilities.
2168  *      @ioc: Pointer to MPT adapter structure
2169  */
2170 static void
2171 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2172 {
2173         int i = 0;
2174
2175         printk(KERN_INFO "%s: ", ioc->name);
2176         if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2177                 printk("%s: ", ioc->prod_name+3);
2178         printk("Capabilities={");
2179
2180         if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2181                 printk("Initiator");
2182                 i++;
2183         }
2184
2185         if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2186                 printk("%sTarget", i ? "," : "");
2187                 i++;
2188         }
2189
2190         if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2191                 printk("%sLAN", i ? "," : "");
2192                 i++;
2193         }
2194
2195 #if 0
2196         /*
2197          *  This would probably evoke more questions than it's worth
2198          */
2199         if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2200                 printk("%sLogBusAddr", i ? "," : "");
2201                 i++;
2202         }
2203 #endif
2204
2205         printk("}\n");
2206 }
2207
2208 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2209 /*
2210  *      MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2211  *      @ioc: Pointer to MPT_ADAPTER structure
2212  *      @force: Force hard KickStart of IOC
2213  *      @sleepFlag: Specifies whether the process can sleep
2214  *
2215  *      Returns:
2216  *               1 - DIAG reset and READY
2217  *               0 - READY initially OR soft reset and READY
2218  *              -1 - Any failure on KickStart
2219  *              -2 - Msg Unit Reset Failed
2220  *              -3 - IO Unit Reset Failed
2221  *              -4 - IOC owned by a PEER
2222  */
2223 static int
2224 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2225 {
2226         u32      ioc_state;
2227         int      statefault = 0;
2228         int      cntdn;
2229         int      hard_reset_done = 0;
2230         int      r;
2231         int      ii;
2232         int      whoinit;
2233
2234         /* Get current [raw] IOC state  */
2235         ioc_state = mpt_GetIocState(ioc, 0);
2236         dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2237
2238         /*
2239          *      Check to see if IOC got left/stuck in doorbell handshake
2240          *      grip of death.  If so, hard reset the IOC.
2241          */
2242         if (ioc_state & MPI_DOORBELL_ACTIVE) {
2243                 statefault = 1;
2244                 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2245                                 ioc->name);
2246         }
2247
2248         /* Is it already READY? */
2249         if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) {
2250                 if ((int)ioc->chip_type <= (int)FC929)
2251                         return 0;
2252                 else {
2253                         /* Workaround from broken 1030 FW.
2254                          * Force a diagnostic reset if fails.
2255                          */
2256                         if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2257                                 return 0;
2258                         else
2259                                 statefault = 4;
2260                 }
2261         }
2262
2263         /*
2264          *      Check to see if IOC is in FAULT state.
2265          */
2266         if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2267                 statefault = 2;
2268                 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2269                                 ioc->name);
2270                 printk(KERN_WARNING "           FAULT code = %04xh\n",
2271                                 ioc_state & MPI_DOORBELL_DATA_MASK);
2272         }
2273
2274         /*
2275          *      Hmmm...  Did it get left operational?
2276          */
2277         if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2278                 dprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
2279                                 ioc->name));
2280
2281                 /* Check WhoInit.
2282                  * If PCI Peer, exit.
2283                  * Else, if no fault conditions are present, issue a MessageUnitReset
2284                  * Else, fall through to KickStart case
2285                  */
2286                 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2287                 dprintk((KERN_WARNING MYNAM
2288                         ": whoinit 0x%x\n statefault %d force %d\n",
2289                         whoinit, statefault, force));
2290                 if (whoinit == MPI_WHOINIT_PCI_PEER)
2291                         return -4;
2292                 else {
2293                         if ((statefault == 0 ) && (force == 0)) {
2294                                 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2295                                         return 0;
2296                         }
2297                         statefault = 3;
2298                 }
2299         }
2300
2301         hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2302         if (hard_reset_done < 0)
2303                 return -1;
2304
2305         /*
2306          *  Loop here waiting for IOC to come READY.
2307          */
2308         ii = 0;
2309         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15;    /* 15 seconds */
2310
2311         while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2312                 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2313                         /*
2314                          *  BIOS or previous driver load left IOC in OP state.
2315                          *  Reset messaging FIFOs.
2316                          */
2317                         if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2318                                 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2319                                 return -2;
2320                         }
2321                 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2322                         /*
2323                          *  Something is wrong.  Try to get IOC back
2324                          *  to a known state.
2325                          */
2326                         if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2327                                 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2328                                 return -3;
2329                         }
2330                 }
2331
2332                 ii++; cntdn--;
2333                 if (!cntdn) {
2334                         printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2335                                         ioc->name, (ii+5)/HZ);
2336                         return -ETIME;
2337                 }
2338
2339                 if (sleepFlag == CAN_SLEEP) {
2340                         set_current_state(TASK_INTERRUPTIBLE);
2341                         schedule_timeout(1);
2342                 } else {
2343                         mdelay (1);     /* 1 msec delay */
2344                 }
2345
2346         }
2347
2348         if (statefault < 3) {
2349                 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2350                                 ioc->name,
2351                                 statefault==1 ? "stuck handshake" : "IOC FAULT");
2352         }
2353
2354         return hard_reset_done;
2355 }
2356
2357 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2358 /*
2359  *      mpt_GetIocState - Get the current state of a MPT adapter.
2360  *      @ioc: Pointer to MPT_ADAPTER structure
2361  *      @cooked: Request raw or cooked IOC state
2362  *
2363  *      Returns all IOC Doorbell register bits if cooked==0, else just the
2364  *      Doorbell bits in MPI_IOC_STATE_MASK.
2365  */
2366 u32
2367 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2368 {
2369         u32 s, sc;
2370
2371         /*  Get!  */
2372         s = CHIPREG_READ32(&ioc->chip->Doorbell);
2373 //      dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2374         sc = s & MPI_IOC_STATE_MASK;
2375
2376         /*  Save!  */
2377         ioc->last_state = sc;
2378
2379         return cooked ? sc : s;
2380 }
2381
2382 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2383 /*
2384  *      GetIocFacts - Send IOCFacts request to MPT adapter.
2385  *      @ioc: Pointer to MPT_ADAPTER structure
2386  *      @sleepFlag: Specifies whether the process can sleep
2387  *      @reason: If recovery, only update facts.
2388  *
2389  *      Returns 0 for success, non-zero for failure.
2390  */
2391 static int
2392 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2393 {
2394         IOCFacts_t               get_facts;
2395         IOCFactsReply_t         *facts;
2396         int                      r;
2397         int                      req_sz;
2398         int                      reply_sz;
2399         u32                      status;
2400
2401         /* IOC *must* NOT be in RESET state! */
2402         if (ioc->last_state == MPI_IOC_STATE_RESET) {
2403                 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2404                                 ioc->name,
2405                                 ioc->last_state );
2406                 return -44;
2407         }
2408
2409         facts = &ioc->facts;
2410
2411         /* Destination (reply area)... */
2412         reply_sz = sizeof(*facts);
2413         memset(facts, 0, reply_sz);
2414
2415         /* Request area (get_facts on the stack right now!) */
2416         req_sz = sizeof(get_facts);
2417         memset(&get_facts, 0, req_sz);
2418
2419         get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2420         /* Assert: All other get_facts fields are zero! */
2421
2422         dprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name));
2423
2424         /* No non-zero fields in the get_facts request are greater than
2425          * 1 byte in size, so we can just fire it off as is.
2426          */
2427         r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2428                         reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2429         if (r != 0)
2430                 return r;
2431
2432         /*
2433          * Now byte swap (GRRR) the necessary fields before any further
2434          * inspection of reply contents.
2435          *
2436          * But need to do some sanity checks on MsgLength (byte) field
2437          * to make sure we don't zero IOC's req_sz!
2438          */
2439         /* Did we get a valid reply? */
2440         if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2441                 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2442                         /*
2443                          * If not been here, done that, save off first WhoInit value
2444                          */
2445                         if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2446                                 ioc->FirstWhoInit = facts->WhoInit;
2447                 }
2448
2449                 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2450                 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2451                 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2452                 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2453                 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2454                 status = facts->IOCStatus & MPI_IOCSTATUS_MASK;
2455                 /* CHECKME! IOCStatus, IOCLogInfo */
2456
2457                 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2458                 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2459
2460                 /*
2461                  * FC f/w version changed between 1.1 and 1.2
2462                  *      Old: u16{Major(4),Minor(4),SubMinor(8)}
2463                  *      New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2464                  */
2465                 if (facts->MsgVersion < 0x0102) {
2466                         /*
2467                          *      Handle old FC f/w style, convert to new...
2468                          */
2469                         u16      oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2470                         facts->FWVersion.Word =
2471                                         ((oldv<<12) & 0xFF000000) |
2472                                         ((oldv<<8)  & 0x000FFF00);
2473                 } else
2474                         facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2475
2476                 facts->ProductID = le16_to_cpu(facts->ProductID);
2477                 facts->CurrentHostMfaHighAddr =
2478                                 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2479                 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2480                 facts->CurrentSenseBufferHighAddr =
2481                                 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2482                 facts->CurReplyFrameSize =
2483                                 le16_to_cpu(facts->CurReplyFrameSize);
2484
2485                 /*
2486                  * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2487                  * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2488                  * to 14 in MPI-1.01.0x.
2489                  */
2490                 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2491                     facts->MsgVersion > 0x0100) {
2492                         facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2493                 }
2494
2495                 if (!facts->RequestFrameSize) {
2496                         /*  Something is wrong!  */
2497                         printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2498                                         ioc->name);
2499                         return -55;
2500                 }
2501
2502                 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2503                         /*
2504                          * Set values for this IOC's request & reply frame sizes,
2505                          * and request & reply queue depths...
2506                          */
2507                         ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2508                         ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2509                         ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2510                         ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2511
2512                         dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2513                                 ioc->name, ioc->reply_sz, ioc->reply_depth));
2514                         dprintk((MYIOC_s_INFO_FMT "req_sz  =%3d, req_depth  =%4d\n",
2515                                 ioc->name, ioc->req_sz, ioc->req_depth));
2516
2517                         /* Get port facts! */
2518                         if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2519                                 return r;
2520                 }
2521         } else {
2522                 printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply!\n",
2523                                 ioc->name);
2524                 return -66;
2525         }
2526
2527         return 0;
2528 }
2529
2530 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2531 /*
2532  *      GetPortFacts - Send PortFacts request to MPT adapter.
2533  *      @ioc: Pointer to MPT_ADAPTER structure
2534  *      @portnum: Port number
2535  *      @sleepFlag: Specifies whether the process can sleep
2536  *
2537  *      Returns 0 for success, non-zero for failure.
2538  */
2539 static int
2540 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2541 {
2542         PortFacts_t              get_pfacts;
2543         PortFactsReply_t        *pfacts;
2544         int                      ii;
2545         int                      req_sz;
2546         int                      reply_sz;
2547
2548         /* IOC *must* NOT be in RESET state! */
2549         if (ioc->last_state == MPI_IOC_STATE_RESET) {
2550                 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2551                                 ioc->name,
2552                                 ioc->last_state );
2553                 return -4;
2554         }
2555
2556         pfacts = &ioc->pfacts[portnum];
2557
2558         /* Destination (reply area)...  */
2559         reply_sz = sizeof(*pfacts);
2560         memset(pfacts, 0, reply_sz);
2561
2562         /* Request area (get_pfacts on the stack right now!) */
2563         req_sz = sizeof(get_pfacts);
2564         memset(&get_pfacts, 0, req_sz);
2565
2566         get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2567         get_pfacts.PortNumber = portnum;
2568         /* Assert: All other get_pfacts fields are zero! */
2569
2570         dprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2571                         ioc->name, portnum));
2572
2573         /* No non-zero fields in the get_pfacts request are greater than
2574          * 1 byte in size, so we can just fire it off as is.
2575          */
2576         ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2577                                 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2578         if (ii != 0)
2579                 return ii;
2580
2581         /* Did we get a valid reply? */
2582
2583         /* Now byte swap the necessary fields in the response. */
2584         pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2585         pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2586         pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2587         pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2588         pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2589         pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2590         pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2591         pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2592         pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2593
2594         return 0;
2595 }
2596
2597 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2598 /*
2599  *      SendIocInit - Send IOCInit request to MPT adapter.
2600  *      @ioc: Pointer to MPT_ADAPTER structure
2601  *      @sleepFlag: Specifies whether the process can sleep
2602  *
2603  *      Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2604  *
2605  *      Returns 0 for success, non-zero for failure.
2606  */
2607 static int
2608 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2609 {
2610         IOCInit_t                ioc_init;
2611         MPIDefaultReply_t        init_reply;
2612         u32                      state;
2613         int                      r;
2614         int                      count;
2615         int                      cntdn;
2616
2617         memset(&ioc_init, 0, sizeof(ioc_init));
2618         memset(&init_reply, 0, sizeof(init_reply));
2619
2620         ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2621 /*      ioc_init.ChainOffset = 0;                       */
2622         ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2623 /*      ioc_init.Flags = 0;                             */
2624
2625         /* If we are in a recovery mode and we uploaded the FW image,
2626          * then this pointer is not NULL. Skip the upload a second time.
2627          * Set this flag if cached_fw set for either IOC.
2628          */
2629         ioc->upload_fw = 0;
2630         ioc_init.Flags = 0;
2631         if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
2632                 if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw))
2633                         ioc_init.Flags = MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE;
2634                 else
2635                         ioc->upload_fw = 1;
2636         }
2637         ddlprintk((MYIOC_s_INFO_FMT "flags %d, upload_fw %d \n",
2638                    ioc->name, ioc_init.Flags, ioc->upload_fw));
2639
2640         if ((int)ioc->chip_type <= (int)FC929) {
2641                 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2642         } else {
2643                 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2644         }
2645         ioc_init.MaxBuses = MPT_MAX_BUS;
2646
2647 /*      ioc_init.MsgFlags = 0;                          */
2648 /*      ioc_init.MsgContext = cpu_to_le32(0x00000000);  */
2649         ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);   /* in BYTES */
2650                 
2651         ioc->facts.RequestFrameSize = ioc_init.ReplyFrameSize;
2652
2653         if (sizeof(dma_addr_t) == sizeof(u64)) {
2654                 /* Save the upper 32-bits of the request
2655                  * (reply) and sense buffers.
2656                  */
2657                 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32));
2658                 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2659         } else {
2660                 /* Force 32-bit addressing */
2661                 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2662                 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2663         }
2664                 
2665         ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2666         ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2667
2668         dprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2669                         ioc->name, &ioc_init));
2670
2671         r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2672                                 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2673         if (r != 0)
2674                 return r;
2675
2676         /* No need to byte swap the multibyte fields in the reply
2677          * since we don't even look at it's contents.
2678          */
2679
2680         if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0)
2681                 return r;
2682
2683         /* YIKES!  SUPER IMPORTANT!!!
2684          *  Poll IocState until _OPERATIONAL while IOC is doing
2685          *  LoopInit and TargetDiscovery!
2686          */
2687         count = 0;
2688         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60;    /* 60 seconds */
2689         state = mpt_GetIocState(ioc, 1);
2690         while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2691                 if (sleepFlag == CAN_SLEEP) {
2692                         set_current_state(TASK_INTERRUPTIBLE);
2693                         schedule_timeout(1);
2694                 } else {
2695                         mdelay(1);
2696                 }
2697
2698                 if (!cntdn) {
2699                         printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2700                                         ioc->name, (count+5)/HZ);
2701                         return -9;
2702                 }
2703
2704                 state = mpt_GetIocState(ioc, 1);
2705                 count++;
2706         }
2707         dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2708                         ioc->name, count));
2709
2710         return r;
2711 }
2712
2713 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2714 /*
2715  *      SendPortEnable - Send PortEnable request to MPT adapter port.
2716  *      @ioc: Pointer to MPT_ADAPTER structure
2717  *      @portnum: Port number to enable
2718  *      @sleepFlag: Specifies whether the process can sleep
2719  *
2720  *      Send PortEnable to bring IOC to OPERATIONAL state.
2721  *
2722  *      Returns 0 for success, non-zero for failure.
2723  */
2724 static int
2725 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2726 {
2727         PortEnable_t             port_enable;
2728         MPIDefaultReply_t        reply_buf;
2729         int      ii;
2730         int      req_sz;
2731         int      reply_sz;
2732
2733         /*  Destination...  */
2734         reply_sz = sizeof(MPIDefaultReply_t);
2735         memset(&reply_buf, 0, reply_sz);
2736
2737         req_sz = sizeof(PortEnable_t);
2738         memset(&port_enable, 0, req_sz);
2739
2740         port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2741         port_enable.PortNumber = portnum;
2742 /*      port_enable.ChainOffset = 0;            */
2743 /*      port_enable.MsgFlags = 0;               */
2744 /*      port_enable.MsgContext = 0;             */
2745
2746         dprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2747                         ioc->name, portnum, &port_enable));
2748
2749         /* RAID FW may take a long time to enable
2750          */
2751         if ((int)ioc->chip_type <= (int)FC929) {
2752                 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
2753                                 reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag);
2754         } else {
2755                 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
2756                                 reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
2757         }
2758
2759         if (ii != 0)
2760                 return ii;
2761
2762         /* We do not even look at the reply, so we need not
2763          * swap the multi-byte fields.
2764          */
2765
2766         return 0;
2767 }
2768
2769 /*
2770  * Inputs: size - total FW bytes
2771  * Outputs: frags - number of fragments needed
2772  * Return NULL if failed.
2773  */
2774 void *
2775 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz)
2776 {
2777         fw_image_t      **cached_fw;
2778         u8              *mem;
2779         dma_addr_t      fw_dma;
2780         int             alloc_total = 0;
2781         int             bytes_left, bytes, num_frags;
2782         int             sz, ii;
2783
2784         /* cached_fw
2785          */
2786         sz = ioc->num_fw_frags * sizeof(void *);
2787         mem = kmalloc(sz, GFP_ATOMIC);
2788         if (mem == NULL)
2789                 return NULL;
2790
2791         memset(mem, 0, sz);
2792         cached_fw = (fw_image_t **)mem;
2793         alloc_total += sz;
2794
2795         /* malloc fragment memory
2796          * fw_image_t struct and dma for fw data
2797          */
2798         bytes_left = size;
2799         ii = 0;
2800         num_frags = 0;
2801         bytes = bytes_left;
2802         while((bytes_left) && (num_frags < ioc->num_fw_frags)) {
2803                 if (cached_fw[ii] == NULL) {
2804                         mem = kmalloc(sizeof(fw_image_t), GFP_ATOMIC);
2805                         if (mem == NULL)
2806                                 break;
2807
2808                         memset(mem, 0, sizeof(fw_image_t));
2809                         cached_fw[ii] = (fw_image_t *)mem;
2810                         alloc_total += sizeof(fw_image_t);
2811                 }
2812
2813                 mem = pci_alloc_consistent(ioc->pcidev, bytes, &fw_dma);
2814                 if (mem == NULL) {
2815                         if (bytes > 0x10000)
2816                                 bytes = 0x10000;
2817                         else if (bytes > 0x8000)
2818                                 bytes = 0x8000;
2819                         else if (bytes > 0x4000)
2820                                 bytes = 0x4000;
2821                         else if (bytes > 0x2000)
2822                                 bytes = 0x2000;
2823                         else if (bytes > 0x1000)
2824                                 bytes = 0x1000;
2825                         else
2826                                 break;
2827
2828                         continue;
2829                 }
2830
2831                 cached_fw[ii]->fw = mem;
2832                 cached_fw[ii]->fw_dma = fw_dma;
2833                 cached_fw[ii]->size = bytes;
2834                 memset(mem, 0, bytes);
2835                 alloc_total += bytes;
2836
2837                 bytes_left -= bytes;
2838
2839                 num_frags++;
2840                 ii++;
2841         }
2842
2843         if (bytes_left ) {
2844                 /* Major Failure.
2845                  */
2846                 mpt_free_fw_memory(ioc, cached_fw);
2847                 return NULL;
2848         }
2849
2850         *frags = num_frags;
2851         *alloc_sz = alloc_total;
2852
2853         return (void *) cached_fw;
2854 }
2855
2856 /*
2857  * If alt_img is NULL, delete from ioc structure.
2858  * Else, delete a secondary image in same format.
2859  */
2860 void
2861 mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img)
2862 {
2863         fw_image_t **cached_fw;
2864         int ii;
2865         int sz;
2866         int alloc_freed = 0;
2867
2868         if (alt_img != NULL)
2869                 cached_fw = alt_img;
2870         else
2871                 cached_fw = ioc->cached_fw;
2872
2873         if (cached_fw == NULL)
2874                 return;
2875
2876         ii = 0;
2877         while ((ii < ioc->num_fw_frags) && (cached_fw[ii]!= NULL)) {
2878                 sz = cached_fw[ii]->size;
2879                 if (sz > 0) {
2880                         pci_free_consistent(ioc->pcidev, sz,
2881                                                 cached_fw[ii]->fw, cached_fw[ii]->fw_dma);
2882                 }
2883                 cached_fw[ii]->fw = NULL;
2884                 alloc_freed += sz;
2885
2886                 kfree(cached_fw[ii]);
2887                 cached_fw[ii] = NULL;
2888                 alloc_freed += sizeof(fw_image_t);
2889
2890                 ii++;
2891         }
2892
2893         kfree(cached_fw);
2894         cached_fw = NULL;
2895         sz = ioc->num_fw_frags * sizeof(void *);
2896         alloc_freed += sz;
2897
2898         if (alt_img == NULL)
2899                 ioc->alloc_total -= alloc_freed;
2900
2901         return;
2902 }
2903
2904
2905 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2906 /*
2907  *      mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2908  *      @ioc: Pointer to MPT_ADAPTER structure
2909  *      @sleepFlag: Specifies whether the process can sleep
2910  *
2911  *      Returns 0 for success, >0 for handshake failure
2912  *              <0 for fw upload failure.
2913  *
2914  *      Remark: If bound IOC and a successful FWUpload was performed
2915  *      on the bound IOC, the second image is discarded
2916  *      and memory is free'd. Both channels must upload to prevent
2917  *      IOC from running in degraded mode.
2918  */
2919 static int
2920 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2921 {
2922         u8                       request[ioc->req_sz];
2923         u8                       reply[sizeof(FWUploadReply_t)];
2924         FWUpload_t              *prequest;
2925         FWUploadReply_t         *preply;
2926         FWUploadTCSGE_t         *ptcsge;
2927         int                      sgeoffset;
2928         int                      ii, sz, reply_sz;
2929         int                      cmdStatus, freeMem = 0;
2930         int                      num_frags, alloc_sz;
2931
2932         /* If the image size is 0 or if the pointer is
2933          * not NULL (error), we are done.
2934          */
2935         if (((sz = ioc->facts.FWImageSize) == 0) || ioc->cached_fw)
2936                 return 0;
2937
2938         ioc->num_fw_frags = ioc->req_sz - sizeof(FWUpload_t) + sizeof(dma_addr_t) + sizeof(u32) -1;
2939         ioc->num_fw_frags /= sizeof(dma_addr_t) + sizeof(u32);
2940
2941         ioc->cached_fw = (fw_image_t **) mpt_alloc_fw_memory(ioc,
2942                         ioc->facts.FWImageSize, &num_frags, &alloc_sz);
2943
2944         if (ioc->cached_fw == NULL) {
2945                 /* Major Failure.
2946                  */
2947                 mpt_free_fw_memory(ioc, NULL);
2948                 ioc->cached_fw = NULL;
2949                 
2950                 return -ENOMEM;
2951         }
2952         ioc->alloc_total += alloc_sz;
2953
2954         ddlprintk((KERN_INFO MYNAM ": FW Image  @ %p, sz=%d bytes\n",
2955                  (void *)(ulong)ioc->cached_fw, ioc->facts.FWImageSize));
2956
2957         prequest = (FWUpload_t *)&request;
2958         preply = (FWUploadReply_t *)&reply;
2959
2960         /*  Destination...  */
2961         memset(prequest, 0, ioc->req_sz);
2962
2963         reply_sz = sizeof(reply);
2964         memset(preply, 0, reply_sz);
2965
2966         prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2967         prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2968         prequest->MsgContext = 0;               /* anything */
2969
2970         ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2971         ptcsge->Reserved = 0;
2972         ptcsge->ContextSize = 0;
2973         ptcsge->DetailsLength = 12;
2974         ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2975         ptcsge->Reserved1 = 0;
2976         ptcsge->ImageOffset = 0;
2977         ptcsge->ImageSize = cpu_to_le32(sz);
2978
2979         sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2980
2981         for (ii = 0; ii < (num_frags-1); ii++) {
2982                 mpt_add_sge(&request[sgeoffset], MPT_SGE_FLAGS_SIMPLE_ELEMENT | 
2983                         MPT_SGE_FLAGS_ADDRESSING | MPT_TRANSFER_IOC_TO_HOST |
2984                         (u32) ioc->cached_fw[ii]->size, ioc->cached_fw[ii]->fw_dma);
2985
2986                 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2987         }
2988
2989         mpt_add_sge(&request[sgeoffset],
2990                         MPT_SGE_FLAGS_SSIMPLE_READ |(u32) ioc->cached_fw[ii]->size,
2991                         ioc->cached_fw[ii]->fw_dma);
2992
2993         sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2994
2995         dprintk((MYIOC_s_INFO_FMT "Sending FW Upload (req @ %p) size %d \n",
2996                         ioc->name, prequest, sgeoffset));
2997
2998         ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2999                                 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
3000
3001         cmdStatus = -EFAULT;
3002         if (ii == 0) {
3003                 /* Handshake transfer was complete and successful.
3004                  * Check the Reply Frame.
3005                  */
3006                 int status, transfer_sz;
3007                 status = le16_to_cpu(preply->IOCStatus);
3008                 if (status == MPI_IOCSTATUS_SUCCESS) {
3009                         transfer_sz = le32_to_cpu(preply->ActualImageSize);
3010                         if (transfer_sz == sz)
3011                                 cmdStatus = 0;
3012                 }
3013         }
3014         ddlprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
3015                         ioc->name, cmdStatus));
3016
3017         /* Check to see if we have a copy of this image in
3018          * host memory already.
3019          */
3020         if (cmdStatus == 0) {
3021                 ioc->upload_fw = 0;
3022                 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
3023                         freeMem = 1;
3024         }
3025
3026         /* We already have a copy of this image or
3027          * we had some type of an error  - either the handshake
3028          * failed (i != 0) or the command did not complete successfully.
3029          */
3030         if (cmdStatus || freeMem) {
3031
3032                 ddlprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n",
3033                         ioc->name, cmdStatus ? "incomplete" : "duplicate"));
3034                 mpt_free_fw_memory(ioc, NULL);
3035                 ioc->cached_fw = NULL;
3036         }
3037
3038         return cmdStatus;
3039 }
3040
3041 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3042 /*
3043  *      mpt_downloadboot - DownloadBoot code
3044  *      @ioc: Pointer to MPT_ADAPTER structure
3045  *      @flag: Specify which part of IOC memory is to be uploaded.
3046  *      @sleepFlag: Specifies whether the process can sleep
3047  *
3048  *      FwDownloadBoot requires Programmed IO access.
3049  *
3050  *      Returns 0 for success
3051  *              -1 FW Image size is 0
3052  *              -2 No valid cached_fw Pointer
3053  *              <0 for fw upload failure.
3054  */
3055 static int
3056 mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
3057 {
3058         MpiFwHeader_t           *FwHdr;
3059         MpiExtImageHeader_t     *ExtHdr;
3060         fw_image_t              **pCached=NULL;
3061         int                      fw_sz;
3062         u32                      diag0val;
3063 #ifdef MPT_DEBUG
3064         u32                      diag1val = 0;
3065 #endif
3066         int                      count = 0;
3067         u32                     *ptru32;
3068         u32                      diagRwData;
3069         u32                      nextImage;
3070         u32                      ext_offset;
3071         u32                      load_addr;
3072         int                      max_idx, fw_idx, ext_idx;
3073         int                      left_u32s;
3074
3075         ddlprintk((MYIOC_s_INFO_FMT "DbGb0: downloadboot entered.\n",
3076                                 ioc->name));
3077 #ifdef MPT_DEBUG
3078         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3079         if (ioc->alt_ioc)
3080                 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3081         ddlprintk((MYIOC_s_INFO_FMT "DbGb1: diag0=%08x, diag1=%08x\n",
3082                                 ioc->name, diag0val, diag1val));
3083 #endif
3084
3085         ddlprintk((MYIOC_s_INFO_FMT "fw size 0x%x, ioc FW Ptr %p\n",
3086                                 ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
3087         if (ioc->alt_ioc)
3088                 ddlprintk((MYIOC_s_INFO_FMT "alt ioc FW Ptr %p\n",
3089                                 ioc->name, ioc->alt_ioc->cached_fw));
3090
3091         /* Get dma_addr and data transfer size.
3092          */
3093         if ((fw_sz = ioc->facts.FWImageSize) == 0)
3094                 return -1;
3095
3096         /* Get the DMA from ioc or ioc->alt_ioc */
3097         if (ioc->cached_fw != NULL)
3098                 pCached = (fw_image_t **)ioc->cached_fw;
3099         else if (ioc->alt_ioc && (ioc->alt_ioc->cached_fw != NULL))
3100                 pCached = (fw_image_t **)ioc->alt_ioc->cached_fw;
3101         else
3102                 return -2;
3103
3104         ddlprintk((MYIOC_s_INFO_FMT "DbGb2: FW Image @ %p\n",
3105                         ioc->name, pCached));
3106
3107         /* Write magic sequence to WriteSequence register
3108          * until enter diagnostic mode
3109          */
3110         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3111         while ((diag0val & MPI_DIAG_DRWE) == 0) {
3112                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3113                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3114                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3115                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3116                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3117                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3118
3119                 /* wait 100 msec */
3120                 if (sleepFlag == CAN_SLEEP) {
3121                         set_current_state(TASK_INTERRUPTIBLE);
3122                         schedule_timeout(100 * HZ / 1000);
3123                 } else {
3124                         mdelay (100);
3125                 }
3126
3127                 count++;
3128                 if (count > 20) {
3129                         printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3130                                         ioc->name, diag0val);
3131                         return -EFAULT;
3132
3133                 }
3134
3135                 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3136 #ifdef MPT_DEBUG
3137                 if (ioc->alt_ioc)
3138                         diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3139                 ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
3140                                 ioc->name, diag0val, diag1val));
3141 #endif
3142                 ddlprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3143                                 ioc->name, diag0val));
3144         }
3145
3146         /* Set the DiagRwEn and Disable ARM bits */
3147         diag0val |= (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM);
3148         CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3149
3150 #ifdef MPT_DEBUG
3151         if (ioc->alt_ioc)
3152                 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3153
3154         ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
3155                         ioc->name, diag0val, diag1val));
3156 #endif
3157
3158         /* max_idx = 1 + maximum valid buffer index
3159          */
3160         max_idx = 0;
3161         while (pCached[max_idx])
3162                 max_idx++;
3163
3164         fw_idx = 0;
3165         FwHdr = (MpiFwHeader_t *) pCached[fw_idx]->fw;
3166         ptru32 = (u32 *) FwHdr;
3167         count = (FwHdr->ImageSize + 3)/4;
3168         nextImage = FwHdr->NextImageHeaderOffset;
3169
3170         /* Write the LoadStartAddress to the DiagRw Address Register
3171          * using Programmed IO
3172          */
3173         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->LoadStartAddress);
3174         ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
3175                 ioc->name, FwHdr->LoadStartAddress));
3176
3177         ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x u32's @ %p\n",
3178                                 ioc->name, count, ptru32));
3179         left_u32s = pCached[fw_idx]->size/4;
3180         while (count--) {
3181                 if (left_u32s == 0) {
3182                         fw_idx++;
3183                         if (fw_idx >= max_idx) {
3184                                 /* FIXME
3185                                 ERROR CASE
3186                                 */
3187                                 ;
3188                         }
3189                         ptru32 = (u32 *) pCached[fw_idx]->fw;
3190                         left_u32s = pCached[fw_idx]->size / 4;
3191                 }
3192                 left_u32s--;
3193                 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
3194                 ptru32++;
3195         }
3196
3197         /* left_u32s, fw_idx and ptru32 are all valid
3198          */
3199         while (nextImage) {
3200                 ext_idx = 0;
3201                 ext_offset = nextImage;
3202                 while (ext_offset > pCached[ext_idx]->size) {
3203                         ext_idx++;
3204                         if (ext_idx >= max_idx) {
3205                                 /* FIXME
3206                                 ERROR CASE
3207                                 */
3208                                 ;
3209                         }
3210                         ext_offset -= pCached[ext_idx]->size;
3211                 }
3212                 ptru32 = (u32 *) ((char *)pCached[ext_idx]->fw + ext_offset);
3213                 left_u32s = pCached[ext_idx]->size - ext_offset;
3214
3215                 if ((left_u32s * 4) >= sizeof(MpiExtImageHeader_t)) {
3216                         ExtHdr = (MpiExtImageHeader_t *) ptru32;
3217                         count = (ExtHdr->ImageSize + 3 )/4;
3218                         nextImage = ExtHdr->NextImageHeaderOffset;
3219                         load_addr = ExtHdr->LoadStartAddress;
3220                 } else {
3221                         u32 * ptmp = (u32 *)pCached[ext_idx+1]->fw;
3222
3223                         switch (left_u32s) {
3224                         case 5:
3225                                 count = *(ptru32 + 2);
3226                                 nextImage = *(ptru32 + 3);
3227                                 load_addr = *(ptru32 + 4);
3228                                 break;
3229                         case 4:
3230                                 count = *(ptru32 + 2);
3231                                 nextImage = *(ptru32 + 3);
3232                                 load_addr = *ptmp;
3233                                 break;
3234                         case 3:
3235                                 count = *(ptru32 + 2);
3236                                 nextImage = *ptmp;
3237                                 load_addr = *(ptmp + 1);
3238                                 break;
3239                         case 2:
3240                                 count = *ptmp;
3241                                 nextImage = *(ptmp + 1);
3242                                 load_addr = *(ptmp + 2);
3243                                 break;
3244
3245                         case 1:
3246                                 count = *(ptmp + 1);
3247                                 nextImage = *(ptmp + 2);
3248                                 load_addr = *(ptmp + 3);
3249                                 break;
3250
3251                         default:
3252                                 count = 0;
3253                                 nextImage = 0;
3254                                 load_addr = 0;
3255                                 /* FIXME
3256                                 ERROR CASE
3257                                 */
3258                                 ;
3259
3260                         }
3261                         count = (count +3)/4;
3262                 }
3263
3264                 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x u32's @ %p\n",
3265                                                 ioc->name, count, ptru32));
3266                 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3267
3268                 while (count--) {
3269                         if (left_u32s == 0) {
3270                                 fw_idx++;
3271                                 if (fw_idx >= max_idx) {
3272                                         /* FIXME
3273                                         ERROR CASE
3274                                         */
3275                                         ;
3276                                 }
3277                                 ptru32 = (u32 *) pCached[fw_idx]->fw;
3278                                 left_u32s = pCached[fw_idx]->size / 4;
3279                         }
3280                         left_u32s--;
3281                         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
3282                         ptru32++;
3283                 }
3284         }
3285
3286         /* Write the IopResetVectorRegAddr */
3287         ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr! \n", ioc->name));
3288         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->IopResetRegAddr);
3289
3290         /* Write the IopResetVectorValue */
3291         ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value! \n", ioc->name));
3292         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, FwHdr->IopResetVectorValue);
3293
3294         /* Clear the internal flash bad bit - autoincrementing register,
3295          * so must do two writes.
3296          */
3297         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3298         diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3299         diagRwData |= 0x4000000;
3300         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3301         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3302
3303         /* clear the RW enable and DISARM bits */
3304         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3305         diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_FLASH_BAD_SIG);
3306         CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3307
3308         /* Write 0xFF to reset the sequencer */
3309         CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3310
3311         return 0;
3312 }
3313
3314 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3315 /*
3316  *      KickStart - Perform hard reset of MPT adapter.
3317  *      @ioc: Pointer to MPT_ADAPTER structure
3318  *      @force: Force hard reset
3319  *      @sleepFlag: Specifies whether the process can sleep
3320  *
3321  *      This routine places MPT adapter in diagnostic mode via the
3322  *      WriteSequence register, and then performs a hard reset of adapter
3323  *      via the Diagnostic register.
3324  *
3325  *      Inputs:   sleepflag - CAN_SLEEP (non-interrupt thread)
3326  *                      or NO_SLEEP (interrupt thread, use mdelay)
3327  *                force - 1 if doorbell active, board fault state
3328  *                              board operational, IOC_RECOVERY or
3329  *                              IOC_BRINGUP and there is an alt_ioc.
3330  *                        0 else
3331  *
3332  *      Returns:
3333  *               1 - hard reset, READY  
3334  *               0 - no reset due to History bit, READY 
3335  *              -1 - no reset due to History bit but not READY  
3336  *                   OR reset but failed to come READY
3337  *              -2 - no reset, could not enter DIAG mode
3338  *              -3 - reset but bad FW bit
3339  */
3340 static int
3341 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3342 {
3343         int hard_reset_done = 0;
3344         u32 ioc_state;
3345         int cntdn, cnt = 0;
3346
3347         dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3348         if ((int)ioc->chip_type > (int)FC929) {
3349                 /* Always issue a Msg Unit Reset first. This will clear some
3350                  * SCSI bus hang conditions.
3351                  */
3352                 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3353
3354                 if (sleepFlag == CAN_SLEEP) {
3355                         set_current_state(TASK_INTERRUPTIBLE);
3356                         schedule_timeout(HZ);
3357                 } else {
3358                         mdelay (1000);
3359                 }
3360         }
3361
3362         hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3363         if (hard_reset_done < 0)
3364                 return hard_reset_done;
3365
3366         dprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3367                         ioc->name));
3368
3369         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 20;    /* 20 seconds */
3370         for (cnt=0; cnt<cntdn; cnt++) {
3371                 if ((ioc_state = mpt_GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) {
3372                         dprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3373                                         ioc->name, cnt));
3374                         return hard_reset_done;
3375                 }
3376                 if (sleepFlag == CAN_SLEEP) {
3377                         set_current_state(TASK_INTERRUPTIBLE);
3378                         schedule_timeout(1);
3379                 } else {
3380                         mdelay (10);
3381                 }
3382         }
3383
3384         printk(MYIOC_s_ERR_FMT "Failed to come READY after reset!\n",
3385                         ioc->name);
3386         return -1;
3387 }
3388
3389 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3390 /*
3391  *      mpt_diag_reset - Perform hard reset of the adapter.
3392  *      @ioc: Pointer to MPT_ADAPTER structure
3393  *      @ignore: Set if to honor and clear to ignore
3394  *              the reset history bit
3395  *      @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3396  *              else set to NO_SLEEP (use mdelay instead)
3397  *
3398  *      This routine places the adapter in diagnostic mode via the
3399  *      WriteSequence register and then performs a hard reset of adapter
3400  *      via the Diagnostic register. Adapter should be in ready state
3401  *      upon successful completion.
3402  *
3403  *      Returns:  1  hard reset successful
3404  *                0  no reset performed because reset history bit set
3405  *               -2  enabling diagnostic mode failed
3406  *               -3  diagnostic reset failed
3407  */
3408 static int
3409 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3410 {
3411         u32 diag0val;
3412         u32 doorbell;
3413         int hard_reset_done = 0;
3414         int count = 0;
3415 #ifdef MPT_DEBUG
3416         u32 diag1val = 0;
3417 #endif
3418
3419         /* Clear any existing interrupts */
3420         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3421
3422         /* Use "Diagnostic reset" method! (only thing available!) */
3423         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3424
3425 #ifdef MPT_DEBUG
3426         if (ioc->alt_ioc)
3427                 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3428         dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3429                         ioc->name, diag0val, diag1val));
3430 #endif
3431
3432         /* Do the reset if we are told to ignore the reset history
3433          * or if the reset history is 0
3434          */
3435         if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3436                 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3437                         /* Write magic sequence to WriteSequence register
3438                          * Loop until in diagnostic mode
3439                          */
3440                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3441                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3442                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3443                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3444                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3445                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3446
3447                         /* wait 100 msec */
3448                         if (sleepFlag == CAN_SLEEP) {
3449                                 set_current_state(TASK_INTERRUPTIBLE);
3450                                 schedule_timeout(100 * HZ / 1000);
3451                         } else {
3452                                 mdelay (100);
3453                         }
3454
3455                         count++;
3456                         if (count > 20) {
3457                                 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3458                                                 ioc->name, diag0val);
3459                                 return -2;
3460
3461                         }
3462
3463                         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3464
3465                         dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3466                                         ioc->name, diag0val));
3467                 }
3468
3469 #ifdef MPT_DEBUG
3470                 if (ioc->alt_ioc)
3471                         diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3472                 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3473                                 ioc->name, diag0val, diag1val));
3474 #endif
3475                 /* Write the PreventIocBoot bit */
3476                 if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
3477                         diag0val |= MPI_DIAG_PREVENT_IOC_BOOT;
3478                         CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3479                 }
3480
3481                 /*
3482                  * Disable the ARM (Bug fix)
3483                  *
3484                  */
3485                 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3486                 mdelay (1);
3487
3488                 /*
3489                  * Now hit the reset bit in the Diagnostic register
3490                  * (THE BIG HAMMER!) (Clears DRWE bit).
3491                  */
3492                 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3493                 hard_reset_done = 1;
3494                 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3495                                 ioc->name));
3496
3497                 /*
3498                  * Call each currently registered protocol IOC reset handler
3499                  * with pre-reset indication.
3500                  * NOTE: If we're doing _IOC_BRINGUP, there can be no
3501                  * MptResetHandlers[] registered yet.
3502                  */
3503                 {
3504                         int      ii;
3505                         int      r = 0;
3506
3507                         for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3508                                 if (MptResetHandlers[ii]) {
3509                                         dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3510                                                         ioc->name, ii));
3511                                         r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
3512                                         if (ioc->alt_ioc) {
3513                                                 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3514                                                                 ioc->name, ioc->alt_ioc->name, ii));
3515                                                 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
3516                                         }
3517                                 }
3518                         }
3519                         /* FIXME?  Examine results here? */
3520                 }
3521
3522                 if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
3523                         /* If the DownloadBoot operation fails, the
3524                          * IOC will be left unusable. This is a fatal error
3525                          * case.  _diag_reset will return < 0
3526                          */
3527                         for (count = 0; count < 30; count ++) {
3528                                 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3529 #ifdef MPT_DEBUG
3530                                 if (ioc->alt_ioc)
3531                                         diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3532                                 dprintk((MYIOC_s_INFO_FMT
3533                                         "DbG2b: diag0=%08x, diag1=%08x\n",
3534                                         ioc->name, diag0val, diag1val));
3535 #endif
3536                                 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3537                                         break;
3538                                 }
3539
3540                                 /* wait 1 sec */
3541                                 if (sleepFlag == CAN_SLEEP) {
3542                                         set_current_state(TASK_INTERRUPTIBLE);
3543                                         schedule_timeout(HZ);
3544                                 } else {
3545                                         mdelay (1000);
3546                                 }
3547                         }
3548                         if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) {
3549                                 printk(KERN_WARNING MYNAM
3550                                         ": firmware downloadboot failure (%d)!\n", count);
3551                         }
3552
3553                 } else {
3554                         /* Wait for FW to reload and for board
3555                          * to go to the READY state.
3556                          * Maximum wait is 60 seconds.
3557                          * If fail, no error will check again
3558                          * with calling program.
3559                          */
3560                         for (count = 0; count < 60; count ++) {
3561                                 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3562                                 doorbell &= MPI_IOC_STATE_MASK;
3563
3564                                 if (doorbell == MPI_IOC_STATE_READY) {
3565                                         break;
3566                                 }
3567
3568                                 /* wait 1 sec */
3569                                 if (sleepFlag == CAN_SLEEP) {
3570                                         set_current_state(TASK_INTERRUPTIBLE);
3571                                         schedule_timeout(HZ);
3572                                 } else {
3573                                         mdelay (1000);
3574                                 }
3575                         }
3576                 }
3577         }
3578
3579         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3580 #ifdef MPT_DEBUG
3581         if (ioc->alt_ioc)
3582                 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3583         dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3584                 ioc->name, diag0val, diag1val));
3585 #endif
3586
3587         /* Clear RESET_HISTORY bit!  Place board in the
3588          * diagnostic mode to update the diag register.
3589          */
3590         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3591         count = 0;
3592         while ((diag0val & MPI_DIAG_DRWE) == 0) {
3593                 /* Write magic sequence to WriteSequence register
3594                  * Loop until in diagnostic mode
3595                  */
3596                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3597                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3598                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3599                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3600                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3601
3602                 /* wait 100 msec */
3603                 if (sleepFlag == CAN_SLEEP) {
3604                         set_current_state(TASK_INTERRUPTIBLE);
3605                         schedule_timeout(100 * HZ / 1000);
3606                 } else {
3607                         mdelay (100);
3608                 }
3609
3610                 count++;
3611                 if (count > 20) {
3612                         printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3613                                         ioc->name, diag0val);
3614                         break;
3615                 }
3616                 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3617         }
3618         diag0val &= ~MPI_DIAG_RESET_HISTORY;
3619         CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3620         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3621         if (diag0val & MPI_DIAG_RESET_HISTORY) {
3622                 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3623                                 ioc->name);
3624         }
3625
3626         /* Disable Diagnostic Mode
3627          */
3628         CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3629
3630         /* Check FW reload status flags.
3631          */
3632         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3633         if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3634                 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3635                                 ioc->name, diag0val);
3636                 return -3;
3637         }
3638
3639 #ifdef MPT_DEBUG
3640         if (ioc->alt_ioc)
3641                 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3642         dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3643                         ioc->name, diag0val, diag1val));
3644 #endif
3645
3646         /*
3647          * Reset flag that says we've enabled event notification
3648          */
3649         ioc->facts.EventState = 0;
3650
3651         if (ioc->alt_ioc)
3652                 ioc->alt_ioc->facts.EventState = 0;
3653
3654         return hard_reset_done;
3655 }
3656
3657 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3658 /*
3659  *      SendIocReset - Send IOCReset request to MPT adapter.
3660  *      @ioc: Pointer to MPT_ADAPTER structure
3661  *      @reset_type: reset type, expected values are
3662  *      %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3663  *
3664  *      Send IOCReset request to the MPT adapter.
3665  *
3666  *      Returns 0 for success, non-zero for failure.
3667  */
3668 static int
3669 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3670 {
3671         int r;
3672         u32 state;
3673         int cntdn, count;
3674
3675         dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3676                         ioc->name, reset_type));
3677         CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3678         if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3679                 return r;
3680
3681         /* FW ACK'd request, wait for READY state
3682          */
3683         count = 0;
3684         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15;    /* 15 seconds */
3685
3686         while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3687                 cntdn--;
3688                 count++;
3689                 if (!cntdn) {
3690                         if (sleepFlag != CAN_SLEEP)
3691                                 count *= 10;
3692
3693                         printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3694                                         ioc->name, (count+5)/HZ);
3695                         return -ETIME;
3696                 }
3697
3698                 if (sleepFlag == CAN_SLEEP) {
3699                         set_current_state(TASK_INTERRUPTIBLE);
3700                         schedule_timeout(1);
3701                 } else {
3702                         mdelay (1);     /* 1 msec delay */
3703                 }
3704         }
3705
3706         /* TODO!
3707          *  Cleanup all event stuff for this IOC; re-issue EventNotification
3708          *  request if needed.
3709          */
3710         if (ioc->facts.Function)
3711                 ioc->facts.EventState = 0;
3712
3713         return 0;
3714 }
3715
3716 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3717 /*
3718  *      PrimeIocFifos - Initialize IOC request and reply FIFOs.
3719  *      @ioc: Pointer to MPT_ADAPTER structure
3720  *
3721  *      This routine allocates memory for the MPT reply and request frame
3722  *      pools (if necessary), and primes the IOC reply FIFO with
3723  *      reply frames.
3724  *
3725  *      Returns 0 for success, non-zero for failure.
3726  */
3727 static int
3728 PrimeIocFifos(MPT_ADAPTER *ioc)
3729 {
3730         MPT_FRAME_HDR *mf;
3731         unsigned long b;
3732         unsigned long flags;
3733         dma_addr_t aligned_mem_dma;
3734         u8 *aligned_mem;
3735         int i, sz;
3736         int chain_buffer_sz, reply_buffer_sz, request_buffer_sz;
3737         int scale, num_sge, num_chain;
3738
3739         /* request buffer size,  rounding UP to nearest 4-kB boundary */
3740         request_buffer_sz = (ioc->req_sz * ioc->req_depth) + 128;
3741         request_buffer_sz = ((request_buffer_sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
3742
3743         /* reply buffer size */
3744         reply_buffer_sz = (ioc->reply_sz * ioc->reply_depth) + 128;
3745
3746         /* chain buffer size, copied from from mptscsih_initChainBuffers()
3747          *
3748          * Calculate the number of chain buffers needed(plus 1) per I/O
3749          * then multiply the the maximum number of simultaneous cmds
3750          *
3751          * num_sge = num sge in request frame + last chain buffer
3752          * scale = num sge per chain buffer if no chain element
3753          */
3754
3755         scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3756         if (sizeof(dma_addr_t) == sizeof(u64))
3757                 num_sge =  scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3758         else
3759                 num_sge =  1 + scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3760
3761         num_chain = 1;
3762         while (MPT_SCSI_SG_DEPTH - num_sge > 0) {
3763                 num_chain++;
3764                 num_sge += (scale - 1);
3765         }
3766         num_chain++;
3767
3768         if ((int)ioc->chip_type > (int) FC929)
3769                 num_chain *= MPT_SCSI_CAN_QUEUE;
3770         else
3771                 num_chain *= MPT_FC_CAN_QUEUE;
3772
3773         chain_buffer_sz = num_chain * ioc->req_sz;
3774
3775         if(ioc->fifo_pool == NULL) {
3776
3777                 ioc->fifo_pool_sz = request_buffer_sz +
3778                         reply_buffer_sz + chain_buffer_sz;
3779
3780                 ioc->fifo_pool = pci_alloc_consistent(ioc->pcidev,
3781                 ioc->fifo_pool_sz, &ioc->fifo_pool_dma);
3782
3783                 if( ioc->fifo_pool == NULL)
3784                         goto out_fail;
3785
3786                 ioc->alloc_total += ioc->fifo_pool_sz;
3787                 memset(ioc->fifo_pool, 0, ioc->fifo_pool_sz);
3788
3789                 /* reply fifo pointers */
3790                 ioc->reply_alloc = ioc->fifo_pool;
3791                 ioc->reply_alloc_dma = ioc->fifo_pool_dma;
3792                 /* request fifo pointers */
3793                 ioc->req_alloc = ioc->reply_alloc+reply_buffer_sz;
3794                 ioc->req_alloc_dma = ioc->reply_alloc_dma+reply_buffer_sz;
3795                 /* chain buffer pointers */
3796                 ioc->chain_alloc = ioc->req_alloc+request_buffer_sz;
3797                 ioc->chain_alloc_dma = ioc->req_alloc_dma+request_buffer_sz;
3798                 ioc->chain_alloc_sz = chain_buffer_sz;
3799
3800                 /*  Prime reply FIFO...  */
3801                 dprintk((KERN_INFO MYNAM ": %s.reply_alloc  @ %p[%p], sz=%d bytes\n",
3802                         ioc->name, ioc->reply_alloc, 
3803                         (void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz));
3804
3805                 b = (unsigned long) ioc->reply_alloc;
3806                 b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
3807                 aligned_mem = (u8 *) b;
3808                 ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem;
3809                 ioc->reply_frames_dma =
3810                         (ioc->reply_alloc_dma + (aligned_mem - ioc->reply_alloc));
3811
3812                 ioc->reply_frames_low_dma = (u32) (ioc->reply_frames_dma & 0xFFFFFFFF);
3813         
3814                 /*  Request FIFO - WE manage this!  */
3815                 dprintk((KERN_INFO MYNAM ": %s.req_alloc    @ %p[%p], sz=%d bytes\n",
3816                         ioc->name, ioc->req_alloc,
3817                         (void *)(ulong)ioc->req_alloc_dma, request_buffer_sz));
3818
3819                 b = (unsigned long) ioc->req_alloc;
3820                 b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
3821                 aligned_mem = (u8 *) b;
3822                 ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem;
3823                 ioc->req_frames_dma =
3824                         (ioc->req_alloc_dma + (aligned_mem - ioc->req_alloc));
3825
3826                 ioc->req_frames_low_dma = (u32) (ioc->req_frames_dma & 0xFFFFFFFF);
3827
3828 #if defined(CONFIG_MTRR) && 0
3829                 /*
3830                  *  Enable Write Combining MTRR for IOC's memory region.
3831                  *  (at least as much as we can; "size and base must be
3832                  *  multiples of 4 kiB"
3833                  */
3834                 ioc->mtrr_reg = mtrr_add(ioc->fifo_pool,
3835                                          ioc->fifo_pool_sz,
3836                                          MTRR_TYPE_WRCOMB, 1);
3837                 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3838                                 ioc->name, ioc->fifo_pool, ioc->fifo_pool_sz));
3839 #endif
3840
3841         } /* ioc->fifo_pool == NULL */
3842         
3843         /* Post Reply frames to FIFO
3844          */
3845         aligned_mem_dma = ioc->reply_frames_dma;
3846         dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%p]\n",
3847                         ioc->name, ioc->reply_frames, (void *)(ulong)aligned_mem_dma));
3848
3849         for (i = 0; i < ioc->reply_depth; i++) {
3850                 /*  Write each address to the IOC!  */
3851                 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma);
3852                 aligned_mem_dma += ioc->reply_sz;
3853         }
3854
3855
3856         /* Initialize Request frames linked list
3857          */
3858         aligned_mem_dma = ioc->req_frames_dma;
3859         aligned_mem = (u8 *) ioc->req_frames;
3860         dprintk((KERN_INFO MYNAM ": %s.req_frames   @ %p[%p]\n",
3861                         ioc->name, aligned_mem, (void *)(ulong)aligned_mem_dma));
3862
3863         spin_lock_irqsave(&ioc->FreeQlock, flags);
3864         Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
3865         for (i = 0; i < ioc->req_depth; i++) {
3866                 mf = (MPT_FRAME_HDR *) aligned_mem;
3867
3868                 /*  Queue REQUESTs *internally*!  */
3869                 Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
3870                 aligned_mem += ioc->req_sz;
3871         }
3872         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3873
3874
3875         if (ioc->sense_buf_pool == NULL) {
3876                 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3877                 ioc->sense_buf_pool =
3878                                 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3879                 if (ioc->sense_buf_pool == NULL)
3880                         goto out_fail;
3881
3882                 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3883                 ioc->alloc_total += sz;
3884         }
3885
3886         return 0;
3887
3888 out_fail:
3889         if (ioc->fifo_pool != NULL) {
3890                 pci_free_consistent(ioc->pcidev,
3891                                 ioc->fifo_pool_sz,
3892                                 ioc->fifo_pool, ioc->fifo_pool_dma);
3893                 ioc->reply_frames = NULL;
3894                 ioc->reply_alloc = NULL;
3895                 ioc->req_frames = NULL;
3896                 ioc->req_alloc = NULL;
3897                 ioc->chain_alloc = NULL;
3898                 ioc->fifo_pool = NULL;
3899                 ioc->alloc_total -= ioc->fifo_pool_sz;
3900 #if defined(CONFIG_MTRR) && 0
3901                 if (ioc->mtrr_reg > 0) {
3902                         mtrr_del(ioc->mtrr_reg, 0, 0);
3903                         dprintk((MYIOC_s_INFO_FMT "MTRR region de-registered\n",
3904                                         ioc->name));
3905                 }
3906 #endif
3907         }
3908         if (ioc->sense_buf_pool != NULL) {
3909                 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3910                 pci_free_consistent(ioc->pcidev,
3911                                 sz,
3912                                 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3913                 ioc->sense_buf_pool = NULL;
3914         }
3915         return -1;
3916 }
3917
3918 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3919 /**
3920  *      mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3921  *      from IOC via doorbell handshake method.
3922  *      @ioc: Pointer to MPT_ADAPTER structure
3923  *      @reqBytes: Size of the request in bytes
3924  *      @req: Pointer to MPT request frame
3925  *      @replyBytes: Expected size of the reply in bytes
3926  *      @u16reply: Pointer to area where reply should be written
3927  *      @maxwait: Max wait time for a reply (in seconds)
3928  *      @sleepFlag: Specifies whether the process can sleep
3929  *
3930  *      NOTES: It is the callers responsibility to byte-swap fields in the
3931  *      request which are greater than 1 byte in size.  It is also the
3932  *      callers responsibility to byte-swap response fields which are
3933  *      greater than 1 byte in size.
3934  *
3935  *      Returns 0 for success, non-zero for failure.
3936  */
3937 int
3938 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3939                                 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3940 {
3941         MPIDefaultReply_t *mptReply;
3942         int failcnt = 0;
3943         int t;
3944
3945         /*
3946          * Get ready to cache a handshake reply
3947          */
3948         ioc->hs_reply_idx = 0;
3949         mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3950         mptReply->MsgLength = 0;
3951
3952         /*
3953          * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3954          * then tell IOC that we want to handshake a request of N words.
3955          * (WRITE u32val to Doorbell reg).
3956          */
3957         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3958         CHIPREG_WRITE32(&ioc->chip->Doorbell,
3959                         ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3960                          ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3961
3962         /*
3963          * Wait for IOC's doorbell handshake int
3964          */
3965         if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3966                 failcnt++;
3967
3968         dhsprintk((MYIOC_s_INFO_FMT "HandShake request start, WaitCnt=%d%s\n",
3969                         ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3970
3971         /* Read doorbell and check for active bit */
3972         if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3973                         return -1;
3974
3975         /*
3976          * Clear doorbell int (WRITE 0 to IntStatus reg),
3977          * then wait for IOC to ACKnowledge that it's ready for
3978          * our handshake request.
3979          */
3980         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3981         if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3982                 failcnt++;
3983
3984         if (!failcnt) {
3985                 int      ii;
3986                 u8      *req_as_bytes = (u8 *) req;
3987
3988                 /*
3989                  * Stuff request words via doorbell handshake,
3990                  * with ACK from IOC for each.
3991                  */
3992                 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3993                         u32 word = ((req_as_bytes[(ii*4) + 0] <<  0) |
3994                                     (req_as_bytes[(ii*4) + 1] <<  8) |
3995                                     (req_as_bytes[(ii*4) + 2] << 16) |
3996                                     (req_as_bytes[(ii*4) + 3] << 24));
3997
3998                         CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3999                         if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4000                                 failcnt++;
4001                 }
4002
4003                 dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
4004                 DBG_DUMP_REQUEST_FRAME_HDR(req)
4005
4006                 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
4007                                 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
4008
4009                 /*
4010                  * Wait for completion of doorbell handshake reply from the IOC
4011                  */
4012                 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
4013                         failcnt++;
4014
4015                 /*
4016                  * Copy out the cached reply...
4017                  */
4018                 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
4019                         u16reply[ii] = ioc->hs_reply[ii];
4020         } else {
4021                 return -99;
4022         }
4023
4024         return -failcnt;
4025 }
4026
4027 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4028 /*
4029  *      WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
4030  *      in it's IntStatus register.
4031  *      @ioc: Pointer to MPT_ADAPTER structure
4032  *      @howlong: How long to wait (in seconds)
4033  *      @sleepFlag: Specifies whether the process can sleep
4034  *
4035  *      This routine waits (up to ~2 seconds max) for IOC doorbell
4036  *      handshake ACKnowledge.
4037  *
4038  *      Returns a negative value on failure, else wait loop count.
4039  */
4040 static int
4041 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4042 {
4043         int cntdn;
4044         int count = 0;
4045         u32 intstat;
4046
4047         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
4048
4049         if (sleepFlag == CAN_SLEEP) {
4050                 while (--cntdn) {
4051                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4052                         if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4053                                 break;
4054                         set_current_state(TASK_INTERRUPTIBLE);
4055                         schedule_timeout(1);
4056                         count++;
4057                 }
4058         } else {
4059                 while (--cntdn) {
4060                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4061                         if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4062                                 break;
4063                         mdelay (1);
4064                         count++;
4065                 }
4066         }
4067
4068         if (cntdn) {
4069                 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (cnt=%d)\n",
4070                                 ioc->name, count));
4071                 return count;
4072         }
4073
4074         printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout(%d)!\n",
4075                         ioc->name, (count+5)/HZ);
4076         return -1;
4077 }
4078
4079 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4080 /*
4081  *      WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
4082  *      in it's IntStatus register.
4083  *      @ioc: Pointer to MPT_ADAPTER structure
4084  *      @howlong: How long to wait (in seconds)
4085  *      @sleepFlag: Specifies whether the process can sleep
4086  *
4087  *      This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
4088  *
4089  *      Returns a negative value on failure, else wait loop count.
4090  */
4091 static int
4092 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4093 {
4094         int cntdn;
4095         int count = 0;
4096         u32 intstat;
4097
4098         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
4099         if (sleepFlag == CAN_SLEEP) {
4100                 while (--cntdn) {
4101                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4102                         if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4103                                 break;
4104                         set_current_state(TASK_INTERRUPTIBLE);
4105                         schedule_timeout(1);
4106                         count++;
4107                 }
4108         } else {
4109                 while (--cntdn) {
4110                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4111                         if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4112                                 break;
4113                         mdelay(1);
4114                         count++;
4115                 }
4116         }
4117
4118         if (cntdn) {
4119                 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d)\n",
4120                                 ioc->name, count));
4121                 return count;
4122         }
4123
4124         printk(MYIOC_s_ERR_FMT "Doorbell INT timeout(%d)!\n",
4125                         ioc->name, (count+5)/HZ);
4126         return -1;
4127 }
4128
4129 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4130 /*
4131  *      WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
4132  *      @ioc: Pointer to MPT_ADAPTER structure
4133  *      @howlong: How long to wait (in seconds)
4134  *      @sleepFlag: Specifies whether the process can sleep
4135  *
4136  *      This routine polls the IOC for a handshake reply, 16 bits at a time.
4137  *      Reply is cached to IOC private area large enough to hold a maximum
4138  *      of 128 bytes of reply data.
4139  *
4140  *      Returns a negative value on failure, else size of reply in WORDS.
4141  */
4142 static int
4143 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4144 {
4145         int u16cnt = 0;
4146         int failcnt = 0;
4147         int t;
4148         u16 *hs_reply = ioc->hs_reply;
4149         volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4150         u16 hword;
4151
4152         hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4153
4154         /*
4155          * Get first two u16's so we can look at IOC's intended reply MsgLength
4156          */
4157         u16cnt=0;
4158         if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4159                 failcnt++;
4160         } else {
4161                 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4162                 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4163                 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4164                         failcnt++;
4165                 else {
4166                         hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4167                         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4168                 }
4169         }
4170
4171         dhsprintk((MYIOC_s_INFO_FMT "First handshake reply word=%08x%s\n",
4172                         ioc->name, le32_to_cpu(*(u32 *)hs_reply),
4173                         failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4174
4175         /*
4176          * If no error (and IOC said MsgLength is > 0), piece together
4177          * reply 16 bits at a time.
4178          */
4179         for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4180                 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4181                         failcnt++;
4182                 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4183                 /* don't overflow our IOC hs_reply[] buffer! */
4184                 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4185                         hs_reply[u16cnt] = hword;
4186                 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4187         }
4188
4189         if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4190                 failcnt++;
4191         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4192
4193         if (failcnt) {
4194                 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4195                                 ioc->name);
4196                 return -failcnt;
4197         }
4198 #if 0
4199         else if (u16cnt != (2 * mptReply->MsgLength)) {
4200                 return -101;
4201         }
4202         else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4203                 return -102;
4204         }
4205 #endif
4206
4207         dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4208         DBG_DUMP_REPLY_FRAME(mptReply)
4209
4210         dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY (sz=%d)\n",
4211                         ioc->name, u16cnt/2));
4212         return u16cnt/2;
4213 }
4214
4215 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4216 /*
4217  *      GetLanConfigPages - Fetch LANConfig pages.
4218  *      @ioc: Pointer to MPT_ADAPTER structure
4219  *
4220  *      Return: 0 for success
4221  *      -ENOMEM if no memory available
4222  *              -EPERM if not allowed due to ISR context
4223  *              -EAGAIN if no msg frames currently available
4224  *              -EFAULT for non-successful reply or no reply (timeout)
4225  */
4226 static int
4227 GetLanConfigPages(MPT_ADAPTER *ioc)
4228 {
4229         ConfigPageHeader_t       hdr;
4230         CONFIGPARMS              cfg;
4231         LANPage0_t              *ppage0_alloc;
4232         dma_addr_t               page0_dma;
4233         LANPage1_t              *ppage1_alloc;
4234         dma_addr_t               page1_dma;
4235         int                      rc = 0;
4236         int                      data_sz;
4237         int                      copy_sz;
4238
4239         /* Get LAN Page 0 header */
4240         hdr.PageVersion = 0;
4241         hdr.PageLength = 0;
4242         hdr.PageNumber = 0;
4243         hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4244         cfg.hdr = &hdr;
4245         cfg.physAddr = -1;
4246         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4247         cfg.dir = 0;
4248         cfg.pageAddr = 0;
4249         cfg.timeout = 0;
4250
4251         if ((rc = mpt_config(ioc, &cfg)) != 0)
4252                 return rc;
4253
4254         if (hdr.PageLength > 0) {
4255                 data_sz = hdr.PageLength * 4;
4256                 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4257                 rc = -ENOMEM;
4258                 if (ppage0_alloc) {
4259                         memset((u8 *)ppage0_alloc, 0, data_sz);
4260                         cfg.physAddr = page0_dma;
4261                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4262
4263                         if ((rc = mpt_config(ioc, &cfg)) == 0) {
4264                                 /* save the data */
4265                                 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4266                                 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4267
4268                         }
4269
4270                         pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4271
4272                         /* FIXME!
4273                          *      Normalize endianness of structure data,
4274                          *      by byte-swapping all > 1 byte fields!
4275                          */
4276
4277                 }
4278
4279                 if (rc)
4280                         return rc;
4281         }
4282
4283         /* Get LAN Page 1 header */
4284         hdr.PageVersion = 0;
4285         hdr.PageLength = 0;
4286         hdr.PageNumber = 1;
4287         hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4288         cfg.hdr = &hdr;
4289         cfg.physAddr = -1;
4290         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4291         cfg.dir = 0;
4292         cfg.pageAddr = 0;
4293
4294         if ((rc = mpt_config(ioc, &cfg)) != 0)
4295                 return rc;
4296
4297         if (hdr.PageLength == 0)
4298                 return 0;
4299
4300         data_sz = hdr.PageLength * 4;
4301         rc = -ENOMEM;
4302         ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4303         if (ppage1_alloc) {
4304                 memset((u8 *)ppage1_alloc, 0, data_sz);
4305                 cfg.physAddr = page1_dma;
4306                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4307
4308                 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4309                         /* save the data */
4310                         copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4311                         memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4312                 }
4313
4314                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4315
4316                 /* FIXME!
4317                  *      Normalize endianness of structure data,
4318                  *      by byte-swapping all > 1 byte fields!
4319                  */
4320
4321         }
4322
4323         return rc;
4324 }
4325
4326 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4327 /*
4328  *      GetFcPortPage0 - Fetch FCPort config Page0.
4329  *      @ioc: Pointer to MPT_ADAPTER structure
4330  *      @portnum: IOC Port number
4331  *
4332  *      Return: 0 for success
4333  *      -ENOMEM if no memory available
4334  *              -EPERM if not allowed due to ISR context
4335  *              -EAGAIN if no msg frames currently available
4336  *              -EFAULT for non-successful reply or no reply (timeout)
4337  */
4338 static int
4339 GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4340 {
4341         ConfigPageHeader_t       hdr;
4342         CONFIGPARMS              cfg;
4343         FCPortPage0_t           *ppage0_alloc;
4344         FCPortPage0_t           *pp0dest;
4345         dma_addr_t               page0_dma;
4346         int                      data_sz;
4347         int                      copy_sz;
4348         int                      rc;
4349
4350         /* Get FCPort Page 0 header */
4351         hdr.PageVersion = 0;
4352         hdr.PageLength = 0;
4353         hdr.PageNumber = 0;
4354         hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
4355         cfg.hdr = &hdr;
4356         cfg.physAddr = -1;
4357         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4358         cfg.dir = 0;
4359         cfg.pageAddr = portnum;
4360         cfg.timeout = 0;
4361
4362         if ((rc = mpt_config(ioc, &cfg)) != 0)
4363                 return rc;
4364
4365         if (hdr.PageLength == 0)
4366                 return 0;
4367
4368         data_sz = hdr.PageLength * 4;
4369         rc = -ENOMEM;
4370         ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4371         if (ppage0_alloc) {
4372                 memset((u8 *)ppage0_alloc, 0, data_sz);
4373                 cfg.physAddr = page0_dma;
4374                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4375
4376                 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4377                         /* save the data */
4378                         pp0dest = &ioc->fc_port_page0[portnum];
4379                         copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
4380                         memcpy(pp0dest, ppage0_alloc, copy_sz);
4381
4382                         /*
4383                          *      Normalize endianness of structure data,
4384                          *      by byte-swapping all > 1 byte fields!
4385                          */
4386                         pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
4387                         pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
4388                         pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
4389                         pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
4390                         pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
4391                         pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
4392                         pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
4393                         pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
4394                         pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
4395                         pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
4396                         pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
4397                         pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
4398                         pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
4399                         pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
4400                         pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
4401                         pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
4402
4403                 }
4404
4405                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4406         }
4407
4408         return rc;
4409 }
4410
4411 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4412 /*
4413  *      GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4414  *      @ioc: Pointer to MPT_ADAPTER structure
4415  *
4416  *      Returns: 0 for success
4417  *      -ENOMEM if no memory available
4418  *              -EPERM if not allowed due to ISR context
4419  *              -EAGAIN if no msg frames currently available
4420  *              -EFAULT for non-successful reply or no reply (timeout)
4421  */
4422 static int
4423 GetIoUnitPage2(MPT_ADAPTER *ioc)
4424 {
4425         ConfigPageHeader_t       hdr;
4426         CONFIGPARMS              cfg;
4427         IOUnitPage2_t           *ppage_alloc;
4428         dma_addr_t               page_dma;
4429         int                      data_sz;
4430         int                      rc;
4431
4432         /* Get the page header */
4433         hdr.PageVersion = 0;
4434         hdr.PageLength = 0;
4435         hdr.PageNumber = 2;
4436         hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4437         cfg.hdr = &hdr;
4438         cfg.physAddr = -1;
4439         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4440         cfg.dir = 0;
4441         cfg.pageAddr = 0;
4442         cfg.timeout = 0;
4443
4444         if ((rc = mpt_config(ioc, &cfg)) != 0)
4445                 return rc;
4446
4447         if (hdr.PageLength == 0)
4448                 return 0;
4449
4450         /* Read the config page */
4451         data_sz = hdr.PageLength * 4;
4452         rc = -ENOMEM;
4453         ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4454         if (ppage_alloc) {
4455                 memset((u8 *)ppage_alloc, 0, data_sz);
4456                 cfg.physAddr = page_dma;
4457                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4458
4459                 /* If Good, save data */
4460                 if ((rc = mpt_config(ioc, &cfg)) == 0)
4461                         ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4462
4463                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4464         }
4465
4466         return rc;
4467 }
4468
4469 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4470 /*      mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4471  *      @ioc: Pointer to a Adapter Strucutre
4472  *      @portnum: IOC port number
4473  *
4474  *      Return: -EFAULT if read of config page header fails
4475  *                      or if no nvram
4476  *      If read of SCSI Port Page 0 fails,
4477  *              NVRAM = MPT_HOST_NVRAM_INVALID  (0xFFFFFFFF)
4478  *              Adapter settings: async, narrow
4479  *              Return 1
4480  *      If read of SCSI Port Page 2 fails,
4481  *              Adapter settings valid
4482  *              NVRAM = MPT_HOST_NVRAM_INVALID  (0xFFFFFFFF)
4483  *              Return 1
4484  *      Else
4485  *              Both valid
4486  *              Return 0
4487  *      CHECK - what type of locking mechanisms should be used????
4488  */
4489 static int
4490 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4491 {
4492         u8                      *pbuf;
4493         dma_addr_t               buf_dma;
4494         CONFIGPARMS              cfg;
4495         ConfigPageHeader_t       header;
4496         int                      ii;
4497         int                      data, rc = 0;
4498
4499         /* Allocate memory
4500          */
4501         if (!ioc->spi_data.nvram) {
4502                 int      sz;
4503                 u8      *mem;
4504                 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4505                 mem = kmalloc(sz, GFP_ATOMIC);
4506                 if (mem == NULL)
4507                         return -EFAULT;
4508
4509                 ioc->spi_data.nvram = (int *) mem;
4510
4511                 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4512                         ioc->name, ioc->spi_data.nvram, sz));
4513         }
4514
4515         /* Invalidate NVRAM information
4516          */
4517         for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4518                 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4519         }
4520
4521         /* Read SPP0 header, allocate memory, then read page.
4522          */
4523         header.PageVersion = 0;
4524         header.PageLength = 0;
4525         header.PageNumber = 0;
4526         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4527         cfg.hdr = &header;
4528         cfg.physAddr = -1;
4529         cfg.pageAddr = portnum;
4530         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4531         cfg.dir = 0;
4532         cfg.timeout = 0;        /* use default */
4533         if (mpt_config(ioc, &cfg) != 0)
4534                  return -EFAULT;
4535
4536         if (header.PageLength > 0) {
4537                 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4538                 if (pbuf) {
4539                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4540                         cfg.physAddr = buf_dma;
4541                         if (mpt_config(ioc, &cfg) != 0) {
4542                                 ioc->spi_data.maxBusWidth = MPT_NARROW;
4543                                 ioc->spi_data.maxSyncOffset = 0;
4544                                 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4545                                 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4546                                 rc = 1;
4547                         } else {
4548                                 /* Save the Port Page 0 data
4549                                  */
4550                                 SCSIPortPage0_t  *pPP0 = (SCSIPortPage0_t  *) pbuf;
4551                                 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4552                                 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4553
4554                                 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 )
4555                                         ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4556
4557                                 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4558                                 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4559                                 if (data) {
4560                                         ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4561                                         data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4562                                         ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4563                                 } else {
4564                                         ioc->spi_data.maxSyncOffset = 0;
4565                                         ioc->spi_data.minSyncFactor = MPT_ASYNC;
4566                                 }
4567
4568                                 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4569
4570                                 /* Update the minSyncFactor based on bus type.
4571                                  */
4572                                 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4573                                         (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE))  {
4574
4575                                         if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
4576                                                 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4577                                 }
4578                         }
4579                         if (pbuf) {
4580                                 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4581                         }
4582                 }
4583         }
4584
4585         /* SCSI Port Page 2 - Read the header then the page.
4586          */
4587         header.PageVersion = 0;
4588         header.PageLength = 0;
4589         header.PageNumber = 2;
4590         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4591         cfg.hdr = &header;
4592         cfg.physAddr = -1;
4593         cfg.pageAddr = portnum;
4594         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4595         cfg.dir = 0;
4596         if (mpt_config(ioc, &cfg) != 0)
4597                 return -EFAULT;
4598
4599         if (header.PageLength > 0) {
4600                 /* Allocate memory and read SCSI Port Page 2
4601                  */
4602                 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4603                 if (pbuf) {
4604                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4605                         cfg.physAddr = buf_dma;
4606                         if (mpt_config(ioc, &cfg) != 0) {
4607                                 /* Nvram data is left with INVALID mark
4608                                  */
4609                                 rc = 1;
4610                         } else {
4611                                 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t  *) pbuf;
4612                                 MpiDeviceInfo_t *pdevice = NULL;
4613
4614                                 /* Save the Port Page 2 data
4615                                  * (reformat into a 32bit quantity)
4616                                  */
4617                                 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4618                                 ioc->spi_data.PortFlags = data;
4619                                 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4620                                         pdevice = &pPP2->DeviceSettings[ii];
4621                                         data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4622                                                 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4623                                         ioc->spi_data.nvram[ii] = data;
4624                                 }
4625                         }
4626
4627                         pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4628                 }
4629         }
4630
4631         /* Update Adapter limits with those from NVRAM
4632          * Comment: Don't need to do this. Target performance
4633          * parameters will never exceed the adapters limits.
4634          */
4635
4636         return rc;
4637 }
4638
4639 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4640 /*      mpt_readScsiDevicePageHeaders - save version and length of SDP1
4641  *      @ioc: Pointer to a Adapter Strucutre
4642  *      @portnum: IOC port number
4643  *
4644  *      Return: -EFAULT if read of config page header fails
4645  *              or 0 if success.
4646  */
4647 static int
4648 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4649 {
4650         CONFIGPARMS              cfg;
4651         ConfigPageHeader_t       header;
4652
4653         /* Read the SCSI Device Page 1 header
4654          */
4655         header.PageVersion = 0;
4656         header.PageLength = 0;
4657         header.PageNumber = 1;
4658         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4659         cfg.hdr = &header;
4660         cfg.physAddr = -1;
4661         cfg.pageAddr = portnum;
4662         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4663         cfg.dir = 0;
4664         cfg.timeout = 0;
4665         if (mpt_config(ioc, &cfg) != 0)
4666                  return -EFAULT;
4667
4668         ioc->spi_data.sdp1version = cfg.hdr->PageVersion;
4669         ioc->spi_data.sdp1length = cfg.hdr->PageLength;
4670
4671         header.PageVersion = 0;
4672         header.PageLength = 0;
4673         header.PageNumber = 0;
4674         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4675         if (mpt_config(ioc, &cfg) != 0)
4676                  return -EFAULT;
4677
4678         ioc->spi_data.sdp0version = cfg.hdr->PageVersion;
4679         ioc->spi_data.sdp0length = cfg.hdr->PageLength;
4680
4681         dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4682                         ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4683
4684         dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4685                         ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4686         return 0;
4687 }
4688
4689 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4690 /**
4691  *      mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4692  *      @ioc: Pointer to a Adapter Strucutre
4693  *      @portnum: IOC port number
4694  *
4695  *      Return:
4696  *      0 on success
4697  *      -EFAULT if read of config page header fails or data pointer not NULL
4698  *      -ENOMEM if pci_alloc failed
4699  */
4700 int
4701 mpt_findImVolumes(MPT_ADAPTER *ioc)
4702 {
4703         IOCPage2_t              *pIoc2;
4704         u8                      *mem;
4705         ConfigPageIoc2RaidVol_t *pIocRv;
4706         dma_addr_t               ioc2_dma;
4707         CONFIGPARMS              cfg;
4708         ConfigPageHeader_t       header;
4709         int                      jj;
4710         int                      rc = 0;
4711         int                      iocpage2sz;
4712         u8                       nVols, nPhys;
4713         u8                       vid, vbus, vioc;
4714
4715         /* Read IOCP2 header then the page.
4716          */
4717         header.PageVersion = 0;
4718         header.PageLength = 0;
4719         header.PageNumber = 2;
4720         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4721         cfg.hdr = &header;
4722         cfg.physAddr = -1;
4723         cfg.pageAddr = 0;
4724         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4725         cfg.dir = 0;
4726         cfg.timeout = 0;
4727         if (mpt_config(ioc, &cfg) != 0)
4728                  return -EFAULT;
4729
4730         if (header.PageLength == 0)
4731                 return -EFAULT;
4732
4733         iocpage2sz = header.PageLength * 4;
4734         pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4735         if (!pIoc2)
4736                 return -ENOMEM;
4737
4738         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4739         cfg.physAddr = ioc2_dma;
4740         if (mpt_config(ioc, &cfg) != 0)
4741                 goto done_and_free;
4742
4743         if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) {
4744                 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4745                 if (mem) {
4746                         ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem;
4747                 } else {
4748                         goto done_and_free;
4749                 }
4750         }
4751         memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4752
4753         /* Identify RAID Volume Id's */
4754         nVols = pIoc2->NumActiveVolumes;
4755         if ( nVols == 0) {
4756                 /* No RAID Volume.
4757                  */
4758                 goto done_and_free;
4759         } else {
4760                 /* At least 1 RAID Volume
4761                  */
4762                 pIocRv = pIoc2->RaidVolume;
4763                 ioc->spi_data.isRaid = 0;
4764                 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4765                         vid = pIocRv->VolumeID;
4766                         vbus = pIocRv->VolumeBus;
4767                         vioc = pIocRv->VolumeIOC;
4768
4769                         /* find the match
4770                          */
4771                         if (vbus == 0) {
4772                                 ioc->spi_data.isRaid |= (1 << vid);
4773                         } else {
4774                                 /* Error! Always bus 0
4775                                  */
4776                         }
4777                 }
4778         }
4779
4780         /* Identify Hidden Physical Disk Id's */
4781         nPhys = pIoc2->NumActivePhysDisks;
4782         if (nPhys == 0) {
4783                 /* No physical disks.
4784                  */
4785         } else {
4786                 mpt_read_ioc_pg_3(ioc);
4787         }
4788
4789 done_and_free:
4790         pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4791
4792         return rc;
4793 }
4794
4795 int
4796 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4797 {
4798         IOCPage3_t              *pIoc3;
4799         u8                      *mem;
4800         CONFIGPARMS              cfg;
4801         ConfigPageHeader_t       header;
4802         dma_addr_t               ioc3_dma;
4803         int                      iocpage3sz = 0;
4804
4805         /* Free the old page
4806          */
4807         if (ioc->spi_data.pIocPg3) {
4808                 kfree(ioc->spi_data.pIocPg3);
4809                 ioc->spi_data.pIocPg3 = NULL;
4810         }
4811
4812         /* There is at least one physical disk.
4813          * Read and save IOC Page 3
4814          */
4815         header.PageVersion = 0;
4816         header.PageLength = 0;
4817         header.PageNumber = 3;
4818         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4819         cfg.hdr = &header;
4820         cfg.physAddr = -1;
4821         cfg.pageAddr = 0;
4822         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4823         cfg.dir = 0;
4824         cfg.timeout = 0;
4825         if (mpt_config(ioc, &cfg) != 0)
4826                 return 0;
4827
4828         if (header.PageLength == 0)
4829                 return 0;
4830
4831         /* Read Header good, alloc memory
4832          */
4833         iocpage3sz = header.PageLength * 4;
4834         pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4835         if (!pIoc3)
4836                 return 0;
4837
4838         /* Read the Page and save the data
4839          * into malloc'd memory.
4840          */
4841         cfg.physAddr = ioc3_dma;
4842         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4843         if (mpt_config(ioc, &cfg) == 0) {
4844                 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4845                 if (mem) {
4846                         memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4847                         ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
4848                 }
4849         }
4850
4851         pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4852
4853         return 0;
4854 }
4855
4856 static void
4857 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4858 {
4859         IOCPage4_t              *pIoc4;
4860         CONFIGPARMS              cfg;
4861         ConfigPageHeader_t       header;
4862         dma_addr_t               ioc4_dma;
4863         int                      iocpage4sz;
4864
4865         /* Read and save IOC Page 4
4866          */
4867         header.PageVersion = 0;
4868         header.PageLength = 0;
4869         header.PageNumber = 4;
4870         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4871         cfg.hdr = &header;
4872         cfg.physAddr = -1;
4873         cfg.pageAddr = 0;
4874         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4875         cfg.dir = 0;
4876         cfg.timeout = 0;
4877         if (mpt_config(ioc, &cfg) != 0)
4878                 return;
4879
4880         if (header.PageLength == 0)
4881                 return;
4882
4883         if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4884                 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4885                 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4886                 if (!pIoc4)
4887                         return;
4888         } else {
4889                 ioc4_dma = ioc->spi_data.IocPg4_dma;
4890                 iocpage4sz = ioc->spi_data.IocPg4Sz;
4891         }
4892
4893         /* Read the Page into dma memory.
4894          */
4895         cfg.physAddr = ioc4_dma;
4896         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4897         if (mpt_config(ioc, &cfg) == 0) {
4898                 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4899                 ioc->spi_data.IocPg4_dma = ioc4_dma;
4900                 ioc->spi_data.IocPg4Sz = iocpage4sz;
4901         } else {
4902                 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4903                 ioc->spi_data.pIocPg4 = NULL;
4904         }
4905 }
4906
4907 static void
4908 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4909 {
4910         IOCPage1_t              *pIoc1;
4911         CONFIGPARMS              cfg;
4912         ConfigPageHeader_t       header;
4913         dma_addr_t               ioc1_dma;
4914         int                      iocpage1sz = 0;
4915         u32                      tmp;
4916
4917         /* Check the Coalescing Timeout in IOC Page 1
4918          */
4919         header.PageVersion = 0;
4920         header.PageLength = 0;
4921         header.PageNumber = 1;
4922         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4923         cfg.hdr = &header;
4924         cfg.physAddr = -1;
4925         cfg.pageAddr = 0;
4926         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4927         cfg.dir = 0;
4928         cfg.timeout = 0;
4929         if (mpt_config(ioc, &cfg) != 0)
4930                 return;
4931
4932         if (header.PageLength == 0)
4933                 return;
4934
4935         /* Read Header good, alloc memory
4936          */
4937         iocpage1sz = header.PageLength * 4;
4938         pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4939         if (!pIoc1)
4940                 return;
4941
4942         /* Read the Page and check coalescing timeout
4943          */
4944         cfg.physAddr = ioc1_dma;
4945         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4946         if (mpt_config(ioc, &cfg) == 0) {
4947                 
4948                 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4949                 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4950                         tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4951
4952                         dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4953                                         ioc->name, tmp));
4954
4955                         if (tmp > MPT_COALESCING_TIMEOUT) {
4956                                 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4957
4958                                 /* Write NVRAM and current
4959                                  */
4960                                 cfg.dir = 1;
4961                                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4962                                 if (mpt_config(ioc, &cfg) == 0) {
4963                                         dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
4964                                                         ioc->name, MPT_COALESCING_TIMEOUT));
4965
4966                                         cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
4967                                         if (mpt_config(ioc, &cfg) == 0) {
4968                                                 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
4969                                                                 ioc->name, MPT_COALESCING_TIMEOUT));
4970                                         } else {
4971                                                 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
4972                                                                         ioc->name));
4973                                         }
4974
4975                                 } else {
4976                                         dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4977                                                                 ioc->name));
4978                                 }
4979                         }
4980
4981                 } else {
4982                         dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4983                 }
4984         }
4985
4986         pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
4987
4988         return;
4989 }
4990
4991 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4992 /*
4993  *      SendEventNotification - Send EventNotification (on or off) request
4994  *      to MPT adapter.
4995  *      @ioc: Pointer to MPT_ADAPTER structure
4996  *      @EvSwitch: Event switch flags
4997  */
4998 static int
4999 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5000 {
5001         EventNotification_t     *evnp;
5002
5003         evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc->id);
5004         if (evnp == NULL) {
5005                 dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5006                                 ioc->name));
5007                 return 0;
5008         }
5009         memset(evnp, 0, sizeof(*evnp));
5010
5011         dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch));
5012
5013         evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5014         evnp->ChainOffset = 0;
5015         evnp->MsgFlags = 0;
5016         evnp->Switch = EvSwitch;
5017
5018         mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)evnp);
5019
5020         return 0;
5021 }
5022
5023 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5024 /**
5025  *      SendEventAck - Send EventAck request to MPT adapter.
5026  *      @ioc: Pointer to MPT_ADAPTER structure
5027  *      @evnp: Pointer to original EventNotification request
5028  */
5029 static int
5030 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5031 {
5032         EventAck_t      *pAck;
5033
5034         if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
5035                 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n",
5036                                 ioc->name);
5037                 return -1;
5038         }
5039         memset(pAck, 0, sizeof(*pAck));
5040
5041         dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5042
5043         pAck->Function     = MPI_FUNCTION_EVENT_ACK;
5044         pAck->ChainOffset  = 0;
5045         pAck->MsgFlags     = 0;
5046         pAck->Event        = evnp->Event;
5047         pAck->EventContext = evnp->EventContext;
5048
5049         mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)pAck);
5050
5051         return 0;
5052 }
5053
5054 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5055 /**
5056  *      mpt_config - Generic function to issue config message
5057  *      @ioc - Pointer to an adapter structure
5058  *      @cfg - Pointer to a configuration structure. Struct contains
5059  *              action, page address, direction, physical address
5060  *              and pointer to a configuration page header
5061  *              Page header is updated.
5062  *
5063  *      Returns 0 for success
5064  *      -EPERM if not allowed due to ISR context
5065  *      -EAGAIN if no msg frames currently available
5066  *      -EFAULT for non-successful reply or no reply (timeout)
5067  */
5068 int
5069 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5070 {
5071         Config_t        *pReq;
5072         MPT_FRAME_HDR   *mf;
5073         unsigned long    flags;
5074         int              ii, rc;
5075         int              flagsLength;
5076         int              in_isr;
5077
5078         /* (Bugzilla:fibrebugs, #513)
5079          * Bug fix (part 1)!  20010905 -sralston
5080          *      Prevent calling wait_event() (below), if caller happens
5081          *      to be in ISR context, because that is fatal!
5082          */
5083         in_isr = in_interrupt();
5084         if (in_isr) {
5085                 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5086                                 ioc->name));
5087                 return -EPERM;
5088         }
5089
5090         /* Get and Populate a free Frame
5091          */
5092         if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
5093                 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5094                                 ioc->name));
5095                 return -EAGAIN;
5096         }
5097         pReq = (Config_t *)mf;
5098         pReq->Action = pCfg->action;
5099         pReq->Reserved = 0;
5100         pReq->ChainOffset = 0;
5101         pReq->Function = MPI_FUNCTION_CONFIG;
5102         pReq->ExtPageLength = 0;
5103         pReq->ExtPageType = 0;
5104         pReq->MsgFlags = 0;
5105         for (ii=0; ii < 8; ii++)
5106                 pReq->Reserved2[ii] = 0;
5107
5108         pReq->Header.PageVersion = pCfg->hdr->PageVersion;
5109         pReq->Header.PageLength = pCfg->hdr->PageLength;
5110         pReq->Header.PageNumber = pCfg->hdr->PageNumber;
5111         pReq->Header.PageType = (pCfg->hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5112         pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5113
5114         /* Add a SGE to the config request.
5115          */
5116         if (pCfg->dir)
5117                 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5118         else
5119                 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5120
5121         flagsLength |= pCfg->hdr->PageLength * 4;
5122
5123         mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5124
5125         dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5126                 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5127
5128         /* Append pCfg pointer to end of mf
5129          */
5130         *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) =  (void *) pCfg;
5131
5132         /* Initalize the timer
5133          */
5134         init_timer(&pCfg->timer);
5135         pCfg->timer.data = (unsigned long) ioc;
5136         pCfg->timer.function = mpt_timer_expired;
5137         pCfg->wait_done = 0;
5138
5139         /* Set the timer; ensure 10 second minimum */
5140         if (pCfg->timeout < 10)
5141                 pCfg->timer.expires = jiffies + HZ*10;
5142         else
5143                 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5144
5145         /* Add to end of Q, set timer and then issue this command */
5146         spin_lock_irqsave(&ioc->FreeQlock, flags);
5147         Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
5148         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5149
5150         add_timer(&pCfg->timer);
5151         mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
5152         wait_event(mpt_waitq, pCfg->wait_done);
5153
5154         /* mf has been freed - do not access */
5155
5156         rc = pCfg->status;
5157
5158         return rc;
5159 }
5160
5161 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5162 /**
5163  *      mpt_toolbox - Generic function to issue toolbox message
5164  *      @ioc - Pointer to an adapter structure
5165  *      @cfg - Pointer to a toolbox structure. Struct contains
5166  *              action, page address, direction, physical address
5167  *              and pointer to a configuration page header
5168  *              Page header is updated.
5169  *
5170  *      Returns 0 for success
5171  *      -EPERM if not allowed due to ISR context
5172  *      -EAGAIN if no msg frames currently available
5173  *      -EFAULT for non-successful reply or no reply (timeout)
5174  */
5175 int
5176 mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5177 {
5178         ToolboxIstwiReadWriteRequest_t  *pReq;
5179         MPT_FRAME_HDR   *mf;
5180         unsigned long    flags;
5181         int              rc;
5182         int              flagsLength;
5183         int              in_isr;
5184
5185         /* (Bugzilla:fibrebugs, #513)
5186          * Bug fix (part 1)!  20010905 -sralston
5187          *      Prevent calling wait_event() (below), if caller happens
5188          *      to be in ISR context, because that is fatal!
5189          */
5190         in_isr = in_interrupt();
5191         if (in_isr) {
5192                 dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
5193                                 ioc->name));
5194                 return -EPERM;
5195         }
5196
5197         /* Get and Populate a free Frame
5198          */
5199         if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
5200                 dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
5201                                 ioc->name));
5202                 return -EAGAIN;
5203         }
5204         pReq = (ToolboxIstwiReadWriteRequest_t  *)mf;
5205         pReq->Tool = pCfg->action;
5206         pReq->Reserved = 0;
5207         pReq->ChainOffset = 0;
5208         pReq->Function = MPI_FUNCTION_TOOLBOX;
5209         pReq->Reserved1 = 0;
5210         pReq->Reserved2 = 0;
5211         pReq->MsgFlags = 0;
5212         pReq->Flags = pCfg->dir;
5213         pReq->BusNum = 0;
5214         pReq->Reserved3 = 0;
5215         pReq->NumAddressBytes = 0x01;
5216         pReq->Reserved4 = 0;
5217         pReq->DataLength = 0x04;
5218         pReq->DeviceAddr = 0xB0;
5219         pReq->Addr1 = 0;
5220         pReq->Addr2 = 0;
5221         pReq->Addr3 = 0;
5222         pReq->Reserved5 = 0;
5223
5224         /* Add a SGE to the config request.
5225          */
5226
5227         flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
5228
5229         mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
5230
5231         dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
5232                 ioc->name, pReq->Tool));
5233
5234         /* Append pCfg pointer to end of mf
5235          */
5236         *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) =  (void *) pCfg;
5237
5238         /* Initalize the timer
5239          */
5240         init_timer(&pCfg->timer);
5241         pCfg->timer.data = (unsigned long) ioc;
5242         pCfg->timer.function = mpt_timer_expired;
5243         pCfg->wait_done = 0;
5244
5245         /* Set the timer; ensure 10 second minimum */
5246         if (pCfg->timeout < 10)
5247                 pCfg->timer.expires = jiffies + HZ*10;
5248         else
5249                 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5250
5251         /* Add to end of Q, set timer and then issue this command */
5252         spin_lock_irqsave(&ioc->FreeQlock, flags);
5253         Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
5254         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5255
5256         add_timer(&pCfg->timer);
5257         mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
5258         wait_event(mpt_waitq, pCfg->wait_done);
5259
5260         /* mf has been freed - do not access */
5261
5262         rc = pCfg->status;
5263
5264         return rc;
5265 }
5266
5267 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5268 /*
5269  *      mpt_timer_expired - Call back for timer process.
5270  *      Used only internal config functionality.
5271  *      @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5272  */
5273 static void
5274 mpt_timer_expired(unsigned long data)
5275 {
5276         MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5277
5278         dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5279
5280         /* Perform a FW reload */
5281         if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5282                 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5283
5284         /* No more processing.
5285          * Hard reset clean-up will wake up
5286          * process and free all resources.
5287          */
5288         dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5289
5290         return;
5291 }
5292
5293 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5294 /*
5295  *      mpt_ioc_reset - Base cleanup for hard reset
5296  *      @ioc: Pointer to the adapter structure
5297  *      @reset_phase: Indicates pre- or post-reset functionality
5298  *
5299  *      Remark: Free's resources with internally generated commands.
5300  */
5301 static int
5302 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5303 {
5304         CONFIGPARMS *pCfg;
5305         unsigned long flags;
5306
5307         dprintk((KERN_WARNING MYNAM
5308                         ": IOC %s_reset routed to MPT base driver!\n",
5309                         reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5310                         reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5311
5312         if (reset_phase == MPT_IOC_SETUP_RESET) {
5313                 ;
5314         } else if (reset_phase == MPT_IOC_PRE_RESET) {
5315                 /* If the internal config Q is not empty -
5316                  * delete timer. MF resources will be freed when
5317                  * the FIFO's are primed.
5318                  */
5319                 spin_lock_irqsave(&ioc->FreeQlock, flags);
5320                 if (! Q_IS_EMPTY(&ioc->configQ)){
5321                         pCfg = (CONFIGPARMS *)ioc->configQ.head;
5322                         do {
5323                                 del_timer(&pCfg->timer);
5324                                 pCfg = (CONFIGPARMS *) (pCfg->linkage.forw);
5325                         } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
5326                 }
5327                 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5328
5329         } else {
5330                 CONFIGPARMS *pNext;
5331
5332                 /* Search the configQ for internal commands.
5333                  * Flush the Q, and wake up all suspended threads.
5334                  */
5335                 spin_lock_irqsave(&ioc->FreeQlock, flags);
5336                 if (! Q_IS_EMPTY(&ioc->configQ)){
5337                         pCfg = (CONFIGPARMS *)ioc->configQ.head;
5338                         do {
5339                                 pNext = (CONFIGPARMS *) pCfg->linkage.forw;
5340
5341                                 Q_DEL_ITEM(&pCfg->linkage);
5342
5343                                 pCfg->status = MPT_CONFIG_ERROR;
5344                                 pCfg->wait_done = 1;
5345                                 wake_up(&mpt_waitq);
5346
5347                                 pCfg = pNext;
5348                         } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
5349                 }
5350                 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5351         }
5352
5353         return 1;               /* currently means nothing really */
5354 }
5355
5356
5357 #ifdef CONFIG_PROC_FS           /* { */
5358 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5359 /*
5360  *      procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5361  */
5362 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5363 /*
5364  *      procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5365  *
5366  *      Returns 0 for success, non-zero for failure.
5367  */
5368 static int
5369 procmpt_create(void)
5370 {
5371         MPT_ADAPTER             *ioc;
5372         struct proc_dir_entry   *ent;
5373         int      ii;
5374
5375         /*
5376          *      BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
5377          *      (single level) to multi level (e.g. "driver/message/fusion")
5378          *      something here needs to change.  -sralston
5379          */
5380         mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5381         if (mpt_proc_root_dir == NULL)
5382                 return -ENOTDIR;
5383
5384         for (ii=0; ii < MPT_PROC_ENTRIES; ii++) {
5385                 ent = create_proc_entry(mpt_proc_list[ii].name,
5386                                 S_IFREG|S_IRUGO, mpt_proc_root_dir);
5387                 if (!ent) {
5388                         printk(KERN_WARNING MYNAM
5389                                         ": WARNING - Could not create /proc/mpt/%s entry\n",
5390                                         mpt_proc_list[ii].name);
5391                         continue;
5392                 }
5393                 ent->read_proc = mpt_proc_list[ii].f;
5394                 ent->data      = NULL;
5395         }
5396
5397         ioc = mpt_adapter_find_first();
5398         while (ioc != NULL) {
5399                 struct proc_dir_entry   *dent;
5400                 /*
5401                  *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
5402                  */
5403                 if ((dent = proc_mkdir(ioc->name, mpt_proc_root_dir)) != NULL) {
5404                         /*
5405                          *  And populate it with mpt_ioc_proc_list[] entries.
5406                          */
5407                         for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) {
5408                                 ent = create_proc_entry(mpt_ioc_proc_list[ii].name,
5409                                                 S_IFREG|S_IRUGO, dent);
5410                                 if (!ent) {
5411                                         printk(KERN_WARNING MYNAM
5412                                                         ": WARNING - Could not create /proc/mpt/%s/%s entry!\n",
5413                                                         ioc->name,
5414                                                         mpt_ioc_proc_list[ii].name);
5415                                         continue;
5416                                 }
5417                                 ent->read_proc = mpt_ioc_proc_list[ii].f;
5418                                 ent->data      = ioc;
5419                         }
5420                 } else {
5421                         printk(MYIOC_s_WARN_FMT "Could not create /proc/mpt/%s subdir entry!\n",
5422                                         ioc->name, mpt_ioc_proc_list[ii].name);
5423                 }
5424                 ioc = mpt_adapter_find_next(ioc);
5425         }
5426
5427         return 0;
5428 }
5429
5430 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5431 /*
5432  *      procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5433  *
5434  *      Returns 0 for success, non-zero for failure.
5435  */
5436 static int
5437 procmpt_destroy(void)
5438 {
5439         MPT_ADAPTER     *ioc;
5440         int              ii;
5441
5442         if (!mpt_proc_root_dir)
5443                 return 0;
5444
5445         /*
5446          *      BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
5447          *      (single level) to multi level (e.g. "driver/message/fusion")
5448          *      something here needs to change.  -sralston
5449          */
5450
5451         ioc = mpt_adapter_find_first();
5452         while (ioc != NULL) {
5453                 char pname[32];
5454                 int namelen;
5455
5456                 namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
5457
5458                 /*
5459                  *  Tear down each "/proc/mpt/iocN" subdirectory.
5460                  */
5461                 for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) {
5462                         (void) sprintf(pname+namelen, "/%s", mpt_ioc_proc_list[ii].name);
5463                         remove_proc_entry(pname, NULL);
5464                 }
5465                 remove_proc_entry(ioc->name, mpt_proc_root_dir);
5466                 ioc = mpt_adapter_find_next(ioc);
5467         }
5468
5469         for (ii=0; ii < MPT_PROC_ENTRIES; ii++)
5470                 remove_proc_entry(mpt_proc_list[ii].name, mpt_proc_root_dir);
5471
5472         if (atomic_read((atomic_t *)&mpt_proc_root_dir->count) == 0) {
5473                 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5474                 mpt_proc_root_dir = NULL;
5475                 return 0;
5476         }
5477
5478         return -1;
5479 }
5480
5481 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5482 /*
5483  *      procmpt_summary_read - Handle read request from /proc/mpt/summary
5484  *      or from /proc/mpt/iocN/summary.
5485  *      @buf: Pointer to area to write information
5486  *      @start: Pointer to start pointer
5487  *      @offset: Offset to start writing
5488  *      @request:
5489  *      @eof: Pointer to EOF integer
5490  *      @data: Pointer
5491  *
5492  *      Returns number of characters written to process performing the read.
5493  */
5494 static int
5495 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5496 {
5497         MPT_ADAPTER *ioc;
5498         char *out = buf;
5499         int len;
5500
5501         if (data == NULL)
5502                 ioc = mpt_adapter_find_first();
5503         else
5504                 ioc = data;
5505
5506         while (ioc) {
5507                 int     more = 0;
5508
5509                 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5510
5511                 out += more;
5512                 if ((out-buf) >= request) {
5513                         break;
5514                 }
5515
5516                 if (data == NULL)
5517                         ioc = mpt_adapter_find_next(ioc);
5518                 else
5519                         ioc = NULL;             /* force exit for iocN */
5520         }
5521         len = out - buf;
5522
5523         MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5524 }
5525
5526 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5527 /*
5528  *      procmpt_version_read - Handle read request from /proc/mpt/version.
5529  *      @buf: Pointer to area to write information
5530  *      @start: Pointer to start pointer
5531  *      @offset: Offset to start writing
5532  *      @request:
5533  *      @eof: Pointer to EOF integer
5534  *      @data: Pointer
5535  *
5536  *      Returns number of characters written to process performing the read.
5537  */
5538 static int
5539 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5540 {
5541         int      ii;
5542         int      scsi, lan, ctl, targ, dmp;
5543         char    *drvname;
5544         int      len;
5545
5546         len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5547         len += sprintf(buf+len, "  Fusion MPT base driver\n");
5548
5549         scsi = lan = ctl = targ = dmp = 0;
5550         for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5551                 drvname = NULL;
5552                 if (MptCallbacks[ii]) {
5553                         switch (MptDriverClass[ii]) {
5554                         case MPTSCSIH_DRIVER:
5555                                 if (!scsi++) drvname = "SCSI host";
5556                                 break;
5557                         case MPTLAN_DRIVER:
5558                                 if (!lan++) drvname = "LAN";
5559                                 break;
5560                         case MPTSTM_DRIVER:
5561                                 if (!targ++) drvname = "SCSI target";
5562                                 break;
5563                         case MPTCTL_DRIVER:
5564                                 if (!ctl++) drvname = "ioctl";
5565                                 break;
5566                         case MPTDMP_DRIVER:
5567                                 if (!dmp++) drvname = "DMP";
5568                                 break;
5569                         }
5570
5571                         if (drvname)
5572                                 len += sprintf(buf+len, "  Fusion MPT %s driver\n", drvname);
5573                         /*
5574                          *      Handle isense special case, because it
5575                          *      doesn't do a formal mpt_register call.
5576                          */
5577                         if (isense_idx == ii)
5578                                 len += sprintf(buf+len, "  Fusion MPT isense driver\n");
5579                 }
5580         }
5581
5582         MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5583 }
5584
5585 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5586 /*
5587  *      procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5588  *      @buf: Pointer to area to write information
5589  *      @start: Pointer to start pointer
5590  *      @offset: Offset to start writing
5591  *      @request:
5592  *      @eof: Pointer to EOF integer
5593  *      @data: Pointer
5594  *
5595  *      Returns number of characters written to process performing the read.
5596  */
5597 static int
5598 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5599 {
5600         MPT_ADAPTER     *ioc = data;
5601         int              len;
5602         char             expVer[32];
5603         int              sz;
5604         int              p;
5605
5606         mpt_get_fw_exp_ver(expVer, ioc);
5607
5608         len = sprintf(buf, "%s:", ioc->name);
5609         if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5610                 len += sprintf(buf+len, "  (f/w download boot flag set)");
5611 //      if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5612 //              len += sprintf(buf+len, "  CONFIG_CHECKSUM_FAIL!");
5613
5614         len += sprintf(buf+len, "\n  ProductID = 0x%04x (%s)\n",
5615                         ioc->facts.ProductID,
5616                         ioc->prod_name);
5617         len += sprintf(buf+len, "  FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5618         if (ioc->facts.FWImageSize)
5619                 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5620         len += sprintf(buf+len, "\n  MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5621         len += sprintf(buf+len, "  FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5622         len += sprintf(buf+len, "  EventState = 0x%02x\n", ioc->facts.EventState);
5623
5624         len += sprintf(buf+len, "  CurrentHostMfaHighAddr = 0x%08x\n",
5625                         ioc->facts.CurrentHostMfaHighAddr);
5626         len += sprintf(buf+len, "  CurrentSenseBufferHighAddr = 0x%08x\n",
5627                         ioc->facts.CurrentSenseBufferHighAddr);
5628
5629         len += sprintf(buf+len, "  MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5630         len += sprintf(buf+len, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5631
5632         len += sprintf(buf+len, "  RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5633                                         (void *)ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma);
5634         /*
5635          *  Rounding UP to nearest 4-kB boundary here...
5636          */
5637         sz = (ioc->req_sz * ioc->req_depth) + 128;
5638         sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5639         len += sprintf(buf+len, "    {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5640                                         ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5641         len += sprintf(buf+len, "    {MaxReqSz=%d}   {MaxReqDepth=%d}\n",
5642                                         4*ioc->facts.RequestFrameSize,
5643                                         ioc->facts.GlobalCredits);
5644
5645         len += sprintf(buf+len, "  ReplyFrames   @ 0x%p (Dma @ 0x%p)\n",
5646                                         (void *)ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma);
5647         sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5648         len += sprintf(buf+len, "    {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5649                                         ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5650         len += sprintf(buf+len, "    {MaxRepSz=%d}   {MaxRepDepth=%d}\n",
5651                                         ioc->facts.CurReplyFrameSize,
5652                                         ioc->facts.ReplyQueueDepth);
5653
5654         len += sprintf(buf+len, "  MaxDevices = %d\n",
5655                         (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5656         len += sprintf(buf+len, "  MaxBuses = %d\n", ioc->facts.MaxBuses);
5657
5658         /* per-port info */
5659         for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5660                 len += sprintf(buf+len, "  PortNumber = %d (of %d)\n",
5661                                 p+1,
5662                                 ioc->facts.NumberOfPorts);
5663                 if ((int)ioc->chip_type <= (int)FC929) {
5664                         if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5665                                 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5666                                 len += sprintf(buf+len, "    LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5667                                                 a[5], a[4], a[3], a[2], a[1], a[0]);
5668                         }
5669                         len += sprintf(buf+len, "    WWN = %08X%08X:%08X%08X\n",
5670                                         ioc->fc_port_page0[p].WWNN.High,
5671                                         ioc->fc_port_page0[p].WWNN.Low,
5672                                         ioc->fc_port_page0[p].WWPN.High,
5673                                         ioc->fc_port_page0[p].WWPN.Low);
5674                 }
5675         }
5676
5677         MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5678 }
5679
5680 #endif          /* CONFIG_PROC_FS } */
5681
5682 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5683 static void
5684 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5685 {
5686         buf[0] ='\0';
5687         if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5688                 sprintf(buf, " (Exp %02d%02d)",
5689                         (ioc->facts.FWVersion.Word >> 16) & 0x00FF,     /* Month */
5690                         (ioc->facts.FWVersion.Word >> 8) & 0x1F);       /* Day */
5691
5692                 /* insider hack! */
5693                 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5694                         strcat(buf, " [MDBG]");
5695         }
5696 }
5697
5698 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5699 /**
5700  *      mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5701  *      @ioc: Pointer to MPT_ADAPTER structure
5702  *      @buffer: Pointer to buffer where IOC summary info should be written
5703  *      @size: Pointer to number of bytes we wrote (set by this routine)
5704  *      @len: Offset at which to start writing in buffer
5705  *      @showlan: Display LAN stuff?
5706  *
5707  *      This routine writes (english readable) ASCII text, which represents
5708  *      a summary of IOC information, to a buffer.
5709  */
5710 void
5711 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5712 {
5713         char expVer[32];
5714         int y;
5715
5716         mpt_get_fw_exp_ver(expVer, ioc);
5717
5718         /*
5719          *  Shorter summary of attached ioc's...
5720          */
5721         y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5722                         ioc->name,
5723                         ioc->prod_name,
5724                         MPT_FW_REV_MAGIC_ID_STRING,     /* "FwRev=" or somesuch */
5725                         ioc->facts.FWVersion.Word,
5726                         expVer,
5727                         ioc->facts.NumberOfPorts,
5728                         ioc->req_depth);
5729
5730         if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5731                 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5732                 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5733                         a[5], a[4], a[3], a[2], a[1], a[0]);
5734         }
5735
5736 #ifndef __sparc__
5737         y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5738 #else
5739         y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5740 #endif
5741
5742         if (!ioc->active)
5743                 y += sprintf(buffer+len+y, " (disabled)");
5744
5745         y += sprintf(buffer+len+y, "\n");
5746
5747         *size = y;
5748 }
5749
5750 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5751 /*
5752  *      Reset Handling
5753  */
5754 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5755 /**
5756  *      mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5757  *      Management call based on input arg values.  If TaskMgmt fails,
5758  *      return associated SCSI request.
5759  *      @ioc: Pointer to MPT_ADAPTER structure
5760  *      @sleepFlag: Indicates if sleep or schedule must be called.
5761  *
5762  *      Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5763  *      or a non-interrupt thread.  In the former, must not call schedule().
5764  *
5765  *      Remark: A return of -1 is a FATAL error case, as it means a
5766  *      FW reload/initialization failed.
5767  *
5768  *      Returns 0 for SUCCESS or -1 if FAILED.
5769  */
5770 int
5771 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5772 {
5773         int              rc;
5774         unsigned long    flags;
5775
5776         dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5777 #ifdef MFCNT
5778         printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5779         printk("MF count 0x%x !\n", ioc->mfcnt);
5780 #endif
5781
5782         /* Reset the adapter. Prevent more than 1 call to
5783          * mpt_do_ioc_recovery at any instant in time.
5784          */
5785         spin_lock_irqsave(&ioc->diagLock, flags);
5786         if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5787                 spin_unlock_irqrestore(&ioc->diagLock, flags);
5788                 return 0;
5789         } else {
5790                 ioc->diagPending = 1;
5791         }
5792         spin_unlock_irqrestore(&ioc->diagLock, flags);
5793
5794         /* FIXME: If do_ioc_recovery fails, repeat....
5795          */
5796
5797         /* The SCSI driver needs to adjust timeouts on all current
5798          * commands prior to the diagnostic reset being issued.
5799          * Prevents timeouts occuring during a diagnostic reset...very bad.
5800          * For all other protocol drivers, this is a no-op.
5801          */
5802         {
5803                 int      ii;
5804                 int      r = 0;
5805
5806                 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5807                         if (MptResetHandlers[ii]) {
5808                                 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5809                                                 ioc->name, ii));
5810                                 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
5811                                 if (ioc->alt_ioc) {
5812                                         dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5813                                                         ioc->name, ioc->alt_ioc->name, ii));
5814                                         r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5815                                 }
5816                         }
5817                 }
5818         }
5819
5820         if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5821                 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5822                         rc, ioc->name);
5823         }
5824         ioc->reload_fw = 0;
5825         if (ioc->alt_ioc)
5826                 ioc->alt_ioc->reload_fw = 0;
5827
5828         spin_lock_irqsave(&ioc->diagLock, flags);
5829         ioc->diagPending = 0;
5830         if (ioc->alt_ioc)
5831                 ioc->alt_ioc->diagPending = 0;
5832         spin_unlock_irqrestore(&ioc->diagLock, flags);
5833
5834         dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5835
5836         return rc;
5837 }
5838
5839 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5840 static char *
5841 EventDescriptionStr(u8 event, u32 evData0)
5842 {
5843         char *ds;
5844
5845         switch(event) {
5846         case MPI_EVENT_NONE:
5847                 ds = "None";
5848                 break;
5849         case MPI_EVENT_LOG_DATA:
5850                 ds = "Log Data";
5851                 break;
5852         case MPI_EVENT_STATE_CHANGE:
5853                 ds = "State Change";
5854                 break;
5855         case MPI_EVENT_UNIT_ATTENTION:
5856                 ds = "Unit Attention";
5857                 break;
5858         case MPI_EVENT_IOC_BUS_RESET:
5859                 ds = "IOC Bus Reset";
5860                 break;
5861         case MPI_EVENT_EXT_BUS_RESET:
5862                 ds = "External Bus Reset";
5863                 break;
5864         case MPI_EVENT_RESCAN:
5865                 ds = "Bus Rescan Event";
5866                 /* Ok, do we need to do anything here? As far as
5867                    I can tell, this is when a new device gets added
5868                    to the loop. */
5869                 break;
5870         case MPI_EVENT_LINK_STATUS_CHANGE:
5871                 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5872                         ds = "Link Status(FAILURE) Change";
5873                 else
5874                         ds = "Link Status(ACTIVE) Change";
5875                 break;
5876         case MPI_EVENT_LOOP_STATE_CHANGE:
5877                 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5878                         ds = "Loop State(LIP) Change";
5879                 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5880                         ds = "Loop State(LPE) Change";                  /* ??? */
5881                 else
5882                         ds = "Loop State(LPB) Change";                  /* ??? */
5883                 break;
5884         case MPI_EVENT_LOGOUT:
5885                 ds = "Logout";
5886                 break;
5887         case MPI_EVENT_EVENT_CHANGE:
5888                 if (evData0)
5889                         ds = "Events(ON) Change";
5890                 else
5891                         ds = "Events(OFF) Change";
5892                 break;
5893         case MPI_EVENT_INTEGRATED_RAID:
5894                 ds = "Integrated Raid";
5895                 break;
5896         /*
5897          *  MPT base "custom" events may be added here...
5898          */
5899         default:
5900                 ds = "Unknown";
5901                 break;
5902         }
5903         return ds;
5904 }
5905
5906 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5907 /*
5908  *      ProcessEventNotification - Route a received EventNotificationReply to
5909  *      all currently regeistered event handlers.
5910  *      @ioc: Pointer to MPT_ADAPTER structure
5911  *      @pEventReply: Pointer to EventNotification reply frame
5912  *      @evHandlers: Pointer to integer, number of event handlers
5913  *
5914  *      Returns sum of event handlers return values.
5915  */
5916 static int
5917 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
5918 {
5919         u16 evDataLen;
5920         u32 evData0 = 0;
5921 //      u32 evCtx;
5922         int ii;
5923         int r = 0;
5924         int handlers = 0;
5925         char *evStr;
5926         u8 event;
5927
5928         /*
5929          *  Do platform normalization of values
5930          */
5931         event = le32_to_cpu(pEventReply->Event) & 0xFF;
5932 //      evCtx = le32_to_cpu(pEventReply->EventContext);
5933         evDataLen = le16_to_cpu(pEventReply->EventDataLength);
5934         if (evDataLen) {
5935                 evData0 = le32_to_cpu(pEventReply->Data[0]);
5936         }
5937
5938         evStr = EventDescriptionStr(event, evData0);
5939         dprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
5940                         ioc->name,
5941                         evStr,
5942                         event));
5943
5944 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
5945         printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
5946         for (ii = 0; ii < evDataLen; ii++)
5947                 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
5948         printk("\n");
5949 #endif
5950
5951         /*
5952          *  Do general / base driver event processing
5953          */
5954         switch(event) {
5955         case MPI_EVENT_NONE:                    /* 00 */
5956         case MPI_EVENT_LOG_DATA:                /* 01 */
5957         case MPI_EVENT_STATE_CHANGE:            /* 02 */
5958         case MPI_EVENT_UNIT_ATTENTION:          /* 03 */
5959         case MPI_EVENT_IOC_BUS_RESET:           /* 04 */
5960         case MPI_EVENT_EXT_BUS_RESET:           /* 05 */
5961         case MPI_EVENT_RESCAN:                  /* 06 */
5962         case MPI_EVENT_LINK_STATUS_CHANGE:      /* 07 */
5963         case MPI_EVENT_LOOP_STATE_CHANGE:       /* 08 */
5964         case MPI_EVENT_LOGOUT:                  /* 09 */
5965         case MPI_EVENT_INTEGRATED_RAID:         /* 0B */
5966         case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:       /* 0C */
5967         default:
5968                 break;
5969         case MPI_EVENT_EVENT_CHANGE:            /* 0A */
5970                 if (evDataLen) {
5971                         u8 evState = evData0 & 0xFF;
5972
5973                         /* CHECKME! What if evState unexpectedly says OFF (0)? */
5974
5975                         /* Update EventState field in cached IocFacts */
5976                         if (ioc->facts.Function) {
5977                                 ioc->facts.EventState = evState;
5978                         }
5979                 }
5980                 break;
5981         }
5982
5983         /*
5984          * Should this event be logged? Events are written sequentially.
5985          * When buffer is full, start again at the top.
5986          */
5987         if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
5988                 int idx;
5989
5990                 idx = ioc->eventContext % ioc->eventLogSize;
5991
5992                 ioc->events[idx].event = event;
5993                 ioc->events[idx].eventContext = ioc->eventContext;
5994
5995                 for (ii = 0; ii < 2; ii++) {
5996                         if (ii < evDataLen)
5997                                 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
5998                         else
5999                                 ioc->events[idx].data[ii] =  0;
6000                 }
6001
6002                 ioc->eventContext++;
6003         }
6004
6005
6006         /*
6007          *  Call each currently registered protocol event handler.
6008          */
6009         for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6010                 if (MptEvHandlers[ii]) {
6011                         dprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6012                                         ioc->name, ii));
6013                         r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6014                         handlers++;
6015                 }
6016         }
6017         /* FIXME?  Examine results here? */
6018
6019         /*
6020          *  If needed, send (a single) EventAck.
6021          */
6022         if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6023                 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6024                         printk(MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6025                                         ioc->name, ii);
6026                 }
6027         }
6028
6029         *evHandlers = handlers;
6030         return r;
6031 }
6032
6033 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6034 /*
6035  *      mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6036  *      @ioc: Pointer to MPT_ADAPTER structure
6037  *      @log_info: U32 LogInfo reply word from the IOC
6038  *
6039  *      Refer to lsi/fc_log.h.
6040  */
6041 static void
6042 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6043 {
6044         static char *subcl_str[8] = {
6045                 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6046                 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6047         };
6048         u8 subcl = (log_info >> 24) & 0x7;
6049 //      u32 SubCl = log_info & 0x27000000;
6050
6051         printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}",
6052                         ioc->name, log_info, subcl_str[subcl]);
6053 }
6054
6055 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6056 /*
6057  *      mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
6058  *      @ioc: Pointer to MPT_ADAPTER structure
6059  *      @mr: Pointer to MPT reply frame
6060  *      @log_info: U32 LogInfo word from the IOC
6061  *
6062  *      Refer to lsi/sp_log.h.
6063  */
6064 static void
6065 mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
6066 {
6067         u32 info = log_info & 0x00FF0000;
6068         char *desc = "unknown";
6069
6070         switch (info) {
6071         case 0x00010000:
6072                 desc = "bug! MID not found";
6073                 if (ioc->reload_fw == 0)
6074                         ioc->reload_fw++;
6075                 break;
6076
6077         case 0x00020000:
6078                 desc = "Parity Error";
6079                 break;
6080
6081         case 0x00030000:
6082                 desc = "ASYNC Outbound Overrun";
6083                 break;
6084
6085         case 0x00040000:
6086                 desc = "SYNC Offset Error";
6087                 break;
6088
6089         case 0x00050000:
6090                 desc = "BM Change";
6091                 break;
6092
6093         case 0x00060000:
6094                 desc = "Msg In Overflow";
6095                 break;
6096
6097         case 0x00070000:
6098                 desc = "DMA Error";
6099                 break;
6100
6101         case 0x00080000:
6102                 desc = "Outbound DMA Overrun";
6103                 break;
6104         
6105         case 0x00090000:
6106                 desc = "Task Management";
6107                 break;
6108
6109         case 0x000A0000:
6110                 desc = "Device Problem";
6111                 break;
6112
6113         case 0x000B0000:
6114                 desc = "Invalid Phase Change";
6115                 break;
6116
6117         case 0x000C0000:
6118                 desc = "Untagged Table Size";
6119                 break;
6120         
6121         }
6122
6123         printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6124 }
6125
6126 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6127 /*
6128  *      mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6129  *      @ioc: Pointer to MPT_ADAPTER structure
6130  *      @ioc_status: U32 IOCStatus word from IOC
6131  *      @mf: Pointer to MPT request frame
6132  *
6133  *      Refer to lsi/mpi.h.
6134  */
6135 static void
6136 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6137 {
6138         u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6139         char *desc = "";
6140
6141         switch (status) {
6142         case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6143                 desc = "Invalid Function";
6144                 break;
6145
6146         case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6147                 desc = "Busy";
6148                 break;
6149
6150         case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6151                 desc = "Invalid SGL";
6152                 break;
6153
6154         case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6155                 desc = "Internal Error";
6156                 break;
6157
6158         case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6159                 desc = "Reserved";
6160                 break;
6161
6162         case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6163                 desc = "Insufficient Resources";
6164                 break;
6165
6166         case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6167                 desc = "Invalid Field";
6168                 break;
6169
6170         case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6171                 desc = "Invalid State";
6172                 break;
6173
6174         case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6175         case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
6176         case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
6177         case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
6178         case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
6179         case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
6180                 /* No message for Config IOCStatus values */
6181                 break;
6182
6183         case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6184                 /* No message for recovered error
6185                 desc = "SCSI Recovered Error";
6186                 */
6187                 break;
6188
6189         case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6190                 desc = "SCSI Invalid Bus";
6191                 break;
6192
6193         case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6194                 desc = "SCSI Invalid TargetID";
6195                 break;
6196
6197         case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6198           {
6199                 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6200                 U8 cdb = pScsiReq->CDB[0];
6201                 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6202                         desc = "SCSI Device Not There";
6203                 }
6204                 break;
6205           }
6206
6207         case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6208                 desc = "SCSI Data Overrun";
6209                 break;
6210
6211         case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6212                 /* This error is checked in scsi_io_done(). Skip. 
6213                 desc = "SCSI Data Underrun";
6214                 */
6215                 break;
6216
6217         case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6218                 desc = "SCSI I/O Data Error";
6219                 break;
6220
6221         case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6222                 desc = "SCSI Protocol Error";
6223                 break;
6224
6225         case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6226                 desc = "SCSI Task Terminated";
6227                 break;
6228
6229         case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6230                 desc = "SCSI Residual Mismatch";
6231                 break;
6232
6233         case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6234                 desc = "SCSI Task Management Failed";
6235                 break;
6236
6237         case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6238                 desc = "SCSI IOC Terminated";
6239                 break;
6240
6241         case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6242                 desc = "SCSI Ext Terminated";
6243                 break;
6244
6245         default:
6246                 desc = "Others";
6247                 break;
6248         }
6249         if (desc != "")
6250                 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6251 }
6252
6253 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6254 /**
6255  *      mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI
6256  *      OpCode strings from the (optional) isense module.
6257  *      @ascqTable: Pointer to ASCQ_Table_t structure
6258  *      @ascqtbl_sz: Number of entries in ASCQ_Table
6259  *      @opsTable: Pointer to array of SCSI OpCode strings (char pointers)
6260  *
6261  *      Specialized driver registration routine for the isense driver.
6262  */
6263 int
6264 mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable)
6265 {
6266         int r = 0;
6267
6268         if (ascqTable && ascqtbl_sz && opsTable) {
6269                 mpt_v_ASCQ_TablePtr = ascqTable;
6270                 mpt_ASCQ_TableSz = ascqtbl_sz;
6271                 mpt_ScsiOpcodesPtr = opsTable;
6272                 printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n");
6273                 isense_idx = last_drv_idx;
6274                 r = 1;
6275         }
6276         return r;
6277 }
6278
6279 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6280 /**
6281  *      mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI
6282  *      OpCode strings from the isense driver.
6283  *
6284  *      Specialized driver deregistration routine for the isense driver.
6285  */
6286 void
6287 mpt_deregister_ascqops_strings(void)
6288 {
6289         mpt_v_ASCQ_TablePtr = NULL;
6290         mpt_ASCQ_TableSz = 0;
6291         mpt_ScsiOpcodesPtr = NULL;
6292         printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
6293         isense_idx = -1;
6294 }
6295
6296 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6297
6298 EXPORT_SYMBOL(mpt_adapters);
6299 EXPORT_SYMBOL(mpt_proc_root_dir);
6300 EXPORT_SYMBOL(DmpService);
6301 EXPORT_SYMBOL(mpt_register);
6302 EXPORT_SYMBOL(mpt_deregister);
6303 EXPORT_SYMBOL(mpt_event_register);
6304 EXPORT_SYMBOL(mpt_event_deregister);
6305 EXPORT_SYMBOL(mpt_reset_register);
6306 EXPORT_SYMBOL(mpt_reset_deregister);
6307 EXPORT_SYMBOL(mpt_device_driver_register);
6308 EXPORT_SYMBOL(mpt_device_driver_deregister);
6309 EXPORT_SYMBOL(mpt_get_msg_frame);
6310 EXPORT_SYMBOL(mpt_put_msg_frame);
6311 EXPORT_SYMBOL(mpt_free_msg_frame);
6312 EXPORT_SYMBOL(mpt_add_sge);
6313 EXPORT_SYMBOL(mpt_add_chain);
6314 EXPORT_SYMBOL(mpt_send_handshake_request);
6315 EXPORT_SYMBOL(mpt_handshake_req_reply_wait);
6316 EXPORT_SYMBOL(mpt_adapter_find_first);
6317 EXPORT_SYMBOL(mpt_adapter_find_next);
6318 EXPORT_SYMBOL(mpt_verify_adapter);
6319 EXPORT_SYMBOL(mpt_GetIocState);
6320 EXPORT_SYMBOL(mpt_print_ioc_summary);
6321 EXPORT_SYMBOL(mpt_lan_index);
6322 EXPORT_SYMBOL(mpt_stm_index);
6323 EXPORT_SYMBOL(mpt_HardResetHandler);
6324 EXPORT_SYMBOL(mpt_config);
6325 EXPORT_SYMBOL(mpt_toolbox);
6326 EXPORT_SYMBOL(mpt_findImVolumes);
6327 EXPORT_SYMBOL(mpt_read_ioc_pg_3);
6328 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6329 EXPORT_SYMBOL(mpt_free_fw_memory);
6330
6331 EXPORT_SYMBOL(mpt_register_ascqops_strings);
6332 EXPORT_SYMBOL(mpt_deregister_ascqops_strings);
6333 EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr);
6334 EXPORT_SYMBOL(mpt_ASCQ_TableSz);
6335 EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
6336
6337
6338 static struct pci_driver mptbase_driver = {
6339         .name           = "mptbase",
6340         .id_table       = mptbase_pci_table,
6341         .probe          = mptbase_probe,
6342         .remove         = __devexit_p(mptbase_remove),
6343         .driver         = {
6344                 .shutdown = mptbase_shutdown,
6345         },
6346 #ifdef CONFIG_PM
6347         .suspend        = mptbase_suspend,
6348         .resume         = mptbase_resume,
6349 #endif
6350 };
6351
6352 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6353 /*
6354  *      fusion_init - Fusion MPT base driver initialization routine.
6355  *
6356  *      Returns 0 for success, non-zero for failure.
6357  */
6358 static int __init
6359 fusion_init(void)
6360 {
6361         int i;
6362         int r;
6363
6364         if (FusionInitCalled++) {
6365                 dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n"));
6366                 return 0;
6367         }
6368
6369         show_mptmod_ver(my_NAME, my_VERSION);
6370         printk(KERN_INFO COPYRIGHT "\n");
6371
6372         Q_INIT(&MptAdapters, MPT_ADAPTER);                      /* set to empty */
6373         for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6374                 MptCallbacks[i] = NULL;
6375                 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6376                 MptEvHandlers[i] = NULL;
6377                 MptResetHandlers[i] = NULL;
6378         }
6379
6380         DmpService = NULL;
6381
6382         /* NEW!  20010120 -sralston
6383          *  Register ourselves (mptbase) in order to facilitate
6384          *  EventNotification handling.
6385          */
6386         mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6387
6388         /* Register for hard reset handling callbacks.
6389          */
6390         if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6391                 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6392         } else {
6393                 /* FIXME! */
6394         }
6395
6396         r = pci_module_init(&mptbase_driver);
6397         if(r)
6398                 return(r);
6399
6400 #ifdef CONFIG_PROC_FS
6401         (void) procmpt_create();
6402 #endif
6403
6404         return r;
6405 }
6406
6407 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6408 /*
6409  *      fusion_exit - Perform driver unload cleanup.
6410  *
6411  *      This routine frees all resources associated with each MPT adapter
6412  *      and removes all %MPT_PROCFS_MPTBASEDIR entries.
6413  */
6414 static void __exit
6415 fusion_exit(void)
6416 {
6417
6418         dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6419
6420         /* Whups?  20010120 -sralston
6421          *  Moved this *above* removal of all MptAdapters!
6422          */
6423 #ifdef CONFIG_PROC_FS
6424         (void) procmpt_destroy();
6425 #endif
6426         pci_unregister_driver(&mptbase_driver);
6427         mpt_reset_deregister(mpt_base_index);
6428 }
6429
6430
6431 module_init(fusion_init);
6432 module_exit(fusion_exit);