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