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