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