patch-2_6_7-vs1_9_1_12
[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 (pdev->PCI_BASEADDR_FLAGS(ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1315                         /* Get I/O space! */
1316                         port = pdev->PCI_BASEADDR_START(ii);
1317                         psize = PCI_BASEADDR_SIZE(pdev,ii);
1318                 } else {
1319                         /* Get memmap */
1320                         mem_phys = pdev->PCI_BASEADDR_START(ii);
1321                         msize = PCI_BASEADDR_SIZE(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         mpt_sync_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, mem, (void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz));
3803
3804                 b = (unsigned long) ioc->reply_alloc;
3805                 b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
3806                 aligned_mem = (u8 *) b;
3807                 ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem;
3808                 ioc->reply_frames_dma =
3809                         (ioc->reply_alloc_dma + (aligned_mem - ioc->reply_alloc));
3810
3811                 ioc->reply_frames_low_dma = (u32) (ioc->reply_frames_dma & 0xFFFFFFFF);
3812         
3813                 /*  Request FIFO - WE manage this!  */
3814                 dprintk((KERN_INFO MYNAM ": %s.req_alloc    @ %p[%p], sz=%d bytes\n",
3815                                 ioc->name, mem, (void *)(ulong)ioc->req_alloc_dma, request_buffer_sz));
3816
3817                 b = (unsigned long) ioc->req_alloc;
3818                 b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
3819                 aligned_mem = (u8 *) b;
3820                 ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem;
3821                 ioc->req_frames_dma =
3822                         (ioc->req_alloc_dma + (aligned_mem - ioc->req_alloc));
3823
3824                 ioc->req_frames_low_dma = (u32) (ioc->req_frames_dma & 0xFFFFFFFF);
3825
3826 #if defined(CONFIG_MTRR) && 0
3827                 /*
3828                  *  Enable Write Combining MTRR for IOC's memory region.
3829                  *  (at least as much as we can; "size and base must be
3830                  *  multiples of 4 kiB"
3831                  */
3832                 ioc->mtrr_reg = mtrr_add(ioc->fifo_pool,
3833                                          ioc->fifo_pool_sz,
3834                                          MTRR_TYPE_WRCOMB, 1);
3835                 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3836                                 ioc->name, ioc->fifo_pool, ioc->fifo_pool_sz));
3837 #endif
3838
3839         } /* ioc->fifo_pool == NULL */
3840         
3841         /* Post Reply frames to FIFO
3842          */
3843         aligned_mem_dma = ioc->reply_frames_dma;
3844         dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%p]\n",
3845                         ioc->name, ioc->reply_frames, (void *)(ulong)aligned_mem_dma));
3846
3847         for (i = 0; i < ioc->reply_depth; i++) {
3848                 /*  Write each address to the IOC!  */
3849                 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma);
3850                 aligned_mem_dma += ioc->reply_sz;
3851         }
3852
3853
3854         /* Initialize Request frames linked list
3855          */
3856         aligned_mem_dma = ioc->req_frames_dma;
3857         aligned_mem = (u8 *) ioc->req_frames;
3858         dprintk((KERN_INFO MYNAM ": %s.req_frames   @ %p[%p]\n",
3859                         ioc->name, aligned_mem, (void *)(ulong)aligned_mem_dma));
3860
3861         spin_lock_irqsave(&ioc->FreeQlock, flags);
3862         Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
3863         for (i = 0; i < ioc->req_depth; i++) {
3864                 mf = (MPT_FRAME_HDR *) aligned_mem;
3865
3866                 /*  Queue REQUESTs *internally*!  */
3867                 Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
3868                 aligned_mem += ioc->req_sz;
3869         }
3870         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3871
3872
3873         if (ioc->sense_buf_pool == NULL) {
3874                 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3875                 ioc->sense_buf_pool =
3876                                 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3877                 if (ioc->sense_buf_pool == NULL)
3878                         goto out_fail;
3879
3880                 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3881                 ioc->alloc_total += sz;
3882         }
3883
3884         return 0;
3885
3886 out_fail:
3887         if (ioc->fifo_pool != NULL) {
3888                 pci_free_consistent(ioc->pcidev,
3889                                 ioc->fifo_pool_sz,
3890                                 ioc->fifo_pool, ioc->fifo_pool_dma);
3891                 ioc->reply_frames = NULL;
3892                 ioc->reply_alloc = NULL;
3893                 ioc->req_frames = NULL;
3894                 ioc->req_alloc = NULL;
3895                 ioc->chain_alloc = NULL;
3896                 ioc->fifo_pool = NULL;
3897                 ioc->alloc_total -= ioc->fifo_pool_sz;
3898 #if defined(CONFIG_MTRR) && 0
3899                 if (ioc->mtrr_reg > 0) {
3900                         mtrr_del(ioc->mtrr_reg, 0, 0);
3901                         dprintk((MYIOC_s_INFO_FMT "MTRR region de-registered\n",
3902                                         ioc->name));
3903                 }
3904 #endif
3905         }
3906         if (ioc->sense_buf_pool != NULL) {
3907                 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3908                 pci_free_consistent(ioc->pcidev,
3909                                 sz,
3910                                 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3911                 ioc->sense_buf_pool = NULL;
3912         }
3913         return -1;
3914 }
3915
3916 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3917 /**
3918  *      mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3919  *      from IOC via doorbell handshake method.
3920  *      @ioc: Pointer to MPT_ADAPTER structure
3921  *      @reqBytes: Size of the request in bytes
3922  *      @req: Pointer to MPT request frame
3923  *      @replyBytes: Expected size of the reply in bytes
3924  *      @u16reply: Pointer to area where reply should be written
3925  *      @maxwait: Max wait time for a reply (in seconds)
3926  *      @sleepFlag: Specifies whether the process can sleep
3927  *
3928  *      NOTES: It is the callers responsibility to byte-swap fields in the
3929  *      request which are greater than 1 byte in size.  It is also the
3930  *      callers responsibility to byte-swap response fields which are
3931  *      greater than 1 byte in size.
3932  *
3933  *      Returns 0 for success, non-zero for failure.
3934  */
3935 int
3936 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3937                                 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3938 {
3939         MPIDefaultReply_t *mptReply;
3940         int failcnt = 0;
3941         int t;
3942
3943         /*
3944          * Get ready to cache a handshake reply
3945          */
3946         ioc->hs_reply_idx = 0;
3947         mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3948         mptReply->MsgLength = 0;
3949
3950         /*
3951          * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3952          * then tell IOC that we want to handshake a request of N words.
3953          * (WRITE u32val to Doorbell reg).
3954          */
3955         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3956         CHIPREG_WRITE32(&ioc->chip->Doorbell,
3957                         ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3958                          ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3959
3960         /*
3961          * Wait for IOC's doorbell handshake int
3962          */
3963         if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3964                 failcnt++;
3965
3966         dhsprintk((MYIOC_s_INFO_FMT "HandShake request start, WaitCnt=%d%s\n",
3967                         ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3968
3969         /* Read doorbell and check for active bit */
3970         if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3971                         return -1;
3972
3973         /*
3974          * Clear doorbell int (WRITE 0 to IntStatus reg),
3975          * then wait for IOC to ACKnowledge that it's ready for
3976          * our handshake request.
3977          */
3978         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3979         if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3980                 failcnt++;
3981
3982         if (!failcnt) {
3983                 int      ii;
3984                 u8      *req_as_bytes = (u8 *) req;
3985
3986                 /*
3987                  * Stuff request words via doorbell handshake,
3988                  * with ACK from IOC for each.
3989                  */
3990                 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3991                         u32 word = ((req_as_bytes[(ii*4) + 0] <<  0) |
3992                                     (req_as_bytes[(ii*4) + 1] <<  8) |
3993                                     (req_as_bytes[(ii*4) + 2] << 16) |
3994                                     (req_as_bytes[(ii*4) + 3] << 24));
3995
3996                         CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3997                         if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3998                                 failcnt++;
3999                 }
4000
4001                 dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
4002                 DBG_DUMP_REQUEST_FRAME_HDR(req)
4003
4004                 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
4005                                 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
4006
4007                 /*
4008                  * Wait for completion of doorbell handshake reply from the IOC
4009                  */
4010                 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
4011                         failcnt++;
4012
4013                 /*
4014                  * Copy out the cached reply...
4015                  */
4016                 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
4017                         u16reply[ii] = ioc->hs_reply[ii];
4018         } else {
4019                 return -99;
4020         }
4021
4022         return -failcnt;
4023 }
4024
4025 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4026 /*
4027  *      WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
4028  *      in it's IntStatus register.
4029  *      @ioc: Pointer to MPT_ADAPTER structure
4030  *      @howlong: How long to wait (in seconds)
4031  *      @sleepFlag: Specifies whether the process can sleep
4032  *
4033  *      This routine waits (up to ~2 seconds max) for IOC doorbell
4034  *      handshake ACKnowledge.
4035  *
4036  *      Returns a negative value on failure, else wait loop count.
4037  */
4038 static int
4039 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4040 {
4041         int cntdn;
4042         int count = 0;
4043         u32 intstat;
4044
4045         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
4046
4047         if (sleepFlag == CAN_SLEEP) {
4048                 while (--cntdn) {
4049                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4050                         if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4051                                 break;
4052                         set_current_state(TASK_INTERRUPTIBLE);
4053                         schedule_timeout(1);
4054                         count++;
4055                 }
4056         } else {
4057                 while (--cntdn) {
4058                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4059                         if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4060                                 break;
4061                         mdelay (1);
4062                         count++;
4063                 }
4064         }
4065
4066         if (cntdn) {
4067                 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (cnt=%d)\n",
4068                                 ioc->name, count));
4069                 return count;
4070         }
4071
4072         printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout(%d)!\n",
4073                         ioc->name, (count+5)/HZ);
4074         return -1;
4075 }
4076
4077 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4078 /*
4079  *      WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
4080  *      in it's IntStatus register.
4081  *      @ioc: Pointer to MPT_ADAPTER structure
4082  *      @howlong: How long to wait (in seconds)
4083  *      @sleepFlag: Specifies whether the process can sleep
4084  *
4085  *      This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
4086  *
4087  *      Returns a negative value on failure, else wait loop count.
4088  */
4089 static int
4090 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4091 {
4092         int cntdn;
4093         int count = 0;
4094         u32 intstat;
4095
4096         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
4097         if (sleepFlag == CAN_SLEEP) {
4098                 while (--cntdn) {
4099                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4100                         if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4101                                 break;
4102                         set_current_state(TASK_INTERRUPTIBLE);
4103                         schedule_timeout(1);
4104                         count++;
4105                 }
4106         } else {
4107                 while (--cntdn) {
4108                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4109                         if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4110                                 break;
4111                         mdelay(1);
4112                         count++;
4113                 }
4114         }
4115
4116         if (cntdn) {
4117                 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d)\n",
4118                                 ioc->name, count));
4119                 return count;
4120         }
4121
4122         printk(MYIOC_s_ERR_FMT "Doorbell INT timeout(%d)!\n",
4123                         ioc->name, (count+5)/HZ);
4124         return -1;
4125 }
4126
4127 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4128 /*
4129  *      WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
4130  *      @ioc: Pointer to MPT_ADAPTER structure
4131  *      @howlong: How long to wait (in seconds)
4132  *      @sleepFlag: Specifies whether the process can sleep
4133  *
4134  *      This routine polls the IOC for a handshake reply, 16 bits at a time.
4135  *      Reply is cached to IOC private area large enough to hold a maximum
4136  *      of 128 bytes of reply data.
4137  *
4138  *      Returns a negative value on failure, else size of reply in WORDS.
4139  */
4140 static int
4141 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4142 {
4143         int u16cnt = 0;
4144         int failcnt = 0;
4145         int t;
4146         u16 *hs_reply = ioc->hs_reply;
4147         volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4148         u16 hword;
4149
4150         hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4151
4152         /*
4153          * Get first two u16's so we can look at IOC's intended reply MsgLength
4154          */
4155         u16cnt=0;
4156         if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4157                 failcnt++;
4158         } else {
4159                 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4160                 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4161                 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4162                         failcnt++;
4163                 else {
4164                         hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4165                         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4166                 }
4167         }
4168
4169         dhsprintk((MYIOC_s_INFO_FMT "First handshake reply word=%08x%s\n",
4170                         ioc->name, le32_to_cpu(*(u32 *)hs_reply),
4171                         failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4172
4173         /*
4174          * If no error (and IOC said MsgLength is > 0), piece together
4175          * reply 16 bits at a time.
4176          */
4177         for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4178                 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4179                         failcnt++;
4180                 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4181                 /* don't overflow our IOC hs_reply[] buffer! */
4182                 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4183                         hs_reply[u16cnt] = hword;
4184                 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4185         }
4186
4187         if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4188                 failcnt++;
4189         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4190
4191         if (failcnt) {
4192                 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4193                                 ioc->name);
4194                 return -failcnt;
4195         }
4196 #if 0
4197         else if (u16cnt != (2 * mptReply->MsgLength)) {
4198                 return -101;
4199         }
4200         else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4201                 return -102;
4202         }
4203 #endif
4204
4205         dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4206         DBG_DUMP_REPLY_FRAME(mptReply)
4207
4208         dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY (sz=%d)\n",
4209                         ioc->name, u16cnt/2));
4210         return u16cnt/2;
4211 }
4212
4213 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4214 /*
4215  *      GetLanConfigPages - Fetch LANConfig pages.
4216  *      @ioc: Pointer to MPT_ADAPTER structure
4217  *
4218  *      Return: 0 for success
4219  *      -ENOMEM if no memory available
4220  *              -EPERM if not allowed due to ISR context
4221  *              -EAGAIN if no msg frames currently available
4222  *              -EFAULT for non-successful reply or no reply (timeout)
4223  */
4224 static int
4225 GetLanConfigPages(MPT_ADAPTER *ioc)
4226 {
4227         ConfigPageHeader_t       hdr;
4228         CONFIGPARMS              cfg;
4229         LANPage0_t              *ppage0_alloc;
4230         dma_addr_t               page0_dma;
4231         LANPage1_t              *ppage1_alloc;
4232         dma_addr_t               page1_dma;
4233         int                      rc = 0;
4234         int                      data_sz;
4235         int                      copy_sz;
4236
4237         /* Get LAN Page 0 header */
4238         hdr.PageVersion = 0;
4239         hdr.PageLength = 0;
4240         hdr.PageNumber = 0;
4241         hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4242         cfg.hdr = &hdr;
4243         cfg.physAddr = -1;
4244         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4245         cfg.dir = 0;
4246         cfg.pageAddr = 0;
4247         cfg.timeout = 0;
4248
4249         if ((rc = mpt_config(ioc, &cfg)) != 0)
4250                 return rc;
4251
4252         if (hdr.PageLength > 0) {
4253                 data_sz = hdr.PageLength * 4;
4254                 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4255                 rc = -ENOMEM;
4256                 if (ppage0_alloc) {
4257                         memset((u8 *)ppage0_alloc, 0, data_sz);
4258                         cfg.physAddr = page0_dma;
4259                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4260
4261                         if ((rc = mpt_config(ioc, &cfg)) == 0) {
4262                                 /* save the data */
4263                                 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4264                                 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4265
4266                         }
4267
4268                         pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4269
4270                         /* FIXME!
4271                          *      Normalize endianness of structure data,
4272                          *      by byte-swapping all > 1 byte fields!
4273                          */
4274
4275                 }
4276
4277                 if (rc)
4278                         return rc;
4279         }
4280
4281         /* Get LAN Page 1 header */
4282         hdr.PageVersion = 0;
4283         hdr.PageLength = 0;
4284         hdr.PageNumber = 1;
4285         hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4286         cfg.hdr = &hdr;
4287         cfg.physAddr = -1;
4288         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4289         cfg.dir = 0;
4290         cfg.pageAddr = 0;
4291
4292         if ((rc = mpt_config(ioc, &cfg)) != 0)
4293                 return rc;
4294
4295         if (hdr.PageLength == 0)
4296                 return 0;
4297
4298         data_sz = hdr.PageLength * 4;
4299         rc = -ENOMEM;
4300         ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4301         if (ppage1_alloc) {
4302                 memset((u8 *)ppage1_alloc, 0, data_sz);
4303                 cfg.physAddr = page1_dma;
4304                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4305
4306                 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4307                         /* save the data */
4308                         copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4309                         memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4310                 }
4311
4312                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4313
4314                 /* FIXME!
4315                  *      Normalize endianness of structure data,
4316                  *      by byte-swapping all > 1 byte fields!
4317                  */
4318
4319         }
4320
4321         return rc;
4322 }
4323
4324 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4325 /*
4326  *      GetFcPortPage0 - Fetch FCPort config Page0.
4327  *      @ioc: Pointer to MPT_ADAPTER structure
4328  *      @portnum: IOC Port number
4329  *
4330  *      Return: 0 for success
4331  *      -ENOMEM if no memory available
4332  *              -EPERM if not allowed due to ISR context
4333  *              -EAGAIN if no msg frames currently available
4334  *              -EFAULT for non-successful reply or no reply (timeout)
4335  */
4336 static int
4337 GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4338 {
4339         ConfigPageHeader_t       hdr;
4340         CONFIGPARMS              cfg;
4341         FCPortPage0_t           *ppage0_alloc;
4342         FCPortPage0_t           *pp0dest;
4343         dma_addr_t               page0_dma;
4344         int                      data_sz;
4345         int                      copy_sz;
4346         int                      rc;
4347
4348         /* Get FCPort Page 0 header */
4349         hdr.PageVersion = 0;
4350         hdr.PageLength = 0;
4351         hdr.PageNumber = 0;
4352         hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
4353         cfg.hdr = &hdr;
4354         cfg.physAddr = -1;
4355         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4356         cfg.dir = 0;
4357         cfg.pageAddr = portnum;
4358         cfg.timeout = 0;
4359
4360         if ((rc = mpt_config(ioc, &cfg)) != 0)
4361                 return rc;
4362
4363         if (hdr.PageLength == 0)
4364                 return 0;
4365
4366         data_sz = hdr.PageLength * 4;
4367         rc = -ENOMEM;
4368         ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4369         if (ppage0_alloc) {
4370                 memset((u8 *)ppage0_alloc, 0, data_sz);
4371                 cfg.physAddr = page0_dma;
4372                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4373
4374                 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4375                         /* save the data */
4376                         pp0dest = &ioc->fc_port_page0[portnum];
4377                         copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
4378                         memcpy(pp0dest, ppage0_alloc, copy_sz);
4379
4380                         /*
4381                          *      Normalize endianness of structure data,
4382                          *      by byte-swapping all > 1 byte fields!
4383                          */
4384                         pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
4385                         pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
4386                         pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
4387                         pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
4388                         pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
4389                         pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
4390                         pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
4391                         pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
4392                         pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
4393                         pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
4394                         pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
4395                         pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
4396                         pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
4397                         pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
4398                         pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
4399                         pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
4400
4401                 }
4402
4403                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4404         }
4405
4406         return rc;
4407 }
4408
4409 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4410 /*
4411  *      GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4412  *      @ioc: Pointer to MPT_ADAPTER structure
4413  *
4414  *      Returns: 0 for success
4415  *      -ENOMEM if no memory available
4416  *              -EPERM if not allowed due to ISR context
4417  *              -EAGAIN if no msg frames currently available
4418  *              -EFAULT for non-successful reply or no reply (timeout)
4419  */
4420 static int
4421 GetIoUnitPage2(MPT_ADAPTER *ioc)
4422 {
4423         ConfigPageHeader_t       hdr;
4424         CONFIGPARMS              cfg;
4425         IOUnitPage2_t           *ppage_alloc;
4426         dma_addr_t               page_dma;
4427         int                      data_sz;
4428         int                      rc;
4429
4430         /* Get the page header */
4431         hdr.PageVersion = 0;
4432         hdr.PageLength = 0;
4433         hdr.PageNumber = 2;
4434         hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4435         cfg.hdr = &hdr;
4436         cfg.physAddr = -1;
4437         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4438         cfg.dir = 0;
4439         cfg.pageAddr = 0;
4440         cfg.timeout = 0;
4441
4442         if ((rc = mpt_config(ioc, &cfg)) != 0)
4443                 return rc;
4444
4445         if (hdr.PageLength == 0)
4446                 return 0;
4447
4448         /* Read the config page */
4449         data_sz = hdr.PageLength * 4;
4450         rc = -ENOMEM;
4451         ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4452         if (ppage_alloc) {
4453                 memset((u8 *)ppage_alloc, 0, data_sz);
4454                 cfg.physAddr = page_dma;
4455                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4456
4457                 /* If Good, save data */
4458                 if ((rc = mpt_config(ioc, &cfg)) == 0)
4459                         ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4460
4461                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4462         }
4463
4464         return rc;
4465 }
4466
4467 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4468 /*      mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4469  *      @ioc: Pointer to a Adapter Strucutre
4470  *      @portnum: IOC port number
4471  *
4472  *      Return: -EFAULT if read of config page header fails
4473  *                      or if no nvram
4474  *      If read of SCSI Port Page 0 fails,
4475  *              NVRAM = MPT_HOST_NVRAM_INVALID  (0xFFFFFFFF)
4476  *              Adapter settings: async, narrow
4477  *              Return 1
4478  *      If read of SCSI Port Page 2 fails,
4479  *              Adapter settings valid
4480  *              NVRAM = MPT_HOST_NVRAM_INVALID  (0xFFFFFFFF)
4481  *              Return 1
4482  *      Else
4483  *              Both valid
4484  *              Return 0
4485  *      CHECK - what type of locking mechanisms should be used????
4486  */
4487 static int
4488 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4489 {
4490         u8                      *pbuf;
4491         dma_addr_t               buf_dma;
4492         CONFIGPARMS              cfg;
4493         ConfigPageHeader_t       header;
4494         int                      ii;
4495         int                      data, rc = 0;
4496
4497         /* Allocate memory
4498          */
4499         if (!ioc->spi_data.nvram) {
4500                 int      sz;
4501                 u8      *mem;
4502                 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4503                 mem = kmalloc(sz, GFP_ATOMIC);
4504                 if (mem == NULL)
4505                         return -EFAULT;
4506
4507                 ioc->spi_data.nvram = (int *) mem;
4508
4509                 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4510                         ioc->name, ioc->spi_data.nvram, sz));
4511         }
4512
4513         /* Invalidate NVRAM information
4514          */
4515         for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4516                 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4517         }
4518
4519         /* Read SPP0 header, allocate memory, then read page.
4520          */
4521         header.PageVersion = 0;
4522         header.PageLength = 0;
4523         header.PageNumber = 0;
4524         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4525         cfg.hdr = &header;
4526         cfg.physAddr = -1;
4527         cfg.pageAddr = portnum;
4528         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4529         cfg.dir = 0;
4530         cfg.timeout = 0;        /* use default */
4531         if (mpt_config(ioc, &cfg) != 0)
4532                  return -EFAULT;
4533
4534         if (header.PageLength > 0) {
4535                 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4536                 if (pbuf) {
4537                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4538                         cfg.physAddr = buf_dma;
4539                         if (mpt_config(ioc, &cfg) != 0) {
4540                                 ioc->spi_data.maxBusWidth = MPT_NARROW;
4541                                 ioc->spi_data.maxSyncOffset = 0;
4542                                 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4543                                 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4544                                 rc = 1;
4545                         } else {
4546                                 /* Save the Port Page 0 data
4547                                  */
4548                                 SCSIPortPage0_t  *pPP0 = (SCSIPortPage0_t  *) pbuf;
4549                                 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4550                                 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4551
4552                                 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 )
4553                                         ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4554
4555                                 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4556                                 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4557                                 if (data) {
4558                                         ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4559                                         data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4560                                         ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4561                                 } else {
4562                                         ioc->spi_data.maxSyncOffset = 0;
4563                                         ioc->spi_data.minSyncFactor = MPT_ASYNC;
4564                                 }
4565
4566                                 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4567
4568                                 /* Update the minSyncFactor based on bus type.
4569                                  */
4570                                 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4571                                         (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE))  {
4572
4573                                         if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
4574                                                 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4575                                 }
4576                         }
4577                         if (pbuf) {
4578                                 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4579                         }
4580                 }
4581         }
4582
4583         /* SCSI Port Page 2 - Read the header then the page.
4584          */
4585         header.PageVersion = 0;
4586         header.PageLength = 0;
4587         header.PageNumber = 2;
4588         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4589         cfg.hdr = &header;
4590         cfg.physAddr = -1;
4591         cfg.pageAddr = portnum;
4592         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4593         cfg.dir = 0;
4594         if (mpt_config(ioc, &cfg) != 0)
4595                 return -EFAULT;
4596
4597         if (header.PageLength > 0) {
4598                 /* Allocate memory and read SCSI Port Page 2
4599                  */
4600                 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4601                 if (pbuf) {
4602                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4603                         cfg.physAddr = buf_dma;
4604                         if (mpt_config(ioc, &cfg) != 0) {
4605                                 /* Nvram data is left with INVALID mark
4606                                  */
4607                                 rc = 1;
4608                         } else {
4609                                 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t  *) pbuf;
4610                                 MpiDeviceInfo_t *pdevice = NULL;
4611
4612                                 /* Save the Port Page 2 data
4613                                  * (reformat into a 32bit quantity)
4614                                  */
4615                                 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4616                                 ioc->spi_data.PortFlags = data;
4617                                 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4618                                         pdevice = &pPP2->DeviceSettings[ii];
4619                                         data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4620                                                 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4621                                         ioc->spi_data.nvram[ii] = data;
4622                                 }
4623                         }
4624
4625                         pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4626                 }
4627         }
4628
4629         /* Update Adapter limits with those from NVRAM
4630          * Comment: Don't need to do this. Target performance
4631          * parameters will never exceed the adapters limits.
4632          */
4633
4634         return rc;
4635 }
4636
4637 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4638 /*      mpt_readScsiDevicePageHeaders - save version and length of SDP1
4639  *      @ioc: Pointer to a Adapter Strucutre
4640  *      @portnum: IOC port number
4641  *
4642  *      Return: -EFAULT if read of config page header fails
4643  *              or 0 if success.
4644  */
4645 static int
4646 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4647 {
4648         CONFIGPARMS              cfg;
4649         ConfigPageHeader_t       header;
4650
4651         /* Read the SCSI Device Page 1 header
4652          */
4653         header.PageVersion = 0;
4654         header.PageLength = 0;
4655         header.PageNumber = 1;
4656         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4657         cfg.hdr = &header;
4658         cfg.physAddr = -1;
4659         cfg.pageAddr = portnum;
4660         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4661         cfg.dir = 0;
4662         cfg.timeout = 0;
4663         if (mpt_config(ioc, &cfg) != 0)
4664                  return -EFAULT;
4665
4666         ioc->spi_data.sdp1version = cfg.hdr->PageVersion;
4667         ioc->spi_data.sdp1length = cfg.hdr->PageLength;
4668
4669         header.PageVersion = 0;
4670         header.PageLength = 0;
4671         header.PageNumber = 0;
4672         header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4673         if (mpt_config(ioc, &cfg) != 0)
4674                  return -EFAULT;
4675
4676         ioc->spi_data.sdp0version = cfg.hdr->PageVersion;
4677         ioc->spi_data.sdp0length = cfg.hdr->PageLength;
4678
4679         dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4680                         ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4681
4682         dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4683                         ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4684         return 0;
4685 }
4686
4687 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4688 /**
4689  *      mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4690  *      @ioc: Pointer to a Adapter Strucutre
4691  *      @portnum: IOC port number
4692  *
4693  *      Return:
4694  *      0 on success
4695  *      -EFAULT if read of config page header fails or data pointer not NULL
4696  *      -ENOMEM if pci_alloc failed
4697  */
4698 int
4699 mpt_findImVolumes(MPT_ADAPTER *ioc)
4700 {
4701         IOCPage2_t              *pIoc2;
4702         u8                      *mem;
4703         ConfigPageIoc2RaidVol_t *pIocRv;
4704         dma_addr_t               ioc2_dma;
4705         CONFIGPARMS              cfg;
4706         ConfigPageHeader_t       header;
4707         int                      jj;
4708         int                      rc = 0;
4709         int                      iocpage2sz;
4710         u8                       nVols, nPhys;
4711         u8                       vid, vbus, vioc;
4712
4713         /* Read IOCP2 header then the page.
4714          */
4715         header.PageVersion = 0;
4716         header.PageLength = 0;
4717         header.PageNumber = 2;
4718         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4719         cfg.hdr = &header;
4720         cfg.physAddr = -1;
4721         cfg.pageAddr = 0;
4722         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4723         cfg.dir = 0;
4724         cfg.timeout = 0;
4725         if (mpt_config(ioc, &cfg) != 0)
4726                  return -EFAULT;
4727
4728         if (header.PageLength == 0)
4729                 return -EFAULT;
4730
4731         iocpage2sz = header.PageLength * 4;
4732         pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4733         if (!pIoc2)
4734                 return -ENOMEM;
4735
4736         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4737         cfg.physAddr = ioc2_dma;
4738         if (mpt_config(ioc, &cfg) != 0)
4739                 goto done_and_free;
4740
4741         if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) {
4742                 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4743                 if (mem) {
4744                         ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem;
4745                 } else {
4746                         goto done_and_free;
4747                 }
4748         }
4749         memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4750
4751         /* Identify RAID Volume Id's */
4752         nVols = pIoc2->NumActiveVolumes;
4753         if ( nVols == 0) {
4754                 /* No RAID Volume.
4755                  */
4756                 goto done_and_free;
4757         } else {
4758                 /* At least 1 RAID Volume
4759                  */
4760                 pIocRv = pIoc2->RaidVolume;
4761                 ioc->spi_data.isRaid = 0;
4762                 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4763                         vid = pIocRv->VolumeID;
4764                         vbus = pIocRv->VolumeBus;
4765                         vioc = pIocRv->VolumeIOC;
4766
4767                         /* find the match
4768                          */
4769                         if (vbus == 0) {
4770                                 ioc->spi_data.isRaid |= (1 << vid);
4771                         } else {
4772                                 /* Error! Always bus 0
4773                                  */
4774                         }
4775                 }
4776         }
4777
4778         /* Identify Hidden Physical Disk Id's */
4779         nPhys = pIoc2->NumActivePhysDisks;
4780         if (nPhys == 0) {
4781                 /* No physical disks.
4782                  */
4783         } else {
4784                 mpt_read_ioc_pg_3(ioc);
4785         }
4786
4787 done_and_free:
4788         pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4789
4790         return rc;
4791 }
4792
4793 int
4794 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4795 {
4796         IOCPage3_t              *pIoc3;
4797         u8                      *mem;
4798         CONFIGPARMS              cfg;
4799         ConfigPageHeader_t       header;
4800         dma_addr_t               ioc3_dma;
4801         int                      iocpage3sz = 0;
4802
4803         /* Free the old page
4804          */
4805         if (ioc->spi_data.pIocPg3) {
4806                 kfree(ioc->spi_data.pIocPg3);
4807                 ioc->spi_data.pIocPg3 = NULL;
4808         }
4809
4810         /* There is at least one physical disk.
4811          * Read and save IOC Page 3
4812          */
4813         header.PageVersion = 0;
4814         header.PageLength = 0;
4815         header.PageNumber = 3;
4816         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4817         cfg.hdr = &header;
4818         cfg.physAddr = -1;
4819         cfg.pageAddr = 0;
4820         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4821         cfg.dir = 0;
4822         cfg.timeout = 0;
4823         if (mpt_config(ioc, &cfg) != 0)
4824                 return 0;
4825
4826         if (header.PageLength == 0)
4827                 return 0;
4828
4829         /* Read Header good, alloc memory
4830          */
4831         iocpage3sz = header.PageLength * 4;
4832         pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4833         if (!pIoc3)
4834                 return 0;
4835
4836         /* Read the Page and save the data
4837          * into malloc'd memory.
4838          */
4839         cfg.physAddr = ioc3_dma;
4840         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4841         if (mpt_config(ioc, &cfg) == 0) {
4842                 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4843                 if (mem) {
4844                         memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4845                         ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
4846                 }
4847         }
4848
4849         pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4850
4851         return 0;
4852 }
4853
4854 static void
4855 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4856 {
4857         IOCPage4_t              *pIoc4;
4858         CONFIGPARMS              cfg;
4859         ConfigPageHeader_t       header;
4860         dma_addr_t               ioc4_dma;
4861         int                      iocpage4sz;
4862
4863         /* Read and save IOC Page 4
4864          */
4865         header.PageVersion = 0;
4866         header.PageLength = 0;
4867         header.PageNumber = 4;
4868         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4869         cfg.hdr = &header;
4870         cfg.physAddr = -1;
4871         cfg.pageAddr = 0;
4872         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4873         cfg.dir = 0;
4874         cfg.timeout = 0;
4875         if (mpt_config(ioc, &cfg) != 0)
4876                 return;
4877
4878         if (header.PageLength == 0)
4879                 return;
4880
4881         if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4882                 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4883                 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4884                 if (!pIoc4)
4885                         return;
4886         } else {
4887                 ioc4_dma = ioc->spi_data.IocPg4_dma;
4888                 iocpage4sz = ioc->spi_data.IocPg4Sz;
4889         }
4890
4891         /* Read the Page into dma memory.
4892          */
4893         cfg.physAddr = ioc4_dma;
4894         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4895         if (mpt_config(ioc, &cfg) == 0) {
4896                 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4897                 ioc->spi_data.IocPg4_dma = ioc4_dma;
4898                 ioc->spi_data.IocPg4Sz = iocpage4sz;
4899         } else {
4900                 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4901                 ioc->spi_data.pIocPg4 = NULL;
4902         }
4903 }
4904
4905 static void
4906 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4907 {
4908         IOCPage1_t              *pIoc1;
4909         CONFIGPARMS              cfg;
4910         ConfigPageHeader_t       header;
4911         dma_addr_t               ioc1_dma;
4912         int                      iocpage1sz = 0;
4913         u32                      tmp;
4914
4915         /* Check the Coalescing Timeout in IOC Page 1
4916          */
4917         header.PageVersion = 0;
4918         header.PageLength = 0;
4919         header.PageNumber = 1;
4920         header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4921         cfg.hdr = &header;
4922         cfg.physAddr = -1;
4923         cfg.pageAddr = 0;
4924         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4925         cfg.dir = 0;
4926         cfg.timeout = 0;
4927         if (mpt_config(ioc, &cfg) != 0)
4928                 return;
4929
4930         if (header.PageLength == 0)
4931                 return;
4932
4933         /* Read Header good, alloc memory
4934          */
4935         iocpage1sz = header.PageLength * 4;
4936         pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4937         if (!pIoc1)
4938                 return;
4939
4940         /* Read the Page and check coalescing timeout
4941          */
4942         cfg.physAddr = ioc1_dma;
4943         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4944         if (mpt_config(ioc, &cfg) == 0) {
4945                 
4946                 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4947                 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4948                         tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4949
4950                         dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4951                                         ioc->name, tmp));
4952
4953                         if (tmp > MPT_COALESCING_TIMEOUT) {
4954                                 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4955
4956                                 /* Write NVRAM and current
4957                                  */
4958                                 cfg.dir = 1;
4959                                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4960                                 if (mpt_config(ioc, &cfg) == 0) {
4961                                         dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
4962                                                         ioc->name, MPT_COALESCING_TIMEOUT));
4963
4964                                         cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
4965                                         if (mpt_config(ioc, &cfg) == 0) {
4966                                                 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
4967                                                                 ioc->name, MPT_COALESCING_TIMEOUT));
4968                                         } else {
4969                                                 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
4970                                                                         ioc->name));
4971                                         }
4972
4973                                 } else {
4974                                         dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4975                                                                 ioc->name));
4976                                 }
4977                         }
4978
4979                 } else {
4980                         dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4981                 }
4982         }
4983
4984         pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
4985
4986         return;
4987 }
4988
4989 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4990 /*
4991  *      SendEventNotification - Send EventNotification (on or off) request
4992  *      to MPT adapter.
4993  *      @ioc: Pointer to MPT_ADAPTER structure
4994  *      @EvSwitch: Event switch flags
4995  */
4996 static int
4997 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
4998 {
4999         EventNotification_t     *evnp;
5000
5001         evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc->id);
5002         if (evnp == NULL) {
5003                 dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5004                                 ioc->name));
5005                 return 0;
5006         }
5007         memset(evnp, 0, sizeof(*evnp));
5008
5009         dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch));
5010
5011         evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5012         evnp->ChainOffset = 0;
5013         evnp->MsgFlags = 0;
5014         evnp->Switch = EvSwitch;
5015
5016         mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)evnp);
5017
5018         return 0;
5019 }
5020
5021 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5022 /**
5023  *      SendEventAck - Send EventAck request to MPT adapter.
5024  *      @ioc: Pointer to MPT_ADAPTER structure
5025  *      @evnp: Pointer to original EventNotification request
5026  */
5027 static int
5028 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5029 {
5030         EventAck_t      *pAck;
5031
5032         if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
5033                 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n",
5034                                 ioc->name);
5035                 return -1;
5036         }
5037         memset(pAck, 0, sizeof(*pAck));
5038
5039         dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5040
5041         pAck->Function     = MPI_FUNCTION_EVENT_ACK;
5042         pAck->ChainOffset  = 0;
5043         pAck->MsgFlags     = 0;
5044         pAck->Event        = evnp->Event;
5045         pAck->EventContext = evnp->EventContext;
5046
5047         mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)pAck);
5048
5049         return 0;
5050 }
5051
5052 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5053 /**
5054  *      mpt_config - Generic function to issue config message
5055  *      @ioc - Pointer to an adapter structure
5056  *      @cfg - Pointer to a configuration structure. Struct contains
5057  *              action, page address, direction, physical address
5058  *              and pointer to a configuration page header
5059  *              Page header is updated.
5060  *
5061  *      Returns 0 for success
5062  *      -EPERM if not allowed due to ISR context
5063  *      -EAGAIN if no msg frames currently available
5064  *      -EFAULT for non-successful reply or no reply (timeout)
5065  */
5066 int
5067 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5068 {
5069         Config_t        *pReq;
5070         MPT_FRAME_HDR   *mf;
5071         unsigned long    flags;
5072         int              ii, rc;
5073         int              flagsLength;
5074         int              in_isr;
5075
5076         /* (Bugzilla:fibrebugs, #513)
5077          * Bug fix (part 1)!  20010905 -sralston
5078          *      Prevent calling wait_event() (below), if caller happens
5079          *      to be in ISR context, because that is fatal!
5080          */
5081         in_isr = in_interrupt();
5082         if (in_isr) {
5083                 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5084                                 ioc->name));
5085                 return -EPERM;
5086         }
5087
5088         /* Get and Populate a free Frame
5089          */
5090         if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
5091                 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5092                                 ioc->name));
5093                 return -EAGAIN;
5094         }
5095         pReq = (Config_t *)mf;
5096         pReq->Action = pCfg->action;
5097         pReq->Reserved = 0;
5098         pReq->ChainOffset = 0;
5099         pReq->Function = MPI_FUNCTION_CONFIG;
5100         pReq->ExtPageLength = 0;
5101         pReq->ExtPageType = 0;
5102         pReq->MsgFlags = 0;
5103         for (ii=0; ii < 8; ii++)
5104                 pReq->Reserved2[ii] = 0;
5105
5106         pReq->Header.PageVersion = pCfg->hdr->PageVersion;
5107         pReq->Header.PageLength = pCfg->hdr->PageLength;
5108         pReq->Header.PageNumber = pCfg->hdr->PageNumber;
5109         pReq->Header.PageType = (pCfg->hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5110         pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5111
5112         /* Add a SGE to the config request.
5113          */
5114         if (pCfg->dir)
5115                 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5116         else
5117                 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5118
5119         flagsLength |= pCfg->hdr->PageLength * 4;
5120
5121         mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5122
5123         dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5124                 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5125
5126         /* Append pCfg pointer to end of mf
5127          */
5128         *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) =  (void *) pCfg;
5129
5130         /* Initalize the timer
5131          */
5132         init_timer(&pCfg->timer);
5133         pCfg->timer.data = (unsigned long) ioc;
5134         pCfg->timer.function = mpt_timer_expired;
5135         pCfg->wait_done = 0;
5136
5137         /* Set the timer; ensure 10 second minimum */
5138         if (pCfg->timeout < 10)
5139                 pCfg->timer.expires = jiffies + HZ*10;
5140         else
5141                 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5142
5143         /* Add to end of Q, set timer and then issue this command */
5144         spin_lock_irqsave(&ioc->FreeQlock, flags);
5145         Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
5146         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5147
5148         add_timer(&pCfg->timer);
5149         mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
5150         wait_event(mpt_waitq, pCfg->wait_done);
5151
5152         /* mf has been freed - do not access */
5153
5154         rc = pCfg->status;
5155
5156         return rc;
5157 }
5158
5159 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5160 /**
5161  *      mpt_toolbox - Generic function to issue toolbox message
5162  *      @ioc - Pointer to an adapter structure
5163  *      @cfg - Pointer to a toolbox structure. Struct contains
5164  *              action, page address, direction, physical address
5165  *              and pointer to a configuration page header
5166  *              Page header is updated.
5167  *
5168  *      Returns 0 for success
5169  *      -EPERM if not allowed due to ISR context
5170  *      -EAGAIN if no msg frames currently available
5171  *      -EFAULT for non-successful reply or no reply (timeout)
5172  */
5173 int
5174 mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5175 {
5176         ToolboxIstwiReadWriteRequest_t  *pReq;
5177         MPT_FRAME_HDR   *mf;
5178         unsigned long    flags;
5179         int              rc;
5180         int              flagsLength;
5181         int              in_isr;
5182
5183         /* (Bugzilla:fibrebugs, #513)
5184          * Bug fix (part 1)!  20010905 -sralston
5185          *      Prevent calling wait_event() (below), if caller happens
5186          *      to be in ISR context, because that is fatal!
5187          */
5188         in_isr = in_interrupt();
5189         if (in_isr) {
5190                 dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
5191                                 ioc->name));
5192                 return -EPERM;
5193         }
5194
5195         /* Get and Populate a free Frame
5196          */
5197         if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
5198                 dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
5199                                 ioc->name));
5200                 return -EAGAIN;
5201         }
5202         pReq = (ToolboxIstwiReadWriteRequest_t  *)mf;
5203         pReq->Tool = pCfg->action;
5204         pReq->Reserved = 0;
5205         pReq->ChainOffset = 0;
5206         pReq->Function = MPI_FUNCTION_TOOLBOX;
5207         pReq->Reserved1 = 0;
5208         pReq->Reserved2 = 0;
5209         pReq->MsgFlags = 0;
5210         pReq->Flags = pCfg->dir;
5211         pReq->BusNum = 0;
5212         pReq->Reserved3 = 0;
5213         pReq->NumAddressBytes = 0x01;
5214         pReq->Reserved4 = 0;
5215         pReq->DataLength = 0x04;
5216         pReq->DeviceAddr = 0xB0;
5217         pReq->Addr1 = 0;
5218         pReq->Addr2 = 0;
5219         pReq->Addr3 = 0;
5220         pReq->Reserved5 = 0;
5221
5222         /* Add a SGE to the config request.
5223          */
5224
5225         flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
5226
5227         mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
5228
5229         dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
5230                 ioc->name, pReq->Tool));
5231
5232         /* Append pCfg pointer to end of mf
5233          */
5234         *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) =  (void *) pCfg;
5235
5236         /* Initalize the timer
5237          */
5238         init_timer(&pCfg->timer);
5239         pCfg->timer.data = (unsigned long) ioc;
5240         pCfg->timer.function = mpt_timer_expired;
5241         pCfg->wait_done = 0;
5242
5243         /* Set the timer; ensure 10 second minimum */
5244         if (pCfg->timeout < 10)
5245                 pCfg->timer.expires = jiffies + HZ*10;
5246         else
5247                 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5248
5249         /* Add to end of Q, set timer and then issue this command */
5250         spin_lock_irqsave(&ioc->FreeQlock, flags);
5251         Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
5252         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5253
5254         add_timer(&pCfg->timer);
5255         mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
5256         wait_event(mpt_waitq, pCfg->wait_done);
5257
5258         /* mf has been freed - do not access */
5259
5260         rc = pCfg->status;
5261
5262         return rc;
5263 }
5264
5265 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5266 /*
5267  *      mpt_timer_expired - Call back for timer process.
5268  *      Used only internal config functionality.
5269  *      @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5270  */
5271 static void
5272 mpt_timer_expired(unsigned long data)
5273 {
5274         MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5275
5276         dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5277
5278         /* Perform a FW reload */
5279         if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5280                 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5281
5282         /* No more processing.
5283          * Hard reset clean-up will wake up
5284          * process and free all resources.
5285          */
5286         dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5287
5288         return;
5289 }
5290
5291 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5292 /*
5293  *      mpt_ioc_reset - Base cleanup for hard reset
5294  *      @ioc: Pointer to the adapter structure
5295  *      @reset_phase: Indicates pre- or post-reset functionality
5296  *
5297  *      Remark: Free's resources with internally generated commands.
5298  */
5299 static int
5300 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5301 {
5302         CONFIGPARMS *pCfg;
5303         unsigned long flags;
5304
5305         dprintk((KERN_WARNING MYNAM
5306                         ": IOC %s_reset routed to MPT base driver!\n",
5307                         reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5308                         reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5309
5310         if (reset_phase == MPT_IOC_SETUP_RESET) {
5311                 ;
5312         } else if (reset_phase == MPT_IOC_PRE_RESET) {
5313                 /* If the internal config Q is not empty -
5314                  * delete timer. MF resources will be freed when
5315                  * the FIFO's are primed.
5316                  */
5317                 spin_lock_irqsave(&ioc->FreeQlock, flags);
5318                 if (! Q_IS_EMPTY(&ioc->configQ)){
5319                         pCfg = (CONFIGPARMS *)ioc->configQ.head;
5320                         do {
5321                                 del_timer(&pCfg->timer);
5322                                 pCfg = (CONFIGPARMS *) (pCfg->linkage.forw);
5323                         } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
5324                 }
5325                 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5326
5327         } else {
5328                 CONFIGPARMS *pNext;
5329
5330                 /* Search the configQ for internal commands.
5331                  * Flush the Q, and wake up all suspended threads.
5332                  */
5333                 spin_lock_irqsave(&ioc->FreeQlock, flags);
5334                 if (! Q_IS_EMPTY(&ioc->configQ)){
5335                         pCfg = (CONFIGPARMS *)ioc->configQ.head;
5336                         do {
5337                                 pNext = (CONFIGPARMS *) pCfg->linkage.forw;
5338
5339                                 Q_DEL_ITEM(&pCfg->linkage);
5340
5341                                 pCfg->status = MPT_CONFIG_ERROR;
5342                                 pCfg->wait_done = 1;
5343                                 wake_up(&mpt_waitq);
5344
5345                                 pCfg = pNext;
5346                         } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
5347                 }
5348                 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5349         }
5350
5351         return 1;               /* currently means nothing really */
5352 }
5353
5354
5355 #ifdef CONFIG_PROC_FS           /* { */
5356 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5357 /*
5358  *      procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5359  */
5360 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5361 /*
5362  *      procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5363  *
5364  *      Returns 0 for success, non-zero for failure.
5365  */
5366 static int
5367 procmpt_create(void)
5368 {
5369         MPT_ADAPTER             *ioc;
5370         struct proc_dir_entry   *ent;
5371         int      ii;
5372
5373         /*
5374          *      BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
5375          *      (single level) to multi level (e.g. "driver/message/fusion")
5376          *      something here needs to change.  -sralston
5377          */
5378         mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5379         if (mpt_proc_root_dir == NULL)
5380                 return -ENOTDIR;
5381
5382         for (ii=0; ii < MPT_PROC_ENTRIES; ii++) {
5383                 ent = create_proc_entry(mpt_proc_list[ii].name,
5384                                 S_IFREG|S_IRUGO, mpt_proc_root_dir);
5385                 if (!ent) {
5386                         printk(KERN_WARNING MYNAM
5387                                         ": WARNING - Could not create /proc/mpt/%s entry\n",
5388                                         mpt_proc_list[ii].name);
5389                         continue;
5390                 }
5391                 ent->read_proc = mpt_proc_list[ii].f;
5392                 ent->data      = NULL;
5393         }
5394
5395         ioc = mpt_adapter_find_first();
5396         while (ioc != NULL) {
5397                 struct proc_dir_entry   *dent;
5398                 /*
5399                  *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
5400                  */
5401                 if ((dent = proc_mkdir(ioc->name, mpt_proc_root_dir)) != NULL) {
5402                         /*
5403                          *  And populate it with mpt_ioc_proc_list[] entries.
5404                          */
5405                         for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) {
5406                                 ent = create_proc_entry(mpt_ioc_proc_list[ii].name,
5407                                                 S_IFREG|S_IRUGO, dent);
5408                                 if (!ent) {
5409                                         printk(KERN_WARNING MYNAM
5410                                                         ": WARNING - Could not create /proc/mpt/%s/%s entry!\n",
5411                                                         ioc->name,
5412                                                         mpt_ioc_proc_list[ii].name);
5413                                         continue;
5414                                 }
5415                                 ent->read_proc = mpt_ioc_proc_list[ii].f;
5416                                 ent->data      = ioc;
5417                         }
5418                 } else {
5419                         printk(MYIOC_s_WARN_FMT "Could not create /proc/mpt/%s subdir entry!\n",
5420                                         ioc->name, mpt_ioc_proc_list[ii].name);
5421                 }
5422                 ioc = mpt_adapter_find_next(ioc);
5423         }
5424
5425         return 0;
5426 }
5427
5428 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5429 /*
5430  *      procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5431  *
5432  *      Returns 0 for success, non-zero for failure.
5433  */
5434 static int
5435 procmpt_destroy(void)
5436 {
5437         MPT_ADAPTER     *ioc;
5438         int              ii;
5439
5440         if (!mpt_proc_root_dir)
5441                 return 0;
5442
5443         /*
5444          *      BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
5445          *      (single level) to multi level (e.g. "driver/message/fusion")
5446          *      something here needs to change.  -sralston
5447          */
5448
5449         ioc = mpt_adapter_find_first();
5450         while (ioc != NULL) {
5451                 char pname[32];
5452                 int namelen;
5453
5454                 namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
5455
5456                 /*
5457                  *  Tear down each "/proc/mpt/iocN" subdirectory.
5458                  */
5459                 for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) {
5460                         (void) sprintf(pname+namelen, "/%s", mpt_ioc_proc_list[ii].name);
5461                         remove_proc_entry(pname, NULL);
5462                 }
5463                 remove_proc_entry(ioc->name, mpt_proc_root_dir);
5464                 ioc = mpt_adapter_find_next(ioc);
5465         }
5466
5467         for (ii=0; ii < MPT_PROC_ENTRIES; ii++)
5468                 remove_proc_entry(mpt_proc_list[ii].name, mpt_proc_root_dir);
5469
5470         if (atomic_read((atomic_t *)&mpt_proc_root_dir->count) == 0) {
5471                 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5472                 mpt_proc_root_dir = NULL;
5473                 return 0;
5474         }
5475
5476         return -1;
5477 }
5478
5479 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5480 /*
5481  *      procmpt_summary_read - Handle read request from /proc/mpt/summary
5482  *      or from /proc/mpt/iocN/summary.
5483  *      @buf: Pointer to area to write information
5484  *      @start: Pointer to start pointer
5485  *      @offset: Offset to start writing
5486  *      @request:
5487  *      @eof: Pointer to EOF integer
5488  *      @data: Pointer
5489  *
5490  *      Returns number of characters written to process performing the read.
5491  */
5492 static int
5493 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5494 {
5495         MPT_ADAPTER *ioc;
5496         char *out = buf;
5497         int len;
5498
5499         if (data == NULL)
5500                 ioc = mpt_adapter_find_first();
5501         else
5502                 ioc = data;
5503
5504         while (ioc) {
5505                 int     more = 0;
5506
5507                 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5508
5509                 out += more;
5510                 if ((out-buf) >= request) {
5511                         break;
5512                 }
5513
5514                 if (data == NULL)
5515                         ioc = mpt_adapter_find_next(ioc);
5516                 else
5517                         ioc = NULL;             /* force exit for iocN */
5518         }
5519         len = out - buf;
5520
5521         MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5522 }
5523
5524 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5525 /*
5526  *      procmpt_version_read - Handle read request from /proc/mpt/version.
5527  *      @buf: Pointer to area to write information
5528  *      @start: Pointer to start pointer
5529  *      @offset: Offset to start writing
5530  *      @request:
5531  *      @eof: Pointer to EOF integer
5532  *      @data: Pointer
5533  *
5534  *      Returns number of characters written to process performing the read.
5535  */
5536 static int
5537 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5538 {
5539         int      ii;
5540         int      scsi, lan, ctl, targ, dmp;
5541         char    *drvname;
5542         int      len;
5543
5544         len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5545         len += sprintf(buf+len, "  Fusion MPT base driver\n");
5546
5547         scsi = lan = ctl = targ = dmp = 0;
5548         for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5549                 drvname = NULL;
5550                 if (MptCallbacks[ii]) {
5551                         switch (MptDriverClass[ii]) {
5552                         case MPTSCSIH_DRIVER:
5553                                 if (!scsi++) drvname = "SCSI host";
5554                                 break;
5555                         case MPTLAN_DRIVER:
5556                                 if (!lan++) drvname = "LAN";
5557                                 break;
5558                         case MPTSTM_DRIVER:
5559                                 if (!targ++) drvname = "SCSI target";
5560                                 break;
5561                         case MPTCTL_DRIVER:
5562                                 if (!ctl++) drvname = "ioctl";
5563                                 break;
5564                         case MPTDMP_DRIVER:
5565                                 if (!dmp++) drvname = "DMP";
5566                                 break;
5567                         }
5568
5569                         if (drvname)
5570                                 len += sprintf(buf+len, "  Fusion MPT %s driver\n", drvname);
5571                         /*
5572                          *      Handle isense special case, because it
5573                          *      doesn't do a formal mpt_register call.
5574                          */
5575                         if (isense_idx == ii)
5576                                 len += sprintf(buf+len, "  Fusion MPT isense driver\n");
5577                 }
5578         }
5579
5580         MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5581 }
5582
5583 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5584 /*
5585  *      procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5586  *      @buf: Pointer to area to write information
5587  *      @start: Pointer to start pointer
5588  *      @offset: Offset to start writing
5589  *      @request:
5590  *      @eof: Pointer to EOF integer
5591  *      @data: Pointer
5592  *
5593  *      Returns number of characters written to process performing the read.
5594  */
5595 static int
5596 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5597 {
5598         MPT_ADAPTER     *ioc = data;
5599         int              len;
5600         char             expVer[32];
5601         int              sz;
5602         int              p;
5603
5604         mpt_get_fw_exp_ver(expVer, ioc);
5605
5606         len = sprintf(buf, "%s:", ioc->name);
5607         if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5608                 len += sprintf(buf+len, "  (f/w download boot flag set)");
5609 //      if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5610 //              len += sprintf(buf+len, "  CONFIG_CHECKSUM_FAIL!");
5611
5612         len += sprintf(buf+len, "\n  ProductID = 0x%04x (%s)\n",
5613                         ioc->facts.ProductID,
5614                         ioc->prod_name);
5615         len += sprintf(buf+len, "  FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5616         if (ioc->facts.FWImageSize)
5617                 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5618         len += sprintf(buf+len, "\n  MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5619         len += sprintf(buf+len, "  FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5620         len += sprintf(buf+len, "  EventState = 0x%02x\n", ioc->facts.EventState);
5621
5622         len += sprintf(buf+len, "  CurrentHostMfaHighAddr = 0x%08x\n",
5623                         ioc->facts.CurrentHostMfaHighAddr);
5624         len += sprintf(buf+len, "  CurrentSenseBufferHighAddr = 0x%08x\n",
5625                         ioc->facts.CurrentSenseBufferHighAddr);
5626
5627         len += sprintf(buf+len, "  MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5628         len += sprintf(buf+len, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5629
5630         len += sprintf(buf+len, "  RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5631                                         (void *)ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma);
5632         /*
5633          *  Rounding UP to nearest 4-kB boundary here...
5634          */
5635         sz = (ioc->req_sz * ioc->req_depth) + 128;
5636         sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5637         len += sprintf(buf+len, "    {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5638                                         ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5639         len += sprintf(buf+len, "    {MaxReqSz=%d}   {MaxReqDepth=%d}\n",
5640                                         4*ioc->facts.RequestFrameSize,
5641                                         ioc->facts.GlobalCredits);
5642
5643         len += sprintf(buf+len, "  ReplyFrames   @ 0x%p (Dma @ 0x%p)\n",
5644                                         (void *)ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma);
5645         sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5646         len += sprintf(buf+len, "    {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5647                                         ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5648         len += sprintf(buf+len, "    {MaxRepSz=%d}   {MaxRepDepth=%d}\n",
5649                                         ioc->facts.CurReplyFrameSize,
5650                                         ioc->facts.ReplyQueueDepth);
5651
5652         len += sprintf(buf+len, "  MaxDevices = %d\n",
5653                         (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5654         len += sprintf(buf+len, "  MaxBuses = %d\n", ioc->facts.MaxBuses);
5655
5656         /* per-port info */
5657         for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5658                 len += sprintf(buf+len, "  PortNumber = %d (of %d)\n",
5659                                 p+1,
5660                                 ioc->facts.NumberOfPorts);
5661                 if ((int)ioc->chip_type <= (int)FC929) {
5662                         if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5663                                 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5664                                 len += sprintf(buf+len, "    LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5665                                                 a[5], a[4], a[3], a[2], a[1], a[0]);
5666                         }
5667                         len += sprintf(buf+len, "    WWN = %08X%08X:%08X%08X\n",
5668                                         ioc->fc_port_page0[p].WWNN.High,
5669                                         ioc->fc_port_page0[p].WWNN.Low,
5670                                         ioc->fc_port_page0[p].WWPN.High,
5671                                         ioc->fc_port_page0[p].WWPN.Low);
5672                 }
5673         }
5674
5675         MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5676 }
5677
5678 #endif          /* CONFIG_PROC_FS } */
5679
5680 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5681 static void
5682 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5683 {
5684         buf[0] ='\0';
5685         if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5686                 sprintf(buf, " (Exp %02d%02d)",
5687                         (ioc->facts.FWVersion.Word >> 16) & 0x00FF,     /* Month */
5688                         (ioc->facts.FWVersion.Word >> 8) & 0x1F);       /* Day */
5689
5690                 /* insider hack! */
5691                 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5692                         strcat(buf, " [MDBG]");
5693         }
5694 }
5695
5696 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5697 /**
5698  *      mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5699  *      @ioc: Pointer to MPT_ADAPTER structure
5700  *      @buffer: Pointer to buffer where IOC summary info should be written
5701  *      @size: Pointer to number of bytes we wrote (set by this routine)
5702  *      @len: Offset at which to start writing in buffer
5703  *      @showlan: Display LAN stuff?
5704  *
5705  *      This routine writes (english readable) ASCII text, which represents
5706  *      a summary of IOC information, to a buffer.
5707  */
5708 void
5709 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5710 {
5711         char expVer[32];
5712         int y;
5713
5714         mpt_get_fw_exp_ver(expVer, ioc);
5715
5716         /*
5717          *  Shorter summary of attached ioc's...
5718          */
5719         y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5720                         ioc->name,
5721                         ioc->prod_name,
5722                         MPT_FW_REV_MAGIC_ID_STRING,     /* "FwRev=" or somesuch */
5723                         ioc->facts.FWVersion.Word,
5724                         expVer,
5725                         ioc->facts.NumberOfPorts,
5726                         ioc->req_depth);
5727
5728         if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5729                 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5730                 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5731                         a[5], a[4], a[3], a[2], a[1], a[0]);
5732         }
5733
5734 #ifndef __sparc__
5735         y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5736 #else
5737         y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5738 #endif
5739
5740         if (!ioc->active)
5741                 y += sprintf(buffer+len+y, " (disabled)");
5742
5743         y += sprintf(buffer+len+y, "\n");
5744
5745         *size = y;
5746 }
5747
5748 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5749 /*
5750  *      Reset Handling
5751  */
5752 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5753 /**
5754  *      mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5755  *      Management call based on input arg values.  If TaskMgmt fails,
5756  *      return associated SCSI request.
5757  *      @ioc: Pointer to MPT_ADAPTER structure
5758  *      @sleepFlag: Indicates if sleep or schedule must be called.
5759  *
5760  *      Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5761  *      or a non-interrupt thread.  In the former, must not call schedule().
5762  *
5763  *      Remark: A return of -1 is a FATAL error case, as it means a
5764  *      FW reload/initialization failed.
5765  *
5766  *      Returns 0 for SUCCESS or -1 if FAILED.
5767  */
5768 int
5769 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5770 {
5771         int              rc;
5772         unsigned long    flags;
5773
5774         dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5775 #ifdef MFCNT
5776         printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5777         printk("MF count 0x%x !\n", ioc->mfcnt);
5778 #endif
5779
5780         /* Reset the adapter. Prevent more than 1 call to
5781          * mpt_do_ioc_recovery at any instant in time.
5782          */
5783         spin_lock_irqsave(&ioc->diagLock, flags);
5784         if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5785                 spin_unlock_irqrestore(&ioc->diagLock, flags);
5786                 return 0;
5787         } else {
5788                 ioc->diagPending = 1;
5789         }
5790         spin_unlock_irqrestore(&ioc->diagLock, flags);
5791
5792         /* FIXME: If do_ioc_recovery fails, repeat....
5793          */
5794
5795         /* The SCSI driver needs to adjust timeouts on all current
5796          * commands prior to the diagnostic reset being issued.
5797          * Prevents timeouts occuring during a diagnostic reset...very bad.
5798          * For all other protocol drivers, this is a no-op.
5799          */
5800         {
5801                 int      ii;
5802                 int      r = 0;
5803
5804                 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5805                         if (MptResetHandlers[ii]) {
5806                                 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5807                                                 ioc->name, ii));
5808                                 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
5809                                 if (ioc->alt_ioc) {
5810                                         dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5811                                                         ioc->name, ioc->alt_ioc->name, ii));
5812                                         r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5813                                 }
5814                         }
5815                 }
5816         }
5817
5818         if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5819                 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5820                         rc, ioc->name);
5821         }
5822         ioc->reload_fw = 0;
5823         if (ioc->alt_ioc)
5824                 ioc->alt_ioc->reload_fw = 0;
5825
5826         spin_lock_irqsave(&ioc->diagLock, flags);
5827         ioc->diagPending = 0;
5828         if (ioc->alt_ioc)
5829                 ioc->alt_ioc->diagPending = 0;
5830         spin_unlock_irqrestore(&ioc->diagLock, flags);
5831
5832         dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5833
5834         return rc;
5835 }
5836
5837 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5838 static char *
5839 EventDescriptionStr(u8 event, u32 evData0)
5840 {
5841         char *ds;
5842
5843         switch(event) {
5844         case MPI_EVENT_NONE:
5845                 ds = "None";
5846                 break;
5847         case MPI_EVENT_LOG_DATA:
5848                 ds = "Log Data";
5849                 break;
5850         case MPI_EVENT_STATE_CHANGE:
5851                 ds = "State Change";
5852                 break;
5853         case MPI_EVENT_UNIT_ATTENTION:
5854                 ds = "Unit Attention";
5855                 break;
5856         case MPI_EVENT_IOC_BUS_RESET:
5857                 ds = "IOC Bus Reset";
5858                 break;
5859         case MPI_EVENT_EXT_BUS_RESET:
5860                 ds = "External Bus Reset";
5861                 break;
5862         case MPI_EVENT_RESCAN:
5863                 ds = "Bus Rescan Event";
5864                 /* Ok, do we need to do anything here? As far as
5865                    I can tell, this is when a new device gets added
5866                    to the loop. */
5867                 break;
5868         case MPI_EVENT_LINK_STATUS_CHANGE:
5869                 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5870                         ds = "Link Status(FAILURE) Change";
5871                 else
5872                         ds = "Link Status(ACTIVE) Change";
5873                 break;
5874         case MPI_EVENT_LOOP_STATE_CHANGE:
5875                 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5876                         ds = "Loop State(LIP) Change";
5877                 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5878                         ds = "Loop State(LPE) Change";                  /* ??? */
5879                 else
5880                         ds = "Loop State(LPB) Change";                  /* ??? */
5881                 break;
5882         case MPI_EVENT_LOGOUT:
5883                 ds = "Logout";
5884                 break;
5885         case MPI_EVENT_EVENT_CHANGE:
5886                 if (evData0)
5887                         ds = "Events(ON) Change";
5888                 else
5889                         ds = "Events(OFF) Change";
5890                 break;
5891         case MPI_EVENT_INTEGRATED_RAID:
5892                 ds = "Integrated Raid";
5893                 break;
5894         /*
5895          *  MPT base "custom" events may be added here...
5896          */
5897         default:
5898                 ds = "Unknown";
5899                 break;
5900         }
5901         return ds;
5902 }
5903
5904 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5905 /*
5906  *      ProcessEventNotification - Route a received EventNotificationReply to
5907  *      all currently regeistered event handlers.
5908  *      @ioc: Pointer to MPT_ADAPTER structure
5909  *      @pEventReply: Pointer to EventNotification reply frame
5910  *      @evHandlers: Pointer to integer, number of event handlers
5911  *
5912  *      Returns sum of event handlers return values.
5913  */
5914 static int
5915 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
5916 {
5917         u16 evDataLen;
5918         u32 evData0 = 0;
5919 //      u32 evCtx;
5920         int ii;
5921         int r = 0;
5922         int handlers = 0;
5923         char *evStr;
5924         u8 event;
5925
5926         /*
5927          *  Do platform normalization of values
5928          */
5929         event = le32_to_cpu(pEventReply->Event) & 0xFF;
5930 //      evCtx = le32_to_cpu(pEventReply->EventContext);
5931         evDataLen = le16_to_cpu(pEventReply->EventDataLength);
5932         if (evDataLen) {
5933                 evData0 = le32_to_cpu(pEventReply->Data[0]);
5934         }
5935
5936         evStr = EventDescriptionStr(event, evData0);
5937         dprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
5938                         ioc->name,
5939                         evStr,
5940                         event));
5941
5942 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
5943         printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
5944         for (ii = 0; ii < evDataLen; ii++)
5945                 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
5946         printk("\n");
5947 #endif
5948
5949         /*
5950          *  Do general / base driver event processing
5951          */
5952         switch(event) {
5953         case MPI_EVENT_NONE:                    /* 00 */
5954         case MPI_EVENT_LOG_DATA:                /* 01 */
5955         case MPI_EVENT_STATE_CHANGE:            /* 02 */
5956         case MPI_EVENT_UNIT_ATTENTION:          /* 03 */
5957         case MPI_EVENT_IOC_BUS_RESET:           /* 04 */
5958         case MPI_EVENT_EXT_BUS_RESET:           /* 05 */
5959         case MPI_EVENT_RESCAN:                  /* 06 */
5960         case MPI_EVENT_LINK_STATUS_CHANGE:      /* 07 */
5961         case MPI_EVENT_LOOP_STATE_CHANGE:       /* 08 */
5962         case MPI_EVENT_LOGOUT:                  /* 09 */
5963         case MPI_EVENT_INTEGRATED_RAID:         /* 0B */
5964         case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:       /* 0C */
5965         default:
5966                 break;
5967         case MPI_EVENT_EVENT_CHANGE:            /* 0A */
5968                 if (evDataLen) {
5969                         u8 evState = evData0 & 0xFF;
5970
5971                         /* CHECKME! What if evState unexpectedly says OFF (0)? */
5972
5973                         /* Update EventState field in cached IocFacts */
5974                         if (ioc->facts.Function) {
5975                                 ioc->facts.EventState = evState;
5976                         }
5977                 }
5978                 break;
5979         }
5980
5981         /*
5982          * Should this event be logged? Events are written sequentially.
5983          * When buffer is full, start again at the top.
5984          */
5985         if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
5986                 int idx;
5987
5988                 idx = ioc->eventContext % ioc->eventLogSize;
5989
5990                 ioc->events[idx].event = event;
5991                 ioc->events[idx].eventContext = ioc->eventContext;
5992
5993                 for (ii = 0; ii < 2; ii++) {
5994                         if (ii < evDataLen)
5995                                 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
5996                         else
5997                                 ioc->events[idx].data[ii] =  0;
5998                 }
5999
6000                 ioc->eventContext++;
6001         }
6002
6003
6004         /*
6005          *  Call each currently registered protocol event handler.
6006          */
6007         for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6008                 if (MptEvHandlers[ii]) {
6009                         dprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6010                                         ioc->name, ii));
6011                         r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6012                         handlers++;
6013                 }
6014         }
6015         /* FIXME?  Examine results here? */
6016
6017         /*
6018          *  If needed, send (a single) EventAck.
6019          */
6020         if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6021                 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6022                         printk(MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6023                                         ioc->name, ii);
6024                 }
6025         }
6026
6027         *evHandlers = handlers;
6028         return r;
6029 }
6030
6031 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6032 /*
6033  *      mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6034  *      @ioc: Pointer to MPT_ADAPTER structure
6035  *      @log_info: U32 LogInfo reply word from the IOC
6036  *
6037  *      Refer to lsi/fc_log.h.
6038  */
6039 static void
6040 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6041 {
6042         static char *subcl_str[8] = {
6043                 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6044                 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6045         };
6046         u8 subcl = (log_info >> 24) & 0x7;
6047 //      u32 SubCl = log_info & 0x27000000;
6048
6049         printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}",
6050                         ioc->name, log_info, subcl_str[subcl]);
6051 }
6052
6053 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6054 /*
6055  *      mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
6056  *      @ioc: Pointer to MPT_ADAPTER structure
6057  *      @mr: Pointer to MPT reply frame
6058  *      @log_info: U32 LogInfo word from the IOC
6059  *
6060  *      Refer to lsi/sp_log.h.
6061  */
6062 static void
6063 mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
6064 {
6065         u32 info = log_info & 0x00FF0000;
6066         char *desc = "unknown";
6067
6068         switch (info) {
6069         case 0x00010000:
6070                 desc = "bug! MID not found";
6071                 if (ioc->reload_fw == 0)
6072                         ioc->reload_fw++;
6073                 break;
6074
6075         case 0x00020000:
6076                 desc = "Parity Error";
6077                 break;
6078
6079         case 0x00030000:
6080                 desc = "ASYNC Outbound Overrun";
6081                 break;
6082
6083         case 0x00040000:
6084                 desc = "SYNC Offset Error";
6085                 break;
6086
6087         case 0x00050000:
6088                 desc = "BM Change";
6089                 break;
6090
6091         case 0x00060000:
6092                 desc = "Msg In Overflow";
6093                 break;
6094
6095         case 0x00070000:
6096                 desc = "DMA Error";
6097                 break;
6098
6099         case 0x00080000:
6100                 desc = "Outbound DMA Overrun";
6101                 break;
6102         
6103         case 0x00090000:
6104                 desc = "Task Management";
6105                 break;
6106
6107         case 0x000A0000:
6108                 desc = "Device Problem";
6109                 break;
6110
6111         case 0x000B0000:
6112                 desc = "Invalid Phase Change";
6113                 break;
6114
6115         case 0x000C0000:
6116                 desc = "Untagged Table Size";
6117                 break;
6118         
6119         }
6120
6121         printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6122 }
6123
6124 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6125 /*
6126  *      mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6127  *      @ioc: Pointer to MPT_ADAPTER structure
6128  *      @ioc_status: U32 IOCStatus word from IOC
6129  *      @mf: Pointer to MPT request frame
6130  *
6131  *      Refer to lsi/mpi.h.
6132  */
6133 static void
6134 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6135 {
6136         u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6137         char *desc = "";
6138
6139         switch (status) {
6140         case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6141                 desc = "Invalid Function";
6142                 break;
6143
6144         case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6145                 desc = "Busy";
6146                 break;
6147
6148         case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6149                 desc = "Invalid SGL";
6150                 break;
6151
6152         case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6153                 desc = "Internal Error";
6154                 break;
6155
6156         case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6157                 desc = "Reserved";
6158                 break;
6159
6160         case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6161                 desc = "Insufficient Resources";
6162                 break;
6163
6164         case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6165                 desc = "Invalid Field";
6166                 break;
6167
6168         case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6169                 desc = "Invalid State";
6170                 break;
6171
6172         case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6173         case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
6174         case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
6175         case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
6176         case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
6177         case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
6178                 /* No message for Config IOCStatus values */
6179                 break;
6180
6181         case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6182                 /* No message for recovered error
6183                 desc = "SCSI Recovered Error";
6184                 */
6185                 break;
6186
6187         case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6188                 desc = "SCSI Invalid Bus";
6189                 break;
6190
6191         case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6192                 desc = "SCSI Invalid TargetID";
6193                 break;
6194
6195         case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6196           {
6197                 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6198                 U8 cdb = pScsiReq->CDB[0];
6199                 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6200                         desc = "SCSI Device Not There";
6201                 }
6202                 break;
6203           }
6204
6205         case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6206                 desc = "SCSI Data Overrun";
6207                 break;
6208
6209         case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6210                 /* This error is checked in scsi_io_done(). Skip. 
6211                 desc = "SCSI Data Underrun";
6212                 */
6213                 break;
6214
6215         case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6216                 desc = "SCSI I/O Data Error";
6217                 break;
6218
6219         case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6220                 desc = "SCSI Protocol Error";
6221                 break;
6222
6223         case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6224                 desc = "SCSI Task Terminated";
6225                 break;
6226
6227         case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6228                 desc = "SCSI Residual Mismatch";
6229                 break;
6230
6231         case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6232                 desc = "SCSI Task Management Failed";
6233                 break;
6234
6235         case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6236                 desc = "SCSI IOC Terminated";
6237                 break;
6238
6239         case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6240                 desc = "SCSI Ext Terminated";
6241                 break;
6242
6243         default:
6244                 desc = "Others";
6245                 break;
6246         }
6247         if (desc != "")
6248                 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6249 }
6250
6251 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6252 /**
6253  *      mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI
6254  *      OpCode strings from the (optional) isense module.
6255  *      @ascqTable: Pointer to ASCQ_Table_t structure
6256  *      @ascqtbl_sz: Number of entries in ASCQ_Table
6257  *      @opsTable: Pointer to array of SCSI OpCode strings (char pointers)
6258  *
6259  *      Specialized driver registration routine for the isense driver.
6260  */
6261 int
6262 mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable)
6263 {
6264         int r = 0;
6265
6266         if (ascqTable && ascqtbl_sz && opsTable) {
6267                 mpt_v_ASCQ_TablePtr = ascqTable;
6268                 mpt_ASCQ_TableSz = ascqtbl_sz;
6269                 mpt_ScsiOpcodesPtr = opsTable;
6270                 printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n");
6271                 isense_idx = last_drv_idx;
6272                 r = 1;
6273         }
6274         return r;
6275 }
6276
6277 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6278 /**
6279  *      mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI
6280  *      OpCode strings from the isense driver.
6281  *
6282  *      Specialized driver deregistration routine for the isense driver.
6283  */
6284 void
6285 mpt_deregister_ascqops_strings(void)
6286 {
6287         mpt_v_ASCQ_TablePtr = NULL;
6288         mpt_ASCQ_TableSz = 0;
6289         mpt_ScsiOpcodesPtr = NULL;
6290         printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
6291         isense_idx = -1;
6292 }
6293
6294 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6295
6296 EXPORT_SYMBOL(mpt_adapters);
6297 EXPORT_SYMBOL(mpt_proc_root_dir);
6298 EXPORT_SYMBOL(DmpService);
6299 EXPORT_SYMBOL(mpt_register);
6300 EXPORT_SYMBOL(mpt_deregister);
6301 EXPORT_SYMBOL(mpt_event_register);
6302 EXPORT_SYMBOL(mpt_event_deregister);
6303 EXPORT_SYMBOL(mpt_reset_register);
6304 EXPORT_SYMBOL(mpt_reset_deregister);
6305 EXPORT_SYMBOL(mpt_device_driver_register);
6306 EXPORT_SYMBOL(mpt_device_driver_deregister);
6307 EXPORT_SYMBOL(mpt_get_msg_frame);
6308 EXPORT_SYMBOL(mpt_put_msg_frame);
6309 EXPORT_SYMBOL(mpt_free_msg_frame);
6310 EXPORT_SYMBOL(mpt_add_sge);
6311 EXPORT_SYMBOL(mpt_add_chain);
6312 EXPORT_SYMBOL(mpt_send_handshake_request);
6313 EXPORT_SYMBOL(mpt_handshake_req_reply_wait);
6314 EXPORT_SYMBOL(mpt_adapter_find_first);
6315 EXPORT_SYMBOL(mpt_adapter_find_next);
6316 EXPORT_SYMBOL(mpt_verify_adapter);
6317 EXPORT_SYMBOL(mpt_GetIocState);
6318 EXPORT_SYMBOL(mpt_print_ioc_summary);
6319 EXPORT_SYMBOL(mpt_lan_index);
6320 EXPORT_SYMBOL(mpt_stm_index);
6321 EXPORT_SYMBOL(mpt_HardResetHandler);
6322 EXPORT_SYMBOL(mpt_config);
6323 EXPORT_SYMBOL(mpt_toolbox);
6324 EXPORT_SYMBOL(mpt_findImVolumes);
6325 EXPORT_SYMBOL(mpt_read_ioc_pg_3);
6326 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6327 EXPORT_SYMBOL(mpt_free_fw_memory);
6328
6329 EXPORT_SYMBOL(mpt_register_ascqops_strings);
6330 EXPORT_SYMBOL(mpt_deregister_ascqops_strings);
6331 EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr);
6332 EXPORT_SYMBOL(mpt_ASCQ_TableSz);
6333 EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
6334
6335
6336 static struct pci_driver mptbase_driver = {
6337         .name           = "mptbase",
6338         .id_table       = mptbase_pci_table,
6339         .probe          = mptbase_probe,
6340         .remove         = __devexit_p(mptbase_remove),
6341         .driver         = {
6342                 .shutdown = mptbase_shutdown,
6343         },
6344 #ifdef CONFIG_PM
6345         .suspend        = mptbase_suspend,
6346         .resume         = mptbase_resume,
6347 #endif
6348 };
6349
6350 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6351 /*
6352  *      fusion_init - Fusion MPT base driver initialization routine.
6353  *
6354  *      Returns 0 for success, non-zero for failure.
6355  */
6356 static int __init
6357 fusion_init(void)
6358 {
6359         int i;
6360         int r;
6361
6362         if (FusionInitCalled++) {
6363                 dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n"));
6364                 return 0;
6365         }
6366
6367         show_mptmod_ver(my_NAME, my_VERSION);
6368         printk(KERN_INFO COPYRIGHT "\n");
6369
6370         Q_INIT(&MptAdapters, MPT_ADAPTER);                      /* set to empty */
6371         for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6372                 MptCallbacks[i] = NULL;
6373                 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6374                 MptEvHandlers[i] = NULL;
6375                 MptResetHandlers[i] = NULL;
6376         }
6377
6378         DmpService = NULL;
6379
6380         /* NEW!  20010120 -sralston
6381          *  Register ourselves (mptbase) in order to facilitate
6382          *  EventNotification handling.
6383          */
6384         mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6385
6386         /* Register for hard reset handling callbacks.
6387          */
6388         if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6389                 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6390         } else {
6391                 /* FIXME! */
6392         }
6393
6394         r = pci_module_init(&mptbase_driver);
6395         if(r)
6396                 return(r);
6397
6398 #ifdef CONFIG_PROC_FS
6399         (void) procmpt_create();
6400 #endif
6401
6402         return r;
6403 }
6404
6405 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6406 /*
6407  *      fusion_exit - Perform driver unload cleanup.
6408  *
6409  *      This routine frees all resources associated with each MPT adapter
6410  *      and removes all %MPT_PROCFS_MPTBASEDIR entries.
6411  */
6412 static void __exit
6413 fusion_exit(void)
6414 {
6415
6416         dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6417
6418         /* Whups?  20010120 -sralston
6419          *  Moved this *above* removal of all MptAdapters!
6420          */
6421 #ifdef CONFIG_PROC_FS
6422         (void) procmpt_destroy();
6423 #endif
6424         pci_unregister_driver(&mptbase_driver);
6425         mpt_reset_deregister(mpt_base_index);
6426 }
6427
6428
6429 module_init(fusion_init);
6430 module_exit(fusion_exit);