[PATCH] usbcore: Improve endpoint sysfs file handling
[linux/fpc-iii.git] / drivers / message / fusion / mptbase.c
blob790a2932ded99673bae69d0ab7cd16e99e2454b9
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.
8 * Copyright (c) 1999-2005 LSI Logic Corporation
9 * (mailto:mpt_linux_developer@lsil.com)
12 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
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.
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.
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
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
47 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
71 #include "mptbase.h"
73 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
74 #define my_NAME "Fusion MPT base driver"
75 #define my_VERSION MPT_LINUX_VERSION_COMMON
76 #define MYNAM "mptbase"
78 MODULE_AUTHOR(MODULEAUTHOR);
79 MODULE_DESCRIPTION(my_NAME);
80 MODULE_LICENSE("GPL");
83 * cmd line parameters
85 #ifdef MFCNT
86 static int mfcounter = 0;
87 #define PRINT_MF_COUNT 20000
88 #endif
90 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
92 * Public data...
94 int mpt_lan_index = -1;
95 int mpt_stm_index = -1;
97 struct proc_dir_entry *mpt_proc_root_dir;
99 #define WHOINIT_UNKNOWN 0xAA
101 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
103 * Private data...
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];
117 static int mpt_base_index = -1;
118 static int last_drv_idx = -1;
120 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
122 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
124 * Forward protos...
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);
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);
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);
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);
182 /* module entry point */
183 static int __init fusion_init (void);
184 static void __exit fusion_exit (void);
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)
192 static void
193 pci_disable_io_access(struct pci_dev *pdev)
195 u16 command_reg;
197 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
198 command_reg &= ~1;
199 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
202 static void
203 pci_enable_io_access(struct pci_dev *pdev)
205 u16 command_reg;
207 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
208 command_reg |= 1;
209 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
213 * Process turbo (context) reply...
215 static void
216 mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
218 MPT_FRAME_HDR *mf = NULL;
219 MPT_FRAME_HDR *mr = NULL;
220 int req_idx = 0;
221 int cb_idx;
223 dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
224 ioc->name, pa));
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;
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:-)
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;
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();
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;
270 if (MptCallbacks[cb_idx](ioc, mf, mr))
271 mpt_free_msg_frame(ioc, mf);
272 out:
273 mb();
276 static void
277 mpt_reply(MPT_ADAPTER *ioc, u32 pa)
279 MPT_FRAME_HDR *mf;
280 MPT_FRAME_HDR *mr;
281 int req_idx;
282 int cb_idx;
283 int freeme;
285 u32 reply_dma_low;
286 u16 ioc_stat;
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)!
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
298 reply_dma_low = (pa <<= 1);
299 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
300 (reply_dma_low - ioc->reply_frames_low_dma));
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);
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)
310 /* Check/log IOC log info
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);
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);
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;
339 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
341 out:
342 /* Flush (non-TURBO) reply with a WRITE! */
343 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
345 if (freeme)
346 mpt_free_msg_frame(ioc, mf);
347 mb();
350 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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)
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.
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.
368 static irqreturn_t
369 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
371 MPT_ADAPTER *ioc = bus_id;
372 u32 pa;
375 * Drain the reply FIFO!
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);
387 return IRQ_HANDLED;
390 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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)
399 * Returns 1 indicating original alloc'd request frame ptr
400 * should be freed, or 0 if it shouldn't.
402 static int
403 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
405 int freereq = 1;
406 u8 func;
408 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
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)
415 #endif
417 func = reply->u.hdr.Function;
418 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
419 ioc->name, func));
421 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
422 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
423 int evHandlers = 0;
424 int results;
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));
434 * Hmmm... It seems that EventNotificationReply is an exception
435 * to the rule of one reply per request.
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));
446 #ifdef CONFIG_PROC_FS
447 // LogEvent(ioc, pEvReply);
448 #endif
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;
458 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
459 ioc->name, mf, reply));
461 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
463 if (pCfg) {
464 /* disable timer and remove from linked list */
465 del_timer(&pCfg->timer);
467 spin_lock_irqsave(&ioc->FreeQlock, flags);
468 list_del(&pCfg->linkage);
469 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
472 * If IOC Status is SUCCESS, save the header
473 * and set the status code to GOOD.
475 pCfg->status = MPT_CONFIG_ERROR;
476 if (reply) {
477 ConfigReply_t *pReply = (ConfigReply_t *)reply;
478 u16 status;
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)));
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;
494 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
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;
505 * Wake up the original calling thread
507 pCfg->wait_done = 1;
508 wake_up(&mpt_waitq);
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);
524 * Conditionally tell caller to free the original
525 * EventNotification/EventAck/unexpected request frame!
527 return freereq;
530 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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)
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.
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.
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.
551 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
553 int i;
555 last_drv_idx = -1;
558 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
559 * (slot/handle 0 is reserved!)
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;
571 return last_drv_idx;
574 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
576 * mpt_deregister - Deregister a protocol drivers resources.
577 * @cb_idx: previously registered callback handle
579 * Each protocol-specific driver should call this routine when it's
580 * module is unloaded.
582 void
583 mpt_deregister(int cb_idx)
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;
590 last_drv_idx++;
594 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
601 * This routine can be called by one or more protocol-specific drivers
602 * if/when they choose to be notified of MPT events.
604 * Returns 0 for success.
607 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
609 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
610 return -1;
612 MptEvHandlers[cb_idx] = ev_cbfunc;
613 return 0;
616 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
618 * mpt_event_deregister - Deregister protocol-specific event callback
619 * handler.
620 * @cb_idx: previously registered callback handle
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.
626 void
627 mpt_event_deregister(int cb_idx)
629 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
630 return;
632 MptEvHandlers[cb_idx] = NULL;
635 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
641 * This routine can be called by one or more protocol-specific drivers
642 * if/when they choose to be notified of IOC resets.
644 * Returns 0 for success.
647 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
649 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
650 return -1;
652 MptResetHandlers[cb_idx] = reset_func;
653 return 0;
656 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
658 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
659 * @cb_idx: previously registered callback handle
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.
665 void
666 mpt_reset_deregister(int cb_idx)
668 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
669 return;
671 MptResetHandlers[cb_idx] = NULL;
674 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
676 * mpt_device_driver_register - Register device driver hooks
679 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
681 MPT_ADAPTER *ioc;
683 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
684 return -EINVAL;
687 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
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);
697 return 0;
700 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
702 * mpt_device_driver_deregister - DeRegister device driver hooks
704 void
705 mpt_device_driver_deregister(int cb_idx)
707 struct mpt_pci_driver *dd_cbfunc;
708 MPT_ADAPTER *ioc;
710 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
711 return;
713 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
715 list_for_each_entry(ioc, &ioc_list, list) {
716 if (dd_cbfunc->remove)
717 dd_cbfunc->remove(ioc->pcidev);
720 MptDeviceDriverHandlers[cb_idx] = NULL;
724 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
731 * Returns pointer to a MPT request frame or %NULL if none are available
732 * or IOC is not active.
734 MPT_FRAME_HDR*
735 mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
737 MPT_FRAME_HDR *mf;
738 unsigned long flags;
739 u16 req_idx; /* Request index */
741 /* validate handle and ioc identifier */
743 #ifdef MFCNT
744 if (!ioc->active)
745 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
746 #endif
748 /* If interrupts are not attached, do not return a request frame */
749 if (!ioc->active)
750 return NULL;
752 spin_lock_irqsave(&ioc->FreeQlock, flags);
753 if (!list_empty(&ioc->FreeQ)) {
754 int req_offset;
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
771 else
772 mf = NULL;
773 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
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
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;
788 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
796 * This routine posts a MPT request frame to the request post FIFO of a
797 * specific MPT adapter.
799 void
800 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
802 u32 mf_dma_addr;
803 int req_offset;
804 u16 req_idx; /* Request index */
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;
814 #ifdef MPT_DEBUG_MSG_FRAME
816 u32 *m = mf->u.frame.hwhdr.__hdr;
817 int ii, n;
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]));
829 printk("\n");
831 #endif
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);
838 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
845 * This routine places a MPT request frame back on the MPT adapter's
846 * FreeQ.
848 void
849 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
851 unsigned long flags;
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);
863 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
870 * This routine places a MPT request frame back on the MPT adapter's
871 * FreeQ.
873 void
874 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
876 if (sizeof(dma_addr_t) == sizeof(u64)) {
877 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
878 u32 tmp = dma_addr & 0xFFFFFFFF;
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);
885 } else {
886 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
887 pSge->FlagsLength = cpu_to_le32(flagslength);
888 pSge->Address = cpu_to_le32(dma_addr);
892 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
902 * This routine is used exclusively to send MptScsiTaskMgmt
903 * requests since they are required to be sent via doorbell handshake.
905 * NOTE: It is the callers responsibility to byte-swap fields in the
906 * request which are greater than 1 byte in size.
908 * Returns 0 for success, non-zero for failure.
911 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
913 int r = 0;
914 u8 *req_as_bytes;
915 int ii;
917 /* State is known to be good upon entering
918 * this function so issue the bus reset
919 * request.
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...
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;
934 /* Make sure there are no doorbells */
935 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
937 CHIPREG_WRITE32(&ioc->chip->Doorbell,
938 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
939 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
941 /* Wait for IOC doorbell int */
942 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
943 return ii;
946 /* Read doorbell and check for active bit */
947 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
948 return -5;
950 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
951 ioc->name, ii));
953 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
955 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
956 return -2;
959 /* Send request via doorbell handshake */
960 req_as_bytes = (u8 *) req;
961 for (ii = 0; ii < reqBytes/4; ii++) {
962 u32 word;
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;
975 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
976 r = 0;
977 else
978 r = -4;
980 /* Make sure there are no doorbells */
981 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
983 return r;
986 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
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 }
999 * Returns 0 for success, non-zero for failure.
1002 static int
1003 mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1005 int r = 0;
1007 /* return if in use */
1008 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1009 & MPI_DOORBELL_ACTIVE)
1010 return -1;
1012 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1014 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1015 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1016 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1017 (access_control_value<<12)));
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;
1026 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
1033 * Returns 0 for success, non-zero for failure.
1035 static int
1036 mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1038 char *psge;
1039 int flags_length;
1040 u32 host_page_buffer_sz=0;
1042 if(!ioc->HostPageBuffer) {
1044 host_page_buffer_sz =
1045 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1047 if(!host_page_buffer_sz)
1048 return 0; /* fw doesn't need any host buffers */
1050 /* spin till we get enough memory */
1051 while(host_page_buffer_sz > 0) {
1053 if((ioc->HostPageBuffer = pci_alloc_consistent(
1054 ioc->pcidev,
1055 host_page_buffer_sz,
1056 &ioc->HostPageBuffer_dma)) != NULL) {
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;
1069 host_page_buffer_sz -= (4*1024);
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;
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;
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;
1094 return 0;
1097 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
1104 * Returns iocid and sets iocpp.
1107 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1109 MPT_ADAPTER *ioc;
1111 list_for_each_entry(ioc,&ioc_list,list) {
1112 if (ioc->id == iocid) {
1113 *iocpp =ioc;
1114 return iocid;
1118 *iocpp = NULL;
1119 return -1;
1122 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1124 * mpt_attach - Install a PCI intelligent MPT adapter.
1125 * @pdev: Pointer to pci_dev structure
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.
1132 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1133 * MPT adapter.
1135 * Returns 0 for success, non-zero for failure.
1137 * TODO: Add support for polled controllers
1140 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
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
1157 if (pci_enable_device(pdev))
1158 return r;
1160 dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
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;
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"));
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;
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;
1187 ioc->pcidev = pdev;
1188 ioc->diagPending = 0;
1189 spin_lock_init(&ioc->diagLock);
1191 /* Initialize the event logging.
1193 ioc->eventTypes = 0; /* None */
1194 ioc->eventContext = 0;
1195 ioc->eventLogSize = 0;
1196 ioc->events = NULL;
1198 #ifdef MFCNT
1199 ioc->mfcnt = 0;
1200 #endif
1202 ioc->cached_fw = NULL;
1204 /* Initilize SCSI Config Data structure
1206 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1208 /* Initialize the running configQ head.
1210 INIT_LIST_HEAD(&ioc->configQ);
1212 /* Find lookup slot. */
1213 INIT_LIST_HEAD(&ioc->list);
1214 ioc->id = mpt_ids++;
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;
1230 ioc->mem_size = msize;
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;
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));
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;
1250 ioc->memmap = mem;
1251 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1253 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1254 &ioc->facts, &ioc->pfacts[0]));
1256 ioc->mem_phys = mem_phys;
1257 ioc->chip = (SYSIF_REGS __iomem *)mem;
1259 /* Save Port IO values in case we need to do downloadboot */
1261 u8 *pmem = (u8*)port;
1262 ioc->pio_mem_phys = port;
1263 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1266 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1267 ioc->prod_name = "LSIFC909";
1268 ioc->bus_type = FC;
1270 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1271 ioc->prod_name = "LSIFC929";
1272 ioc->bus_type = FC;
1274 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1275 ioc->prod_name = "LSIFC919";
1276 ioc->bus_type = FC;
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.
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.
1293 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1294 pcixcmd |= 0x08;
1295 pci_write_config_byte(pdev, 0x6a, pcixcmd);
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.
1304 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1305 pcixcmd &= 0x8F;
1306 pci_write_config_byte(pdev, 0x6a, pcixcmd);
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;
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;
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).
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);
1331 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1332 ioc->prod_name = "LSI53C1035";
1333 ioc->bus_type = SCSI;
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;
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;
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;
1350 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1351 ioc->prod_name = "LSISAS1064E";
1352 ioc->bus_type = SAS;
1354 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
1355 ioc->prod_name = "LSISAS1066E";
1356 ioc->bus_type = SAS;
1358 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1359 ioc->prod_name = "LSISAS1068E";
1360 ioc->bus_type = SAS;
1363 if (ioc->errata_flag_1064)
1364 pci_disable_io_access(pdev);
1366 sprintf(ioc->name, "ioc%d", ioc->id);
1368 spin_lock_init(&ioc->FreeQlock);
1370 /* Disable all! */
1371 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1372 ioc->active = 0;
1373 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1375 /* Set lookup ptr. */
1376 list_add_tail(&ioc->list, &ioc_list);
1378 ioc->pci_irq = -1;
1379 if (pdev->irq) {
1380 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
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;
1396 ioc->pci_irq = pdev->irq;
1398 pci_set_master(pdev); /* ?? */
1399 pci_set_drvdata(pdev, ioc);
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
1408 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1410 mpt_detect_bound_ports(ioc, pdev);
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);
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;
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);
1434 #ifdef CONFIG_PROC_FS
1436 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
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;
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;
1451 #endif
1453 return 0;
1456 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1458 * mpt_detach - Remove a PCI intelligent MPT adapter.
1459 * @pdev: Pointer to pci_dev structure
1463 void
1464 mpt_detach(struct pci_dev *pdev)
1466 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1467 char pname[32];
1468 int ii;
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);
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);
1485 /* Disable interrupts! */
1486 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1488 ioc->active = 0;
1489 synchronize_irq(pdev->irq);
1491 /* Clear any lingering interrupt */
1492 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1494 CHIPREG_READ32(&ioc->chip->IntStatus);
1496 mpt_adapter_dispose(ioc);
1498 pci_set_drvdata(pdev, NULL);
1501 /**************************************************************************
1502 * Power Management
1504 #ifdef CONFIG_PM
1505 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1507 * mpt_suspend - Fusion MPT base driver suspend routine.
1512 mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1514 u32 device_state;
1515 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1517 device_state=pci_choose_state(pdev, state);
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);
1523 pci_save_state(pdev);
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);
1531 /* disable interrupts */
1532 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1533 ioc->active = 0;
1535 /* Clear any lingering interrupt */
1536 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1538 pci_disable_device(pdev);
1539 pci_set_power_state(pdev, device_state);
1541 return 0;
1544 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1546 * mpt_resume - Fusion MPT base driver resume routine.
1551 mpt_resume(struct pci_dev *pdev)
1553 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1554 u32 device_state = pdev->current_state;
1555 int recovery_state;
1556 int ii;
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);
1562 pci_set_power_state(pdev, 0);
1563 pci_restore_state(pdev);
1564 pci_enable_device(pdev);
1566 /* enable interrupts */
1567 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1568 ioc->active = 1;
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;
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));
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);
1595 return 0;
1597 #endif
1599 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
1606 * This routine performs all the steps necessary to bring the IOC
1607 * to a OPERATIONAL state.
1609 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1610 * MPT adapter.
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
1619 static int
1620 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
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;
1631 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1632 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1634 /* Disable reply interrupts (also blocks FreeQ) */
1635 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1636 ioc->active = 0;
1638 if (ioc->alt_ioc) {
1639 if (ioc->alt_ioc->active)
1640 reset_alt_ioc_active = 1;
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;
1647 hard = 1;
1648 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1649 hard = 0;
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);
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;
1664 } else {
1665 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1666 ioc->name);
1668 return -1;
1671 /* hard_reset_done = 0 if a soft reset was performed
1672 * and 1 if a hard reset was performed.
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);
1683 for (ii=0; ii<5; ii++) {
1684 /* Get IOC facts! Allow 5 retries */
1685 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1686 break;
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);
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
1702 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
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);
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
1718 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1719 ret = -3;
1721 /* May need to check/upload firmware & data here!
1722 * If fails, continue with alt-ioc processing
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;
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);
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));
1749 /* Controller is not operational, cannot do upload
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) {
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)
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));
1766 } else {
1767 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1768 ret = -5;
1774 if (ret == 0) {
1775 /* Enable! (reply interrupt) */
1776 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1777 ioc->active = 1;
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;
1788 /* Enable MPT base driver management of EventNotification
1789 * and EventAck handling.
1791 if ((ret == 0) && (!ioc->facts.EventState))
1792 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1794 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1795 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
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...
1803 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1804 if (ioc->bus_type == SAS) {
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;
1815 /* Find IM volumes
1817 mpt_findImVolumes(ioc);
1819 } else if (ioc->bus_type == FC) {
1821 * Pre-fetch FC port WWN and stuff...
1822 * (FCPortPage0_t stuff)
1824 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1825 (void) GetFcPortPage0(ioc, ii);
1828 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1829 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1831 * Pre-fetch the ports LAN MAC address!
1832 * (LANPage1_t stuff)
1834 (void) GetLanConfigPages(ioc);
1835 #ifdef MPT_DEBUG
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] ));
1841 #endif
1843 } else {
1844 /* Get NVRAM and adapter maximums from SPP 0 and 2
1846 mpt_GetScsiPortSettings(ioc, 0);
1848 /* Get version and length of SDP 1
1850 mpt_readScsiDevicePageHeaders(ioc, 0);
1852 /* Find IM volumes
1854 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1855 mpt_findImVolumes(ioc);
1857 /* Check, and possibly reset, the coalescing value
1859 mpt_read_ioc_pg_1(ioc);
1861 mpt_read_ioc_pg_4(ioc);
1864 GetIoUnitPage2(ioc);
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.
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++;
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++;
1890 /* FIXME? Examine results here? */
1893 return ret;
1896 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
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.
1907 static void
1908 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
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;
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));
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;
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;
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;
1946 pci_dev_put(peer);
1949 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1951 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1952 * @this: Pointer to MPT adapter structure
1954 static void
1955 mpt_adapter_disable(MPT_ADAPTER *ioc)
1957 int sz;
1958 int ret;
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);
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);
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;
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;
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;
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;
2009 kfree(ioc->spi_data.nvram);
2010 kfree(ioc->raid_data.pIocPg3);
2011 ioc->spi_data.nvram = NULL;
2012 ioc->raid_data.pIocPg3 = NULL;
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;
2023 if (ioc->ReqToChain != NULL) {
2024 kfree(ioc->ReqToChain);
2025 kfree(ioc->RequestNB);
2026 ioc->ReqToChain = NULL;
2029 kfree(ioc->ChainToChain);
2030 ioc->ChainToChain = NULL;
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);
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;
2050 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2052 * mpt_adapter_dispose - Free all resources associated with a MPT
2053 * adapter.
2054 * @ioc: Pointer to MPT adapter structure
2056 * This routine unregisters h/w resources and frees all alloc'd memory
2057 * associated with a MPT adapter structure.
2059 static void
2060 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2062 int sz_first, sz_last;
2064 if (ioc == NULL)
2065 return;
2067 sz_first = ioc->alloc_total;
2069 mpt_adapter_disable(ioc);
2071 if (ioc->pci_irq != -1) {
2072 free_irq(ioc->pci_irq, ioc);
2073 ioc->pci_irq = -1;
2076 if (ioc->memmap != NULL) {
2077 iounmap(ioc->memmap);
2078 ioc->memmap = NULL;
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));
2086 #endif
2088 /* Zap the adapter lookup ptr! */
2089 list_del(&ioc->list);
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);
2097 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2099 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2100 * @ioc: Pointer to MPT adapter structure
2102 static void
2103 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2105 int i = 0;
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={");
2112 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2113 printk("Initiator");
2114 i++;
2117 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2118 printk("%sTarget", i ? "," : "");
2119 i++;
2122 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2123 printk("%sLAN", i ? "," : "");
2124 i++;
2127 #if 0
2129 * This would probably evoke more questions than it's worth
2131 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2132 printk("%sLogBusAddr", i ? "," : "");
2133 i++;
2135 #endif
2137 printk("}\n");
2140 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
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
2155 static int
2156 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
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;
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));
2171 * Check to see if IOC got left/stuck in doorbell handshake
2172 * grip of death. If so, hard reset the IOC.
2174 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2175 statefault = 1;
2176 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2177 ioc->name);
2180 /* Is it already READY? */
2181 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2182 return 0;
2185 * Check to see if IOC is in FAULT state.
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);
2196 * Hmmm... Did it get left operational?
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));
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
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;
2218 statefault = 3;
2222 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2223 if (hard_reset_done < 0)
2224 return -1;
2227 * Loop here waiting for IOC to come READY.
2229 ii = 0;
2230 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
2232 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2233 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2235 * BIOS or previous driver load left IOC in OP state.
2236 * Reset messaging FIFOs.
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;
2242 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2244 * Something is wrong. Try to get IOC back
2245 * to a known state.
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;
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;
2260 if (sleepFlag == CAN_SLEEP) {
2261 msleep_interruptible(1);
2262 } else {
2263 mdelay (1); /* 1 msec delay */
2268 if (statefault < 3) {
2269 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2270 ioc->name,
2271 statefault==1 ? "stuck handshake" : "IOC FAULT");
2274 return hard_reset_done;
2277 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
2283 * Returns all IOC Doorbell register bits if cooked==0, else just the
2284 * Doorbell bits in MPI_IOC_STATE_MASK.
2287 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2289 u32 s, sc;
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;
2296 /* Save! */
2297 ioc->last_state = sc;
2299 return cooked ? sc : s;
2302 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
2309 * Returns 0 for success, non-zero for failure.
2311 static int
2312 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
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;
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;
2331 facts = &ioc->facts;
2333 /* Destination (reply area)... */
2334 reply_sz = sizeof(*facts);
2335 memset(facts, 0, reply_sz);
2337 /* Request area (get_facts on the stack right now!) */
2338 req_sz = sizeof(get_facts);
2339 memset(&get_facts, 0, req_sz);
2341 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2342 /* Assert: All other get_facts fields are zero! */
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));
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.
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;
2357 * Now byte swap (GRRR) the necessary fields before any further
2358 * inspection of reply contents.
2360 * But need to do some sanity checks on MsgLength (byte) field
2361 * to make sure we don't zero IOC's req_sz!
2363 /* Did we get a valid reply? */
2364 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2365 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2367 * If not been here, done that, save off first WhoInit value
2369 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2370 ioc->FirstWhoInit = facts->WhoInit;
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 */
2381 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2382 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
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)}
2389 if (facts->MsgVersion < 0x0102) {
2391 * Handle old FC f/w style, convert to new...
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);
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);
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.
2415 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2416 facts->MsgVersion > 0x0100) {
2417 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2420 sz = facts->FWImageSize;
2421 if ( sz & 0x01 )
2422 sz += 1;
2423 if ( sz & 0x02 )
2424 sz += 2;
2425 facts->FWImageSize = sz;
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;
2434 r = sz = facts->BlockSize;
2435 vv = ((63 / (sz * 4)) + 1) & 0x03;
2436 ioc->NB_for_64_byte_frame = vv;
2437 while ( sz )
2439 shiftFactor++;
2440 sz = sz >> 1;
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));
2446 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2448 * Set values for this IOC's request & reply frame sizes,
2449 * and request & reply queue depths...
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);
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));
2461 /* Get port facts! */
2462 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2463 return r;
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;
2473 return 0;
2476 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
2483 * Returns 0 for success, non-zero for failure.
2485 static int
2486 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2488 PortFacts_t get_pfacts;
2489 PortFactsReply_t *pfacts;
2490 int ii;
2491 int req_sz;
2492 int reply_sz;
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;
2502 pfacts = &ioc->pfacts[portnum];
2504 /* Destination (reply area)... */
2505 reply_sz = sizeof(*pfacts);
2506 memset(pfacts, 0, reply_sz);
2508 /* Request area (get_pfacts on the stack right now!) */
2509 req_sz = sizeof(get_pfacts);
2510 memset(&get_pfacts, 0, req_sz);
2512 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2513 get_pfacts.PortNumber = portnum;
2514 /* Assert: All other get_pfacts fields are zero! */
2516 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2517 ioc->name, portnum));
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.
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;
2527 /* Did we get a valid reply? */
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);
2540 return 0;
2543 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2545 * SendIocInit - Send IOCInit request to MPT adapter.
2546 * @ioc: Pointer to MPT_ADAPTER structure
2547 * @sleepFlag: Specifies whether the process can sleep
2549 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2551 * Returns 0 for success, non-zero for failure.
2553 static int
2554 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2556 IOCInit_t ioc_init;
2557 MPIDefaultReply_t init_reply;
2558 u32 state;
2559 int r;
2560 int count;
2561 int cntdn;
2563 memset(&ioc_init, 0, sizeof(ioc_init));
2564 memset(&init_reply, 0, sizeof(init_reply));
2566 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2567 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
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.
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));
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);
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;
2599 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2601 if (sizeof(dma_addr_t) == sizeof(u64)) {
2602 /* Save the upper 32-bits of the request
2603 * (reply) and sense buffers.
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);
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;
2618 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2619 ioc->name, &ioc_init));
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;
2628 /* No need to byte swap the multibyte fields in the reply
2629 * since we don't even look at it's contents.
2632 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2633 ioc->name, &ioc_init));
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;
2640 /* YIKES! SUPER IMPORTANT!!!
2641 * Poll IocState until _OPERATIONAL while IOC is doing
2642 * LoopInit and TargetDiscovery!
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);
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;
2660 state = mpt_GetIocState(ioc, 1);
2661 count++;
2663 dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2664 ioc->name, count));
2666 return r;
2669 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
2676 * Send PortEnable to bring IOC to OPERATIONAL state.
2678 * Returns 0 for success, non-zero for failure.
2680 static int
2681 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2683 PortEnable_t port_enable;
2684 MPIDefaultReply_t reply_buf;
2685 int rc;
2686 int req_sz;
2687 int reply_sz;
2689 /* Destination... */
2690 reply_sz = sizeof(MPIDefaultReply_t);
2691 memset(&reply_buf, 0, reply_sz);
2693 req_sz = sizeof(PortEnable_t);
2694 memset(&port_enable, 0, req_sz);
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; */
2702 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2703 ioc->name, portnum, &port_enable));
2705 /* RAID FW may take a long time to enable
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);
2715 return rc;
2719 * ioc: Pointer to MPT_ADAPTER structure
2720 * size - total FW bytes
2722 void
2723 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
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;
2736 * If alt_img is NULL, delete from ioc structure.
2737 * Else, delete a secondary image in same format.
2739 void
2740 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2742 int sz;
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;
2751 return;
2755 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
2761 * Returns 0 for success, >0 for handshake failure
2762 * <0 for fw upload failure.
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.
2769 static int
2770 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
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;
2782 /* If the image size is 0, we are done.
2784 if ((sz = ioc->facts.FWImageSize) == 0)
2785 return 0;
2787 mpt_alloc_fw_memory(ioc, sz);
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));
2792 if (ioc->cached_fw == NULL) {
2793 /* Major Failure.
2795 return -ENOMEM;
2798 prequest = (FWUpload_t *)&request;
2799 preply = (FWUploadReply_t *)&reply;
2801 /* Destination... */
2802 memset(prequest, 0, ioc->req_sz);
2804 reply_sz = sizeof(reply);
2805 memset(preply, 0, reply_sz);
2807 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2808 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
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);
2815 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2817 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2818 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
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)
2825 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2826 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2828 dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
2830 cmdStatus = -EFAULT;
2831 if (ii == 0) {
2832 /* Handshake transfer was complete and successful.
2833 * Check the Reply Frame.
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;
2843 dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
2844 ioc->name, cmdStatus));
2847 if (cmdStatus) {
2849 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2850 ioc->name));
2851 mpt_free_fw_memory(ioc);
2854 return cmdStatus;
2857 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
2864 * FwDownloadBoot requires Programmed IO access.
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.
2871 static int
2872 mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
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;
2884 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2885 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
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);
2894 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2896 /* wait 1 msec */
2897 if (sleepFlag == CAN_SLEEP) {
2898 msleep_interruptible(1);
2899 } else {
2900 mdelay (1);
2903 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2904 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
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;
2913 /* wait .1 sec */
2914 if (sleepFlag == CAN_SLEEP) {
2915 msleep_interruptible (100);
2916 } else {
2917 mdelay (100);
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;
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);
2935 /* Set the DiagRwEn and Disable ARM bits */
2936 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2938 fwSize = (pFwHeader->ImageSize + 3)/4;
2939 ptrFw = (u32 *) pFwHeader;
2941 /* Write the LoadStartAddress to the DiagRw Address Register
2942 * using Programmed IO
2944 if (ioc->errata_flag_1064)
2945 pci_enable_io_access(ioc->pcidev);
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));
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++);
2957 nextImage = pFwHeader->NextImageHeaderOffset;
2958 while (nextImage) {
2959 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
2961 load_addr = pExtImage->LoadStartAddress;
2963 fwSize = (pExtImage->ImageSize + 3) >> 2;
2964 ptrFw = (u32 *)pExtImage;
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);
2970 while (fwSize--) {
2971 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2973 nextImage = pExtImage->NextImageHeaderOffset;
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);
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);
2984 /* Clear the internal flash bad bit - autoincrementing register,
2985 * so must do two writes.
2987 if (ioc->bus_type == SCSI) {
2989 * 1030 and 1035 H/W errata, workaround to access
2990 * the ClearFlashBadSignatureBit
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);
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);
3003 /* wait 1 msec */
3004 if (sleepFlag == CAN_SLEEP) {
3005 msleep_interruptible (1);
3006 } else {
3007 mdelay (1);
3011 if (ioc->errata_flag_1064)
3012 pci_disable_io_access(ioc->pcidev);
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);
3023 /* Write 0xFF to reset the sequencer */
3024 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
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;
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;
3043 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3044 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3045 ioc->name));
3046 return -EFAULT;
3048 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3049 ioc->name));
3050 return 0;
3052 if (sleepFlag == CAN_SLEEP) {
3053 msleep_interruptible (10);
3054 } else {
3055 mdelay (10);
3058 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3059 ioc->name, ioc_state));
3060 return -EFAULT;
3063 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
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.
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
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
3089 static int
3090 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3092 int hard_reset_done = 0;
3093 u32 ioc_state=0;
3094 int cnt,cntdn;
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.
3101 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3103 if (sleepFlag == CAN_SLEEP) {
3104 msleep_interruptible (1000);
3105 } else {
3106 mdelay (1000);
3110 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3111 if (hard_reset_done < 0)
3112 return hard_reset_done;
3114 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3115 ioc->name));
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;
3125 if (sleepFlag == CAN_SLEEP) {
3126 msleep_interruptible (10);
3127 } else {
3128 mdelay (10);
3132 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3133 ioc->name, ioc_state);
3134 return -1;
3137 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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)
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.
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
3156 static int
3157 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
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
3167 /* Clear any existing interrupts */
3168 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3170 /* Use "Diagnostic reset" method! (only thing available!) */
3171 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
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
3180 /* Do the reset if we are told to ignore the reset history
3181 * or if the reset history is 0
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
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);
3195 /* wait 100 msec */
3196 if (sleepFlag == CAN_SLEEP) {
3197 msleep_interruptible (100);
3198 } else {
3199 mdelay (100);
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;
3210 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3212 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3213 ioc->name, diag0val));
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
3223 * Disable the ARM (Bug fix)
3226 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3227 mdelay(1);
3230 * Now hit the reset bit in the Diagnostic register
3231 * (THE BIG HAMMER!) (Clears DRWE bit).
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));
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.
3245 int ii;
3246 int r = 0;
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);
3260 /* FIXME? Examine results here? */
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
3268 for (count = 0; count < 30; count ++) {
3269 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3270 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3271 break;
3274 /* wait 1 sec */
3275 if (sleepFlag == CAN_SLEEP) {
3276 msleep_interruptible (1000);
3277 } else {
3278 mdelay (1000);
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);
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.
3294 for (count = 0; count < 60; count ++) {
3295 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3296 doorbell &= MPI_IOC_STATE_MASK;
3298 if (doorbell == MPI_IOC_STATE_READY) {
3299 break;
3302 /* wait 1 sec */
3303 if (sleepFlag == CAN_SLEEP) {
3304 msleep_interruptible (1000);
3305 } else {
3306 mdelay (1000);
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
3320 /* Clear RESET_HISTORY bit! Place board in the
3321 * diagnostic mode to update the diag register.
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
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);
3336 /* wait 100 msec */
3337 if (sleepFlag == CAN_SLEEP) {
3338 msleep_interruptible (100);
3339 } else {
3340 mdelay (100);
3343 count++;
3344 if (count > 20) {
3345 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3346 ioc->name, diag0val);
3347 break;
3349 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
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);
3359 /* Disable Diagnostic Mode
3361 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3363 /* Check FW reload status flags.
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;
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
3380 * Reset flag that says we've enabled event notification
3382 ioc->facts.EventState = 0;
3384 if (ioc->alt_ioc)
3385 ioc->alt_ioc->facts.EventState = 0;
3387 return hard_reset_done;
3390 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
3397 * Send IOCReset request to the MPT adapter.
3399 * Returns 0 for success, non-zero for failure.
3401 static int
3402 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3404 int r;
3405 u32 state;
3406 int cntdn, count;
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;
3414 /* FW ACK'd request, wait for READY state
3416 count = 0;
3417 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
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;
3426 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3427 ioc->name, (int)((count+5)/HZ));
3428 return -ETIME;
3431 if (sleepFlag == CAN_SLEEP) {
3432 msleep_interruptible(1);
3433 } else {
3434 mdelay (1); /* 1 msec delay */
3438 /* TODO!
3439 * Cleanup all event stuff for this IOC; re-issue EventNotification
3440 * request if needed.
3442 if (ioc->facts.Function)
3443 ioc->facts.EventState = 0;
3445 return 0;
3448 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
3455 static int
3456 initChainBuffers(MPT_ADAPTER *ioc)
3458 u8 *mem;
3459 int sz, ii, num_chain;
3460 int scale, num_sge, numSGE;
3462 /* ReqToChain size must equal the req_depth
3463 * index = req_idx
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;
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;
3478 ioc->RequestNB = (int *) mem;
3479 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3480 ioc->name, mem, sz));
3482 for (ii = 0; ii < ioc->req_depth; ii++) {
3483 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3486 /* ChainToChain size must equal the total number
3487 * of chain buffers to be allocated.
3488 * index = chain_idx
3490 * Calculate the number of chain buffers needed(plus 1) per I/O
3491 * then multiply the the maximum number of simultaneous cmds
3493 * num_sge = num sge in request frame + last chain buffer
3494 * scale = num sge per chain buffer if no chain element
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));
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));
3509 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3510 ioc->name, num_sge, numSGE));
3512 if ( numSGE > MPT_SCSI_SG_DEPTH )
3513 numSGE = MPT_SCSI_SG_DEPTH;
3515 num_chain = 1;
3516 while (numSGE - num_sge > 0) {
3517 num_chain++;
3518 num_sge += (scale - 1);
3520 num_chain++;
3522 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3523 ioc->name, numSGE, num_sge, num_chain));
3525 if (ioc->bus_type == SCSI)
3526 num_chain *= MPT_SCSI_CAN_QUEUE;
3527 else
3528 num_chain *= MPT_FC_CAN_QUEUE;
3530 ioc->num_chain = num_chain;
3532 sz = num_chain * sizeof(int);
3533 if (ioc->ChainToChain == NULL) {
3534 mem = kmalloc(sz, GFP_ATOMIC);
3535 if (mem == NULL)
3536 return -1;
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;
3544 memset(mem, 0xFF, sz);
3545 return num_chain;
3548 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3550 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3551 * @ioc: Pointer to MPT_ADAPTER structure
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.
3557 * Returns 0 for success, non-zero for failure.
3559 static int
3560 PrimeIocFifos(MPT_ADAPTER *ioc)
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;
3568 /* Prime reply FIFO... */
3570 if (ioc->reply_frames == NULL) {
3571 if ( (num_chain = initChainBuffers(ioc)) < 0)
3572 return -1;
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));
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;
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));
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;
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));
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);
3612 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3613 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3615 alloc_dma += reply_sz;
3616 mem += reply_sz;
3618 /* Request FIFO - WE manage this! */
3620 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3621 ioc->req_frames_dma = alloc_dma;
3623 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
3624 ioc->name, mem, (void *)(ulong)alloc_dma));
3626 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3628 #if defined(CONFIG_MTRR) && 0
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"
3634 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
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
3641 for (i = 0; i < ioc->req_depth; i++) {
3642 alloc_dma += ioc->req_sz;
3643 mem += ioc->req_sz;
3646 ioc->ChainBuffer = mem;
3647 ioc->ChainBufferDMA = alloc_dma;
3649 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
3650 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3652 /* Initialize the free chain Q.
3655 INIT_LIST_HEAD(&ioc->FreeChainQ);
3657 /* Post the chain buffers to the FreeChainQ.
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;
3666 /* Initialize Request frames linked list
3668 alloc_dma = ioc->req_frames_dma;
3669 mem = (u8 *) ioc->req_frames;
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;
3676 /* Queue REQUESTs *internally*! */
3677 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3679 mem += ioc->req_sz;
3681 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
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;
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));
3699 /* Post Reply frames to FIFO
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));
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;
3711 return 0;
3713 out_fail:
3714 if (ioc->alloc != NULL) {
3715 sz = ioc->alloc_sz;
3716 pci_free_consistent(ioc->pcidev,
3718 ioc->alloc, ioc->alloc_dma);
3719 ioc->reply_frames = NULL;
3720 ioc->req_frames = NULL;
3721 ioc->alloc_total -= sz;
3723 if (ioc->sense_buf_pool != NULL) {
3724 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3725 pci_free_consistent(ioc->pcidev,
3727 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3728 ioc->sense_buf_pool = NULL;
3730 return -1;
3733 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
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.
3750 * Returns 0 for success, non-zero for failure.
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)
3756 MPIDefaultReply_t *mptReply;
3757 int failcnt = 0;
3758 int t;
3761 * Get ready to cache a handshake reply
3763 ioc->hs_reply_idx = 0;
3764 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3765 mptReply->MsgLength = 0;
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).
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)));
3778 * Wait for IOC's doorbell handshake int
3780 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3781 failcnt++;
3783 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3784 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3786 /* Read doorbell and check for active bit */
3787 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3788 return -1;
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.
3795 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3796 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3797 failcnt++;
3799 if (!failcnt) {
3800 int ii;
3801 u8 *req_as_bytes = (u8 *) req;
3804 * Stuff request words via doorbell handshake,
3805 * with ACK from IOC for each.
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));
3813 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3814 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3815 failcnt++;
3818 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3819 DBG_DUMP_REQUEST_FRAME_HDR(req)
3821 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3822 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3825 * Wait for completion of doorbell handshake reply from the IOC
3827 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3828 failcnt++;
3830 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3831 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3834 * Copy out the cached reply...
3836 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3837 u16reply[ii] = ioc->hs_reply[ii];
3838 } else {
3839 return -99;
3842 return -failcnt;
3845 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
3853 * This routine waits (up to ~2 seconds max) for IOC doorbell
3854 * handshake ACKnowledge.
3856 * Returns a negative value on failure, else wait loop count.
3858 static int
3859 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3861 int cntdn;
3862 int count = 0;
3863 u32 intstat=0;
3865 cntdn = 1000 * howlong;
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++;
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++;
3885 if (cntdn) {
3886 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3887 ioc->name, count));
3888 return count;
3891 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3892 ioc->name, count, intstat);
3893 return -1;
3896 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
3904 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3906 * Returns a negative value on failure, else wait loop count.
3908 static int
3909 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3911 int cntdn;
3912 int count = 0;
3913 u32 intstat=0;
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++;
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++;
3934 if (cntdn) {
3935 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
3936 ioc->name, count, howlong));
3937 return count;
3940 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
3941 ioc->name, count, intstat);
3942 return -1;
3945 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
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.
3956 * Returns a negative value on failure, else size of reply in WORDS.
3958 static int
3959 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
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;
3968 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
3971 * Get first two u16's so we can look at IOC's intended reply MsgLength
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);
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!" : ""));
3992 * If no error (and IOC said MsgLength is > 0), piece together
3993 * reply 16 bits at a time.
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);
4005 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4006 failcnt++;
4007 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4009 if (failcnt) {
4010 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4011 ioc->name);
4012 return -failcnt;
4014 #if 0
4015 else if (u16cnt != (2 * mptReply->MsgLength)) {
4016 return -101;
4018 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4019 return -102;
4021 #endif
4023 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4024 DBG_DUMP_REPLY_FRAME(mptReply)
4026 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4027 ioc->name, t, u16cnt/2));
4028 return u16cnt/2;
4031 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4033 * GetLanConfigPages - Fetch LANConfig pages.
4034 * @ioc: Pointer to MPT_ADAPTER structure
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)
4042 static int
4043 GetLanConfigPages(MPT_ADAPTER *ioc)
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;
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;
4067 if ((rc = mpt_config(ioc, &cfg)) != 0)
4068 return rc;
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;
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);
4086 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4088 /* FIXME!
4089 * Normalize endianness of structure data,
4090 * by byte-swapping all > 1 byte fields!
4095 if (rc)
4096 return rc;
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;
4110 if ((rc = mpt_config(ioc, &cfg)) != 0)
4111 return rc;
4113 if (hdr.PageLength == 0)
4114 return 0;
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;
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);
4130 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4132 /* FIXME!
4133 * Normalize endianness of structure data,
4134 * by byte-swapping all > 1 byte fields!
4139 return rc;
4142 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4144 * GetFcPortPage0 - Fetch FCPort config Page0.
4145 * @ioc: Pointer to MPT_ADAPTER structure
4146 * @portnum: IOC Port number
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)
4154 static int
4155 GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
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;
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;
4178 if ((rc = mpt_config(ioc, &cfg)) != 0)
4179 return rc;
4181 if (hdr.PageLength == 0)
4182 return 0;
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;
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);
4199 * Normalize endianness of structure data,
4200 * by byte-swapping all > 1 byte fields!
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);
4221 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4224 return rc;
4227 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
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
4240 * NOTE: Don't use not this function during interrupt time.
4242 * Returns: 0 for success, non-zero error
4245 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4247 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4249 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4250 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4251 MPT_FRAME_HDR *mf = NULL;
4252 MPIHeader_t *mpi_hdr;
4255 /* insure garbage is not sent to fw */
4256 switch(persist_opcode) {
4258 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4259 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4260 break;
4262 default:
4263 return -1;
4264 break;
4267 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4269 /* Get a MF for this command.
4271 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4272 printk("%s: no msg frames!\n",__FUNCTION__);
4273 return -1;
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;
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);
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;
4302 printk("%s: success\n",__FUNCTION__);
4303 return 0;
4306 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4308 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4309 * @ioc: Pointer to MPT_ADAPTER structure
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)
4317 static int
4318 GetIoUnitPage2(MPT_ADAPTER *ioc)
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;
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;
4339 if ((rc = mpt_config(ioc, &cfg)) != 0)
4340 return rc;
4342 if (hdr.PageLength == 0)
4343 return 0;
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;
4354 /* If Good, save data */
4355 if ((rc = mpt_config(ioc, &cfg)) == 0)
4356 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4358 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4361 return rc;
4364 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4365 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4366 * @ioc: Pointer to a Adapter Strucutre
4367 * @portnum: IOC port number
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????
4384 static int
4385 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4387 u8 *pbuf;
4388 dma_addr_t buf_dma;
4389 CONFIGPARMS cfg;
4390 ConfigPageHeader_t header;
4391 int ii;
4392 int data, rc = 0;
4394 /* Allocate memory
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;
4404 ioc->spi_data.nvram = (int *) mem;
4406 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4407 ioc->name, ioc->spi_data.nvram, sz));
4410 /* Invalidate NVRAM information
4412 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4413 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4416 /* Read SPP0 header, allocate memory, then read page.
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;
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
4447 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4448 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4449 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
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));
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;
4469 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4471 /* Update the minSyncFactor based on bus type.
4473 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4474 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
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));
4483 if (pbuf) {
4484 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4489 /* SCSI Port Page 2 - Read the header then the page.
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;
4503 if (header.PageLength > 0) {
4504 /* Allocate memory and read SCSI Port Page 2
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
4513 rc = 1;
4514 } else {
4515 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4516 MpiDeviceInfo_t *pdevice = NULL;
4518 /* Save the Port Page 2 data
4519 * (reformat into a 32bit quantity)
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;
4531 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
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.
4540 return rc;
4543 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4544 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4545 * @ioc: Pointer to a Adapter Strucutre
4546 * @portnum: IOC port number
4548 * Return: -EFAULT if read of config page header fails
4549 * or 0 if success.
4551 static int
4552 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4554 CONFIGPARMS cfg;
4555 ConfigPageHeader_t header;
4557 /* Read the SCSI Device Page 1 header
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;
4572 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4573 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
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;
4582 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4583 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
4585 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4586 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
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;
4593 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4595 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4596 * @ioc: Pointer to a Adapter Strucutre
4597 * @portnum: IOC port number
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
4605 mpt_findImVolumes(MPT_ADAPTER *ioc)
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;
4619 /* Read IOCP2 header then the page.
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;
4634 if (header.PageLength == 0)
4635 return -EFAULT;
4637 iocpage2sz = header.PageLength * 4;
4638 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4639 if (!pIoc2)
4640 return -ENOMEM;
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;
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;
4655 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4657 /* Identify RAID Volume Id's */
4658 nVols = pIoc2->NumActiveVolumes;
4659 if ( nVols == 0) {
4660 /* No RAID Volume.
4662 goto done_and_free;
4663 } else {
4664 /* At least 1 RAID Volume
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;
4673 /* find the match
4675 if (vbus == 0) {
4676 ioc->raid_data.isRaid |= (1 << vid);
4677 } else {
4678 /* Error! Always bus 0
4684 /* Identify Hidden Physical Disk Id's */
4685 nPhys = pIoc2->NumActivePhysDisks;
4686 if (nPhys == 0) {
4687 /* No physical disks.
4689 } else {
4690 mpt_read_ioc_pg_3(ioc);
4693 done_and_free:
4694 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4696 return rc;
4700 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4702 IOCPage3_t *pIoc3;
4703 u8 *mem;
4704 CONFIGPARMS cfg;
4705 ConfigPageHeader_t header;
4706 dma_addr_t ioc3_dma;
4707 int iocpage3sz = 0;
4709 /* Free the old page
4711 kfree(ioc->raid_data.pIocPg3);
4712 ioc->raid_data.pIocPg3 = NULL;
4714 /* There is at least one physical disk.
4715 * Read and save IOC Page 3
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;
4730 if (header.PageLength == 0)
4731 return 0;
4733 /* Read Header good, alloc memory
4735 iocpage3sz = header.PageLength * 4;
4736 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4737 if (!pIoc3)
4738 return 0;
4740 /* Read the Page and save the data
4741 * into malloc'd memory.
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;
4753 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4755 return 0;
4758 static void
4759 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4761 IOCPage4_t *pIoc4;
4762 CONFIGPARMS cfg;
4763 ConfigPageHeader_t header;
4764 dma_addr_t ioc4_dma;
4765 int iocpage4sz;
4767 /* Read and save IOC Page 4
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;
4782 if (header.PageLength == 0)
4783 return;
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;
4795 /* Read the Page into dma memory.
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;
4809 static void
4810 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4812 IOCPage1_t *pIoc1;
4813 CONFIGPARMS cfg;
4814 ConfigPageHeader_t header;
4815 dma_addr_t ioc1_dma;
4816 int iocpage1sz = 0;
4817 u32 tmp;
4819 /* Check the Coalescing Timeout in IOC Page 1
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;
4834 if (header.PageLength == 0)
4835 return;
4837 /* Read Header good, alloc memory
4839 iocpage1sz = header.PageLength * 4;
4840 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4841 if (!pIoc1)
4842 return;
4844 /* Read the Page and check coalescing timeout
4846 cfg.physAddr = ioc1_dma;
4847 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4848 if (mpt_config(ioc, &cfg) == 0) {
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);
4854 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4855 ioc->name, tmp));
4857 if (tmp > MPT_COALESCING_TIMEOUT) {
4858 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4860 /* Write NVRAM and current
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));
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));
4877 } else {
4878 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4879 ioc->name));
4883 } else {
4884 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4888 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
4890 return;
4893 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4895 * SendEventNotification - Send EventNotification (on or off) request
4896 * to MPT adapter.
4897 * @ioc: Pointer to MPT_ADAPTER structure
4898 * @EvSwitch: Event switch flags
4900 static int
4901 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
4903 EventNotification_t *evnp;
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;
4911 memset(evnp, 0, sizeof(*evnp));
4913 devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
4915 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
4916 evnp->ChainOffset = 0;
4917 evnp->MsgFlags = 0;
4918 evnp->Switch = EvSwitch;
4920 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
4922 return 0;
4925 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4927 * SendEventAck - Send EventAck request to MPT adapter.
4928 * @ioc: Pointer to MPT_ADAPTER structure
4929 * @evnp: Pointer to original EventNotification request
4931 static int
4932 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
4934 EventAck_t *pAck;
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;
4943 memset(pAck, 0, sizeof(*pAck));
4945 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
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;
4953 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
4955 return 0;
4958 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
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)
4973 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
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;
4983 /* Prevent calling wait_event() (below), if caller happens
4984 * to be in ISR context, because that is fatal!
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;
4993 /* Get and Populate a free Frame
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;
5000 pReq = (Config_t *)mf;
5001 pReq->Action = pCfg->action;
5002 pReq->Reserved = 0;
5003 pReq->ChainOffset = 0;
5004 pReq->Function = MPI_FUNCTION_CONFIG;
5006 /* Assume page type is not extended and clear "reserved" fields. */
5007 pReq->ExtPageLength = 0;
5008 pReq->ExtPageType = 0;
5009 pReq->MsgFlags = 0;
5011 for (ii=0; ii < 8; ii++)
5012 pReq->Reserved2[ii] = 0;
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);
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;
5025 /* Page Length must be treated as a reserved field for the extended header. */
5026 pReq->Header.PageLength = 0;
5029 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5031 /* Add a SGE to the config request.
5033 if (pCfg->dir)
5034 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5035 else
5036 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5038 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5039 flagsLength |= pExtHdr->ExtPageLength * 4;
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));
5044 else {
5045 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
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));
5051 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5053 /* Append pCfg pointer to end of mf
5055 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5057 /* Initalize the timer
5059 init_timer(&pCfg->timer);
5060 pCfg->timer.data = (unsigned long) ioc;
5061 pCfg->timer.function = mpt_timer_expired;
5062 pCfg->wait_done = 0;
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;
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);
5075 add_timer(&pCfg->timer);
5076 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5077 wait_event(mpt_waitq, pCfg->wait_done);
5079 /* mf has been freed - do not access */
5081 rc = pCfg->status;
5083 return rc;
5086 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
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)
5101 mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
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;
5111 /* Prevent calling wait_event() (below), if caller happens
5112 * to be in ISR context, because that is fatal!
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;
5121 /* Get and Populate a free Frame
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;
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;
5152 /* Add a SGE to the config request.
5155 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
5157 mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
5159 dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
5160 ioc->name, pReq->Tool));
5162 /* Append pCfg pointer to end of mf
5164 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5166 /* Initalize the timer
5168 init_timer(&pCfg->timer);
5169 pCfg->timer.data = (unsigned long) ioc;
5170 pCfg->timer.function = mpt_timer_expired;
5171 pCfg->wait_done = 0;
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;
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);
5184 add_timer(&pCfg->timer);
5185 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5186 wait_event(mpt_waitq, pCfg->wait_done);
5188 /* mf has been freed - do not access */
5190 rc = pCfg->status;
5192 return rc;
5195 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
5201 static void
5202 mpt_timer_expired(unsigned long data)
5204 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5206 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
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);
5212 /* No more processing.
5213 * Hard reset clean-up will wake up
5214 * process and free all resources.
5216 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5218 return;
5221 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
5227 * Remark: Free's resources with internally generated commands.
5229 static int
5230 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5232 CONFIGPARMS *pCfg;
5233 unsigned long flags;
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")));
5240 if (reset_phase == MPT_IOC_SETUP_RESET) {
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.
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);
5252 } else {
5253 CONFIGPARMS *pNext;
5255 /* Search the configQ for internal commands.
5256 * Flush the Q, and wake up all suspended threads.
5258 spin_lock_irqsave(&ioc->FreeQlock, flags);
5259 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5260 list_del(&pCfg->linkage);
5262 pCfg->status = MPT_CONFIG_ERROR;
5263 pCfg->wait_done = 1;
5264 wake_up(&mpt_waitq);
5266 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5269 return 1; /* currently means nothing really */
5273 #ifdef CONFIG_PROC_FS /* { */
5274 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5276 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5278 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5280 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5282 * Returns 0 for success, non-zero for failure.
5284 static int
5285 procmpt_create(void)
5287 struct proc_dir_entry *ent;
5289 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5290 if (mpt_proc_root_dir == NULL)
5291 return -ENOTDIR;
5293 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5294 if (ent)
5295 ent->read_proc = procmpt_summary_read;
5297 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5298 if (ent)
5299 ent->read_proc = procmpt_version_read;
5301 return 0;
5304 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5306 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5308 * Returns 0 for success, non-zero for failure.
5310 static void
5311 procmpt_destroy(void)
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);
5318 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
5329 * Returns number of characters written to process performing the read.
5331 static int
5332 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5334 MPT_ADAPTER *ioc;
5335 char *out = buf;
5336 int len;
5338 if (data) {
5339 int more = 0;
5341 ioc = data;
5342 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5344 out += more;
5345 } else {
5346 list_for_each_entry(ioc, &ioc_list, list) {
5347 int more = 0;
5349 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5351 out += more;
5352 if ((out-buf) >= request)
5353 break;
5357 len = out - buf;
5359 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5362 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
5372 * Returns number of characters written to process performing the read.
5374 static int
5375 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5377 int ii;
5378 int scsi, fc, sas, lan, ctl, targ, dmp;
5379 char *drvname;
5380 int len;
5382 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5383 len += sprintf(buf+len, " Fusion MPT base driver\n");
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;
5410 if (drvname)
5411 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5415 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5418 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
5428 * Returns number of characters written to process performing the read.
5430 static int
5431 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5433 MPT_ADAPTER *ioc = data;
5434 int len;
5435 char expVer[32];
5436 int sz;
5437 int p;
5439 mpt_get_fw_exp_ver(expVer, ioc);
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!");
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);
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);
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);
5465 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5466 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5468 * Rounding UP to nearest 4-kB boundary here...
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);
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);
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);
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]);
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);
5510 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5513 #endif /* CONFIG_PROC_FS } */
5515 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5516 static void
5517 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
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 */
5525 /* insider hack! */
5526 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5527 strcat(buf, " [MDBG]");
5531 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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?
5540 * This routine writes (english readable) ASCII text, which represents
5541 * a summary of IOC information, to a buffer.
5543 void
5544 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5546 char expVer[32];
5547 int y;
5549 mpt_get_fw_exp_ver(expVer, ioc);
5552 * Shorter summary of attached ioc's...
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);
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]);
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
5575 if (!ioc->active)
5576 y += sprintf(buffer+len+y, " (disabled)");
5578 y += sprintf(buffer+len+y, "\n");
5580 *size = y;
5583 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5585 * Reset Handling
5587 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
5595 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5596 * or a non-interrupt thread. In the former, must not call schedule().
5598 * Remark: A return of -1 is a FATAL error case, as it means a
5599 * FW reload/initialization failed.
5601 * Returns 0 for SUCCESS or -1 if FAILED.
5604 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5606 int rc;
5607 unsigned long flags;
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
5615 /* Reset the adapter. Prevent more than 1 call to
5616 * mpt_do_ioc_recovery at any instant in time.
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;
5625 spin_unlock_irqrestore(&ioc->diagLock, flags);
5627 /* FIXME: If do_ioc_recovery fails, repeat....
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.
5636 int ii;
5637 int r = 0;
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);
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);
5657 ioc->reload_fw = 0;
5658 if (ioc->alt_ioc)
5659 ioc->alt_ioc->reload_fw = 0;
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);
5667 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5669 return rc;
5672 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5673 static void
5674 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
5676 char *ds;
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:
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;
5770 break;
5772 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5773 ds = "SCSI Device Status Change";
5774 break;
5775 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
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;
5795 break;
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;
5817 * MPT base "custom" events may be added here...
5819 default:
5820 ds = "Unknown";
5821 break;
5823 strcpy(evStr,ds);
5826 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
5834 * Returns sum of event handlers return values.
5836 static int
5837 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
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;
5849 * Do platform normalization of values
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]);
5858 EventDescriptionStr(event, evData0, evStr);
5859 devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
5860 ioc->name,
5861 evStr,
5862 event));
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
5872 * Do general / base driver event processing
5874 switch(event) {
5875 case MPI_EVENT_EVENT_CHANGE: /* 0A */
5876 if (evDataLen) {
5877 u8 evState = evData0 & 0xFF;
5879 /* CHECKME! What if evState unexpectedly says OFF (0)? */
5881 /* Update EventState field in cached IocFacts */
5882 if (ioc->facts.Function) {
5883 ioc->facts.EventState = evState;
5886 break;
5887 default:
5888 break;
5892 * Should this event be logged? Events are written sequentially.
5893 * When buffer is full, start again at the top.
5895 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
5896 int idx;
5898 idx = ioc->eventContext % ioc->eventLogSize;
5900 ioc->events[idx].event = event;
5901 ioc->events[idx].eventContext = ioc->eventContext;
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;
5910 ioc->eventContext++;
5915 * Call each currently registered protocol event handler.
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++;
5925 /* FIXME? Examine results here? */
5928 * If needed, send (a single) EventAck.
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));
5939 *evHandlers = handlers;
5940 return r;
5943 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
5949 * Refer to lsi/fc_log.h.
5951 static void
5952 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
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"
5958 u8 subcl = (log_info >> 24) & 0x7;
5960 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
5961 ioc->name, log_info, subcl_str[subcl]);
5964 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
5971 * Refer to lsi/sp_log.h.
5973 static void
5974 mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
5976 u32 info = log_info & 0x00FF0000;
5977 char *desc = "unknown";
5979 switch (info) {
5980 case 0x00010000:
5981 desc = "bug! MID not found";
5982 if (ioc->reload_fw == 0)
5983 ioc->reload_fw++;
5984 break;
5986 case 0x00020000:
5987 desc = "Parity Error";
5988 break;
5990 case 0x00030000:
5991 desc = "ASYNC Outbound Overrun";
5992 break;
5994 case 0x00040000:
5995 desc = "SYNC Offset Error";
5996 break;
5998 case 0x00050000:
5999 desc = "BM Change";
6000 break;
6002 case 0x00060000:
6003 desc = "Msg In Overflow";
6004 break;
6006 case 0x00070000:
6007 desc = "DMA Error";
6008 break;
6010 case 0x00080000:
6011 desc = "Outbound DMA Overrun";
6012 break;
6014 case 0x00090000:
6015 desc = "Task Management";
6016 break;
6018 case 0x000A0000:
6019 desc = "Device Problem";
6020 break;
6022 case 0x000B0000:
6023 desc = "Invalid Phase Change";
6024 break;
6026 case 0x000C0000:
6027 desc = "Untagged Table Size";
6028 break;
6032 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6035 /* strings for sas loginfo */
6036 static char *originator_str[] = {
6037 "IOP", /* 00h */
6038 "PL", /* 01h */
6039 "IR" /* 02h */
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 */
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 */
6085 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
6091 * Refer to lsi/mpi_log_sas.h.
6093 static void
6094 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
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;
6105 union loginfo_type sas_loginfo;
6106 char *code_desc = NULL;
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];
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);
6140 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
6147 * Refer to lsi/mpi.h.
6149 static void
6150 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6152 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6153 char *desc = "";
6155 switch (status) {
6156 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6157 desc = "Invalid Function";
6158 break;
6160 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6161 desc = "Busy";
6162 break;
6164 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6165 desc = "Invalid SGL";
6166 break;
6168 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6169 desc = "Internal Error";
6170 break;
6172 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6173 desc = "Reserved";
6174 break;
6176 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6177 desc = "Insufficient Resources";
6178 break;
6180 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6181 desc = "Invalid Field";
6182 break;
6184 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6185 desc = "Invalid State";
6186 break;
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;
6197 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6198 /* No message for recovered error
6199 desc = "SCSI Recovered Error";
6201 break;
6203 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6204 desc = "SCSI Invalid Bus";
6205 break;
6207 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6208 desc = "SCSI Invalid TargetID";
6209 break;
6211 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
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";
6218 break;
6221 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6222 desc = "SCSI Data Overrun";
6223 break;
6225 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
6226 /* This error is checked in scsi_io_done(). Skip.
6227 desc = "SCSI Data Underrun";
6229 break;
6231 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6232 desc = "SCSI I/O Data Error";
6233 break;
6235 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6236 desc = "SCSI Protocol Error";
6237 break;
6239 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6240 desc = "SCSI Task Terminated";
6241 break;
6243 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6244 desc = "SCSI Residual Mismatch";
6245 break;
6247 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6248 desc = "SCSI Task Management Failed";
6249 break;
6251 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6252 desc = "SCSI IOC Terminated";
6253 break;
6255 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6256 desc = "SCSI Ext Terminated";
6257 break;
6259 default:
6260 desc = "Others";
6261 break;
6263 if (desc != "")
6264 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
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);
6304 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6306 * fusion_init - Fusion MPT base driver initialization routine.
6308 * Returns 0 for success, non-zero for failure.
6310 static int __init
6311 fusion_init(void)
6313 int i;
6315 show_mptmod_ver(my_NAME, my_VERSION);
6316 printk(KERN_INFO COPYRIGHT "\n");
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;
6325 /* Register ourselves (mptbase) in order to facilitate
6326 * EventNotification handling.
6328 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6330 /* Register for hard reset handling callbacks.
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! */
6338 #ifdef CONFIG_PROC_FS
6339 (void) procmpt_create();
6340 #endif
6341 return 0;
6344 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6346 * fusion_exit - Perform driver unload cleanup.
6348 * This routine frees all resources associated with each MPT adapter
6349 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6351 static void __exit
6352 fusion_exit(void)
6355 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6357 mpt_reset_deregister(mpt_base_index);
6359 #ifdef CONFIG_PROC_FS
6360 procmpt_destroy();
6361 #endif
6364 module_init(fusion_init);
6365 module_exit(fusion_exit);