2 * linux/drivers/message/fusion/mptbase.c
3 * High performance SCSI + LAN / Fibre Channel device drivers.
4 * This is the Fusion MPT base driver which supports multiple
5 * (SCSI + LAN) specialized protocol drivers.
6 * For use with PCI chip/adapter(s):
7 * LSIFC9xx/LSI409xx Fibre Channel
8 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
11 * There are lots of people not mentioned below that deserve credit
12 * and thanks but won't get it here - sorry in advance that you
15 * This driver would not exist if not for Alan Cox's development
16 * of the linux i2o driver.
18 * A special thanks to Noah Romer (LSI Logic) for tons of work
19 * and tough debugging on the LAN driver, especially early on;-)
20 * And to Roger Hickerson (LSI Logic) for tirelessly supporting
21 * this driver project.
23 * A special thanks to Pamela Delaney (LSI Logic) for tons of work
24 * and countless enhancements while adding support for the 1030
25 * chip family. Pam has been instrumental in the development of
26 * of the 2.xx.xx series fusion drivers, and her contributions are
27 * far too numerous to hope to list in one place.
29 * All manner of help from Stephen Shirron (LSI Logic):
30 * low-level FC analysis, debug + various fixes in FCxx firmware,
31 * initial port to alpha platform, various driver code optimizations,
32 * being a faithful sounding board on all sorts of issues & ideas,
35 * A huge debt of gratitude is owed to David S. Miller (DaveM)
36 * for fixing much of the stupid and broken stuff in the early
37 * driver while porting to sparc64 platform. THANK YOU!
39 * Special thanks goes to the I2O LAN driver people at the
40 * University of Helsinki, who, unbeknownst to them, provided
41 * the inspiration and initial structure for this driver.
43 * A really huge debt of gratitude is owed to Eddie C. Dost
44 * for gobs of hard work fixing and optimizing LAN code.
47 * Copyright (c) 1999-2004 LSI Logic Corporation
48 * Originally By: Steven J. Ralston
49 * (mailto:sjralston1@netscape.net)
50 * (mailto:mpt_linux_developer@lsil.com)
52 * $Id: mptbase.c,v 1.126 2002/12/16 15:28:45 pdelaney Exp $
54 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
56 This program is free software; you can redistribute it and/or modify
57 it under the terms of the GNU General Public License as published by
58 the Free Software Foundation; version 2 of the License.
60 This program is distributed in the hope that it will be useful,
61 but WITHOUT ANY WARRANTY; without even the implied warranty of
62 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63 GNU General Public License for more details.
66 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
67 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
68 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
69 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
70 solely responsible for determining the appropriateness of using and
71 distributing the Program and assumes all risks associated with its
72 exercise of rights under this Agreement, including but not limited to
73 the risks and costs of program errors, damage to or loss of data,
74 programs or equipment, and unavailability or interruption of operations.
76 DISCLAIMER OF LIABILITY
77 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
78 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
79 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
80 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
81 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
82 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
83 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
85 You should have received a copy of the GNU General Public License
86 along with this program; if not, write to the Free Software
87 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
89 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
91 #include <linux/config.h>
92 #include <linux/version.h>
93 #include <linux/kernel.h>
94 #include <linux/module.h>
95 #include <linux/errno.h>
96 #include <linux/init.h>
97 #include <linux/slab.h>
98 #include <linux/types.h>
99 #include <linux/pci.h>
100 #include <linux/kdev_t.h>
101 #include <linux/blkdev.h>
102 #include <linux/delay.h>
103 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
106 #include <asm/mtrr.h>
109 #include <asm/irq.h> /* needed for __irq_itoa() proto */
114 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
115 #define my_NAME "Fusion MPT base driver"
116 #define my_VERSION MPT_LINUX_VERSION_COMMON
117 #define MYNAM "mptbase"
119 MODULE_AUTHOR(MODULEAUTHOR);
120 MODULE_DESCRIPTION(my_NAME);
121 MODULE_LICENSE("GPL");
124 * cmd line parameters
127 static int mfcounter = 0;
128 #define PRINT_MF_COUNT 20000
131 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
135 int mpt_lan_index = -1;
136 int mpt_stm_index = -1;
138 struct proc_dir_entry *mpt_proc_root_dir;
140 DmpServices_t *DmpService;
142 void *mpt_v_ASCQ_TablePtr;
143 const char **mpt_ScsiOpcodesPtr;
144 int mpt_ASCQ_TableSz;
147 #define WHOINIT_UNKNOWN 0xAA
149 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
153 /* Adapter lookup table */
154 MPT_ADAPTER *mpt_adapters[MPT_MAX_ADAPTERS];
155 static MPT_ADAPTER_TRACKER MptAdapters;
156 /* Callback lookup table */
157 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
158 /* Protocol driver class lookup table */
159 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
160 /* Event handler lookup table */
161 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
162 /* Reset handler lookup table */
163 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
164 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
166 static int FusionInitCalled = 0;
167 static int mpt_base_index = -1;
168 static int last_drv_idx = -1;
169 static int isense_idx = -1;
171 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
173 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
177 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
178 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
180 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
181 static void mpt_detect_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);
182 static void mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup);
183 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
185 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
186 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
187 //static u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
188 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
189 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
190 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
191 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
192 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
193 static int mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag);
194 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
195 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
196 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
197 static int PrimeIocFifos(MPT_ADAPTER *ioc);
198 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
199 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
200 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
201 static int GetLanConfigPages(MPT_ADAPTER *ioc);
202 static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
203 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
204 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
205 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
206 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
207 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
208 static void mpt_timer_expired(unsigned long data);
209 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
210 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
212 #ifdef CONFIG_PROC_FS
213 static int procmpt_create(void);
214 static int procmpt_destroy(void);
215 static int procmpt_summary_read(char *buf, char **start, off_t offset,
216 int request, int *eof, void *data);
217 static int procmpt_version_read(char *buf, char **start, off_t offset,
218 int request, int *eof, void *data);
219 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
220 int request, int *eof, void *data);
222 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
224 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
225 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
226 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
227 static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
229 /* module entry point */
230 static int __devinit mptbase_probe (struct pci_dev *, const struct pci_device_id *);
231 static void __devexit mptbase_remove(struct pci_dev *);
232 static void mptbase_shutdown(struct device * );
233 static int __init fusion_init (void);
234 static void __exit fusion_exit (void);
236 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
238 * more Private data...
240 #ifdef CONFIG_PROC_FS
241 struct _mpt_proc_list {
243 int (*f)(char *, char **, off_t, int, int *, void *);
244 } mpt_proc_list[] = {
245 { "summary", procmpt_summary_read},
246 { "version", procmpt_version_read},
248 #define MPT_PROC_ENTRIES (sizeof(mpt_proc_list)/sizeof(mpt_proc_list[0]))
250 struct _mpt_ioc_proc_list {
252 int (*f)(char *, char **, off_t, int, int *, void *);
253 } mpt_ioc_proc_list[] = {
254 { "info", procmpt_iocinfo_read},
255 { "summary", procmpt_summary_read},
257 #define MPT_IOC_PROC_ENTRIES (sizeof(mpt_ioc_proc_list)/sizeof(mpt_ioc_proc_list[0]))
261 /****************************************************************************
265 static struct pci_device_id mptbase_pci_table[] = {
266 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
267 PCI_ANY_ID, PCI_ANY_ID },
268 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
269 PCI_ANY_ID, PCI_ANY_ID },
270 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
271 PCI_ANY_ID, PCI_ANY_ID },
272 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
273 PCI_ANY_ID, PCI_ANY_ID },
274 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
275 PCI_ANY_ID, PCI_ANY_ID },
276 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
277 PCI_ANY_ID, PCI_ANY_ID },
278 {0} /* Terminating entry */
280 MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
282 #define CHIPREG_READ32(addr) readl(addr)
283 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
284 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
285 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
287 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
289 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
290 * @irq: irq number (not used)
291 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
292 * @r: pt_regs pointer (not used)
294 * This routine is registered via the request_irq() kernel API call,
295 * and handles all interrupts generated from a specific MPT adapter
296 * (also referred to as a IO Controller or IOC).
297 * This routine must clear the interrupt from the adapter and does
298 * so by reading the reply FIFO. Multiple replies may be processed
299 * per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
300 * which is currently set to 32 in mptbase.h.
302 * This routine handles register-level access of the adapter but
303 * dispatches (calls) a protocol-specific callback routine to handle
304 * the protocol-specific details of the MPT request completion.
307 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
322 * Verify ioc pointer is ok
326 iocCmp = mpt_adapter_find_first();
327 while ((ioc != iocCmp) && iocCmp)
328 iocCmp = mpt_adapter_find_next(iocCmp);
331 printk(KERN_WARNING "mpt_interrupt: Invalid ioc!\n");
338 * Drain the reply FIFO!
340 * NOTES: I've seen up to 10 replies processed in this loop, so far...
341 * Update: I've seen up to 9182 replies processed in this loop! ??
342 * Update: Limit ourselves to processing max of N replies
347 if ((pa = CHIPREG_READ32(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)
354 * Check for non-TURBO reply!
356 if (pa & MPI_ADDRESS_REPLY_A_BIT) {
360 /* non-TURBO reply! Hmmm, something may be up...
361 * Newest turbo reply mechanism; get address
362 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
365 /* Map DMA address of reply header to cpu address.
366 * pa is 32 bits - but the dma address may be 32 or 64 bits
367 * get offset based only only the low addresses
369 reply_dma_low = (pa = (pa << 1));
370 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
371 (reply_dma_low - ioc->reply_frames_low_dma));
373 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
374 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
375 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
377 dprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p\n",
379 DBG_DUMP_REPLY_FRAME(mr)
381 /* NEW! 20010301 -sralston
382 * Check/log IOC log info
384 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
385 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
386 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
387 if ((int)ioc->chip_type <= (int)FC929)
388 mpt_fc_log_info(ioc, log_info);
390 mpt_sp_log_info(ioc, log_info);
394 * Process turbo (context) reply...
396 dirqprintk((MYIOC_s_INFO_FMT "Got TURBO reply(=%08x)\n", ioc->name, pa));
397 type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
398 if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
399 cb_idx = mpt_stm_index;
401 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
402 } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
403 cb_idx = mpt_lan_index;
405 * BUG FIX! 20001218 -sralston
406 * Blind set of mf to NULL here was fatal
407 * after lan_reply says "freeme"
408 * Fix sort of combined with an optimization here;
409 * added explicit check for case where lan_reply
410 * was just returning 1 and doing nothing else.
411 * For this case skip the callback, but set up
412 * proper mf value first here:-)
414 if ((pa & 0x58000000) == 0x58000000) {
415 req_idx = pa & 0x0000FFFF;
416 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
419 * IMPORTANT! Invalidate the callback!
425 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
427 req_idx = pa & 0x0000FFFF;
428 cb_idx = (pa & 0x00FF0000) >> 16;
429 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
432 pa = 0; /* No reply flush! */
436 if ((int)ioc->chip_type > (int)FC929) {
437 /* Verify mf, mr are reasonable.
439 if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
440 || (mf < ioc->req_frames)) ) {
441 printk(MYIOC_s_WARN_FMT
442 "mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx);
447 if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth))
448 || (mr < ioc->reply_frames)) ) {
449 printk(MYIOC_s_WARN_FMT
450 "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr);
455 if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) {
456 printk(MYIOC_s_WARN_FMT
457 "mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx);
465 /* Check for (valid) IO callback! */
467 /* Do the callback! */
468 freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);
472 /* Flush (non-TURBO) reply with a WRITE! */
473 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
479 /* Put Request back on FreeQ! */
480 spin_lock_irqsave(&ioc->FreeQlock, flags);
481 Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
485 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
489 } /* drain reply FIFO */
494 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
496 * mpt_base_reply - MPT base driver's callback routine; all base driver
497 * "internal" request/reply processing is routed here.
498 * Currently used for EventNotification and EventAck handling.
499 * @ioc: Pointer to MPT_ADAPTER structure
500 * @mf: Pointer to original MPT request frame
501 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
503 * Returns 1 indicating original alloc'd request frame ptr
504 * should be freed, or 0 if it shouldn't.
507 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
512 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
515 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
516 printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n",
517 ioc->name, (void *)mf);
522 dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n",
527 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
528 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
529 DBG_DUMP_REQUEST_FRAME_HDR(mf)
532 func = reply->u.hdr.Function;
533 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
536 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
537 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
541 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
542 if (results != evHandlers) {
543 /* CHECKME! Any special handling needed here? */
544 dprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
545 ioc->name, evHandlers, results));
549 * Hmmm... It seems that EventNotificationReply is an exception
550 * to the rule of one reply per request.
552 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
555 #ifdef CONFIG_PROC_FS
556 // LogEvent(ioc, pEvReply);
559 } else if (func == MPI_FUNCTION_EVENT_ACK) {
560 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
562 } else if (func == MPI_FUNCTION_CONFIG ||
563 func == MPI_FUNCTION_TOOLBOX) {
567 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
568 ioc->name, mf, reply));
570 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
573 /* disable timer and remove from linked list */
574 del_timer(&pCfg->timer);
576 spin_lock_irqsave(&ioc->FreeQlock, flags);
577 Q_DEL_ITEM(&pCfg->linkage);
578 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
581 * If IOC Status is SUCCESS, save the header
582 * and set the status code to GOOD.
584 pCfg->status = MPT_CONFIG_ERROR;
586 ConfigReply_t *pReply = (ConfigReply_t *)reply;
589 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
590 dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
591 status, le32_to_cpu(pReply->IOCLogInfo)));
593 pCfg->status = status;
594 if (status == MPI_IOCSTATUS_SUCCESS) {
595 pCfg->hdr->PageVersion = pReply->Header.PageVersion;
596 pCfg->hdr->PageLength = pReply->Header.PageLength;
597 pCfg->hdr->PageNumber = pReply->Header.PageNumber;
598 pCfg->hdr->PageType = pReply->Header.PageType;
603 * Wake up the original calling thread
609 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
614 * Conditionally tell caller to free the original
615 * EventNotification/EventAck/unexpected request frame!
620 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
622 * mpt_register - Register protocol-specific main callback handler.
623 * @cbfunc: callback function pointer
624 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
626 * This routine is called by a protocol-specific driver (SCSI host,
627 * LAN, SCSI target) to register it's reply callback routine. Each
628 * protocol-specific driver must do this before it will be able to
629 * use any IOC resources, such as obtaining request frames.
631 * NOTES: The SCSI protocol driver currently calls this routine thrice
632 * in order to register separate callbacks; one for "normal" SCSI IO;
633 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
635 * Returns a positive integer valued "handle" in the
636 * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
637 * Any non-positive return value (including zero!) should be considered
638 * an error by the caller.
641 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
649 * Handle possibility of the mptscsih_detect() routine getting
650 * called *before* fusion_init!
652 if (!FusionInitCalled) {
653 dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n"));
655 * NOTE! We'll get recursion here, as fusion_init()
656 * calls mpt_register()!
664 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
665 * (slot/handle 0 is reserved!)
667 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
668 if (MptCallbacks[i] == NULL) {
669 MptCallbacks[i] = cbfunc;
670 MptDriverClass[i] = dclass;
671 MptEvHandlers[i] = NULL;
680 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
682 * mpt_deregister - Deregister a protocol drivers resources.
683 * @cb_idx: previously registered callback handle
685 * Each protocol-specific driver should call this routine when it's
686 * module is unloaded.
689 mpt_deregister(int cb_idx)
691 if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
692 MptCallbacks[cb_idx] = NULL;
693 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
694 MptEvHandlers[cb_idx] = NULL;
697 if (isense_idx != -1 && isense_idx <= cb_idx)
702 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
704 * mpt_event_register - Register protocol-specific event callback
706 * @cb_idx: previously registered (via mpt_register) callback handle
707 * @ev_cbfunc: callback function
709 * This routine can be called by one or more protocol-specific drivers
710 * if/when they choose to be notified of MPT events.
712 * Returns 0 for success.
715 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
717 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
720 MptEvHandlers[cb_idx] = ev_cbfunc;
724 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
726 * mpt_event_deregister - Deregister protocol-specific event callback
728 * @cb_idx: previously registered callback handle
730 * Each protocol-specific driver should call this routine
731 * when it does not (or can no longer) handle events,
732 * or when it's module is unloaded.
735 mpt_event_deregister(int cb_idx)
737 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
740 MptEvHandlers[cb_idx] = NULL;
743 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
745 * mpt_reset_register - Register protocol-specific IOC reset handler.
746 * @cb_idx: previously registered (via mpt_register) callback handle
747 * @reset_func: reset function
749 * This routine can be called by one or more protocol-specific drivers
750 * if/when they choose to be notified of IOC resets.
752 * Returns 0 for success.
755 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
757 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
760 MptResetHandlers[cb_idx] = reset_func;
764 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
766 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
767 * @cb_idx: previously registered callback handle
769 * Each protocol-specific driver should call this routine
770 * when it does not (or can no longer) handle IOC reset handling,
771 * or when it's module is unloaded.
774 mpt_reset_deregister(int cb_idx)
776 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
779 MptResetHandlers[cb_idx] = NULL;
782 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
784 * mpt_device_driver_register - Register device driver hooks
787 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
792 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
797 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
799 /* call per pci device probe entry point */
800 for(ioc = mpt_adapter_find_first(); ioc != NULL;
801 ioc = mpt_adapter_find_next(ioc)) {
802 if(dd_cbfunc->probe) {
803 error = dd_cbfunc->probe(ioc->pcidev,
804 ioc->pcidev->driver->id_table);
813 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
815 * mpt_device_driver_deregister - DeRegister device driver hooks
818 mpt_device_driver_deregister(int cb_idx)
820 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
823 MptDeviceDriverHandlers[cb_idx] = NULL;
827 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
829 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
830 * allocated per MPT adapter.
831 * @handle: Handle of registered MPT protocol driver
832 * @iocid: IOC unique identifier (integer)
834 * Returns pointer to a MPT request frame or %NULL if none are available
835 * or IOC is not active.
838 mpt_get_msg_frame(int handle, int iocid)
844 /* validate handle and ioc identifier */
845 iocp = mpt_adapters[iocid];
849 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
852 /* If interrupts are not attached, do not return a request frame */
856 spin_lock_irqsave(&iocp->FreeQlock, flags);
857 if (! Q_IS_EMPTY(&iocp->FreeQ)) {
860 mf = iocp->FreeQ.head;
861 Q_DEL_ITEM(&mf->u.frame.linkage);
862 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
863 req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
865 mf->u.frame.hwhdr.msgctxu.fld.req_idx =
866 cpu_to_le16(req_offset / iocp->req_sz);
867 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
874 spin_unlock_irqrestore(&iocp->FreeQlock, flags);
878 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", iocp->mfcnt, iocp->req_depth);
880 if (mfcounter == PRINT_MF_COUNT)
881 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", iocp->mfcnt, iocp->req_depth);
884 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
885 iocp->name, handle, iocid, mf));
889 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
891 * mpt_put_msg_frame - Send a protocol specific MPT request frame
893 * @handle: Handle of registered MPT protocol driver
894 * @iocid: IOC unique identifier (integer)
895 * @mf: Pointer to MPT request frame
897 * This routine posts a MPT request frame to the request post FIFO of a
898 * specific MPT adapter.
901 mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
905 iocp = mpt_adapters[iocid];
910 /* ensure values are reset properly! */
911 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
912 req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
914 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz);
915 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
917 #ifdef MPT_DEBUG_MSG_FRAME
919 u32 *m = mf->u.frame.hwhdr.__hdr;
922 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
924 n = iocp->req_sz/4 - 1;
927 for (ii=0; ii<=n; ii++) {
928 if (ii && ((ii%8)==0))
929 printk("\n" KERN_INFO " ");
930 printk(" %08x", le32_to_cpu(m[ii]));
936 mf_dma_addr = iocp->req_frames_low_dma + req_offset;
937 CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);
940 "mpt_put_msg_frame: Invalid iocid=%d\n", iocid);
945 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
947 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
948 * @handle: Handle of registered MPT protocol driver
949 * @iocid: IOC unique identifier (integer)
950 * @mf: Pointer to MPT request frame
952 * This routine places a MPT request frame back on the MPT adapter's
956 mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
961 iocp = mpt_adapters[iocid];
963 /* Put Request back on FreeQ! */
964 spin_lock_irqsave(&iocp->FreeQlock, flags);
965 Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
969 spin_unlock_irqrestore(&iocp->FreeQlock, flags);
973 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
975 * mpt_add_sge - Place a simple SGE at address pAddr.
976 * @pAddr: virtual address for SGE
977 * @flagslength: SGE flags and data transfer length
978 * @dma_addr: Physical address
980 * This routine places a MPT request frame back on the MPT adapter's
984 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
986 if (sizeof(dma_addr_t) == sizeof(u64)) {
987 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
988 u32 tmp = dma_addr & 0xFFFFFFFF;
990 pSge->FlagsLength = cpu_to_le32(flagslength);
991 pSge->Address.Low = cpu_to_le32(tmp);
992 tmp = (u32) ((u64)dma_addr >> 32);
993 pSge->Address.High = cpu_to_le32(tmp);
996 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
997 pSge->FlagsLength = cpu_to_le32(flagslength);
998 pSge->Address = cpu_to_le32(dma_addr);
1002 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1004 * mpt_add_chain - Place a chain SGE at address pAddr.
1005 * @pAddr: virtual address for SGE
1006 * @next: nextChainOffset value (u32's)
1007 * @length: length of next SGL segment
1008 * @dma_addr: Physical address
1010 * This routine places a MPT request frame back on the MPT adapter's
1014 mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
1016 if (sizeof(dma_addr_t) == sizeof(u64)) {
1017 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
1018 u32 tmp = dma_addr & 0xFFFFFFFF;
1020 pChain->Length = cpu_to_le16(length);
1021 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
1023 pChain->NextChainOffset = next;
1025 pChain->Address.Low = cpu_to_le32(tmp);
1026 tmp = (u32) ((u64)dma_addr >> 32);
1027 pChain->Address.High = cpu_to_le32(tmp);
1029 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
1030 pChain->Length = cpu_to_le16(length);
1031 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
1032 pChain->NextChainOffset = next;
1033 pChain->Address = cpu_to_le32(dma_addr);
1037 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1039 * mpt_send_handshake_request - Send MPT request via doorbell
1041 * @handle: Handle of registered MPT protocol driver
1042 * @iocid: IOC unique identifier (integer)
1043 * @reqBytes: Size of the request in bytes
1044 * @req: Pointer to MPT request frame
1045 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1047 * This routine is used exclusively to send MptScsiTaskMgmt
1048 * requests since they are required to be sent via doorbell handshake.
1050 * NOTE: It is the callers responsibility to byte-swap fields in the
1051 * request which are greater than 1 byte in size.
1053 * Returns 0 for success, non-zero for failure.
1056 mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req, int sleepFlag)
1061 iocp = mpt_adapters[iocid];
1066 /* State is known to be good upon entering
1067 * this function so issue the bus reset
1072 * Emulate what mpt_put_msg_frame() does /wrt to sanity
1073 * setting cb_idx/req_idx. But ONLY if this request
1074 * is in proper (pre-alloc'd) request buffer range...
1076 ii = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req);
1077 if (reqBytes >= 12 && ii >= 0 && ii < iocp->req_depth) {
1078 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
1079 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
1080 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
1083 /* Make sure there are no doorbells */
1084 CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
1086 CHIPREG_WRITE32(&iocp->chip->Doorbell,
1087 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
1088 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
1090 /* Wait for IOC doorbell int */
1091 if ((ii = WaitForDoorbellInt(iocp, 5, sleepFlag)) < 0) {
1095 /* Read doorbell and check for active bit */
1096 if (!(CHIPREG_READ32(&iocp->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
1099 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
1102 CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
1104 if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) {
1108 /* Send request via doorbell handshake */
1109 req_as_bytes = (u8 *) req;
1110 for (ii = 0; ii < reqBytes/4; ii++) {
1113 word = ((req_as_bytes[(ii*4) + 0] << 0) |
1114 (req_as_bytes[(ii*4) + 1] << 8) |
1115 (req_as_bytes[(ii*4) + 2] << 16) |
1116 (req_as_bytes[(ii*4) + 3] << 24));
1117 CHIPREG_WRITE32(&iocp->chip->Doorbell, word);
1118 if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) {
1124 if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0)
1129 /* Make sure there are no doorbells */
1130 CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
1136 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1138 * mpt_adapter_find_first - Find first MPT adapter pointer.
1140 * Returns first MPT adapter pointer or %NULL if no MPT adapters
1144 mpt_adapter_find_first(void)
1148 if (! Q_IS_EMPTY(&MptAdapters))
1149 this = MptAdapters.head;
1156 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1158 * mpt_adapter_find_next - Find next MPT adapter pointer.
1159 * @prev: Pointer to previous MPT adapter
1161 * Returns next MPT adapter pointer or %NULL if there are no more.
1164 mpt_adapter_find_next(MPT_ADAPTER *prev)
1168 if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head))
1177 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1179 * mpt_verify_adapter - Given a unique IOC identifier, set pointer to
1180 * the associated MPT adapter structure.
1181 * @iocid: IOC unique identifier (integer)
1182 * @iocpp: Pointer to pointer to IOC adapter
1184 * Returns iocid and sets iocpp.
1187 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1192 if (iocid >= MPT_MAX_ADAPTERS)
1195 p = mpt_adapters[iocid];
1203 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1205 * mptbase_probe - Install a PCI intelligent MPT adapter.
1206 * @pdev: Pointer to pci_dev structure
1208 * This routine performs all the steps necessary to bring the IOC of
1209 * a MPT adapter to a OPERATIONAL state. This includes registering
1210 * memory regions, registering the interrupt, and allocating request
1211 * and reply memory pools.
1213 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1216 * Returns 0 for success, non-zero for failure.
1218 * TODO: Add support for polled controllers
1220 static int __devinit
1221 mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1225 unsigned long mem_phys;
1231 u64 mask = 0xffffffffffffffffULL;
1235 if (pci_enable_device(pdev))
1238 if (!pci_set_dma_mask(pdev, mask)) {
1239 dprintk((KERN_INFO MYNAM
1240 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1241 } else if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {
1242 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1246 if (!pci_set_consistent_dma_mask(pdev, mask))
1247 dprintk((KERN_INFO MYNAM
1248 ": Using 64 bit consistent mask\n"));
1250 dprintk((KERN_INFO MYNAM
1251 ": Not using 64 bit consistent mask\n"));
1253 ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1255 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1258 memset(ioc, 0, sizeof(MPT_ADAPTER));
1259 ioc->alloc_total = sizeof(MPT_ADAPTER);
1260 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1261 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1265 ioc->diagPending = 0;
1266 spin_lock_init(&ioc->diagLock);
1268 /* Initialize the event logging.
1270 ioc->eventTypes = 0; /* None */
1271 ioc->eventContext = 0;
1272 ioc->eventLogSize = 0;
1279 ioc->cached_fw = NULL;
1281 /* Initilize SCSI Config Data structure
1283 memset(&ioc->spi_data, 0, sizeof(ScsiCfgData));
1285 /* Initialize the running configQ head.
1287 Q_INIT(&ioc->configQ, Q_ITEM);
1289 /* Find lookup slot. */
1290 for (ii=0; ii < MPT_MAX_ADAPTERS; ii++) {
1291 if (mpt_adapters[ii] == NULL) {
1292 ioc->id = ii; /* Assign adapter unique id (lookup) */
1296 if (ii == MPT_MAX_ADAPTERS) {
1297 printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", ii);
1302 mem_phys = msize = 0;
1304 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1305 if (pdev->PCI_BASEADDR_FLAGS(ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1306 /* Get I/O space! */
1307 port = pdev->PCI_BASEADDR_START(ii);
1308 psize = PCI_BASEADDR_SIZE(pdev,ii);
1311 mem_phys = pdev->PCI_BASEADDR_START(ii);
1312 msize = PCI_BASEADDR_SIZE(pdev,ii);
1316 ioc->mem_size = msize;
1318 if (ii == DEVICE_COUNT_RESOURCE) {
1319 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1324 dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1325 dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1328 /* Get logical ptr for PciMem0 space */
1329 /*mem = ioremap(mem_phys, msize);*/
1330 mem = ioremap(mem_phys, 0x100);
1332 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1337 dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1339 dprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1340 &ioc->facts, &ioc->pfacts[0]));
1342 ioc->mem_phys = mem_phys;
1343 ioc->chip = (SYSIF_REGS*)mem;
1345 /* Save Port IO values incase we need to do downloadboot */
1347 u8 *pmem = (u8*)port;
1348 ioc->pio_mem_phys = port;
1349 ioc->pio_chip = (SYSIF_REGS*)pmem;
1352 ioc->chip_type = FCUNK;
1353 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1354 ioc->chip_type = FC929;
1355 ioc->prod_name = "LSIFC929";
1357 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1358 ioc->chip_type = FC919;
1359 ioc->prod_name = "LSIFC919";
1361 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1362 ioc->chip_type = FC929X;
1363 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1364 if (revision < XL_929) {
1365 ioc->prod_name = "LSIFC929X";
1366 /* 929X Chip Fix. Set Split transactions level
1367 * for PCIX. Set MOST bits to zero.
1369 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1371 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1373 ioc->prod_name = "LSIFC929XL";
1374 /* 929XL Chip Fix. Set MMRBC to 0x08.
1376 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1378 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1381 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1382 ioc->chip_type = FC919X;
1383 ioc->prod_name = "LSIFC919X";
1384 /* 919X Chip Fix. Set Split transactions level
1385 * for PCIX. Set MOST bits to zero.
1387 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1389 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1391 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1392 ioc->chip_type = C1030;
1393 ioc->prod_name = "LSI53C1030";
1394 /* 1030 Chip Fix. Disable Split transactions
1395 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1397 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1398 if (revision < C0_1030) {
1399 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1401 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1404 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1405 ioc->chip_type = C1035;
1406 ioc->prod_name = "LSI53C1035";
1409 sprintf(ioc->name, "ioc%d", ioc->id);
1411 Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
1412 spin_lock_init(&ioc->FreeQlock);
1415 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1417 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1419 /* tack onto tail of our MPT adapter list */
1420 Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER);
1422 /* Set lookup ptr. */
1423 mpt_adapters[ioc->id] = ioc;
1427 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1431 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n",
1432 ioc->name, pdev->irq);
1434 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
1435 ioc->name, __irq_itoa(pdev->irq));
1438 mpt_adapters[ioc->id] = NULL;
1444 ioc->pci_irq = pdev->irq;
1446 pci_set_master(pdev); /* ?? */
1447 pci_set_drvdata(pdev, ioc);
1450 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
1452 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));
1456 /* NEW! 20010220 -sralston
1457 * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1459 if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030)
1460 || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X))
1461 mpt_detect_bound_ports(ioc, pdev);
1463 if ((r = mpt_do_ioc_recovery(ioc,
1464 MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) {
1465 printk(KERN_WARNING MYNAM
1466 ": WARNING - %s did not initialize properly! (%d)\n",
1470 mpt_adapters[ioc->id] = NULL;
1471 free_irq(ioc->pci_irq, ioc);
1474 pci_set_drvdata(pdev, NULL);
1478 /* call per device driver probe entry point */
1479 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1480 if(MptDeviceDriverHandlers[ii] &&
1481 MptDeviceDriverHandlers[ii]->probe) {
1482 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1489 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1491 * mptbase_remove - Remove a PCI intelligent MPT adapter.
1492 * @pdev: Pointer to pci_dev structure
1496 static void __devexit
1497 mptbase_remove(struct pci_dev *pdev)
1499 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1502 /* call per device driver remove entry point */
1503 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1504 if(MptDeviceDriverHandlers[ii] &&
1505 MptDeviceDriverHandlers[ii]->remove) {
1506 MptDeviceDriverHandlers[ii]->remove(pdev);
1510 /* Disable interrupts! */
1511 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1514 mpt_sync_irq(pdev->irq);
1516 /* Clear any lingering interrupt */
1517 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1519 CHIPREG_READ32(&ioc->chip->IntStatus);
1522 mpt_adapter_dispose(ioc);
1524 pci_set_drvdata(pdev, NULL);
1527 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1529 * mptbase_shutdown -
1533 mptbase_shutdown(struct device * dev)
1537 /* call per device driver shutdown entry point */
1538 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1539 if(MptDeviceDriverHandlers[ii] &&
1540 MptDeviceDriverHandlers[ii]->shutdown) {
1541 MptDeviceDriverHandlers[ii]->shutdown(dev);
1548 /**************************************************************************
1552 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1554 * mptbase_suspend - Fusion MPT base driver suspend routine.
1559 mptbase_suspend(struct pci_dev *pdev, u32 state)
1562 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1568 device_state=1; /* D1 */;
1572 device_state=3; /* D3 */;
1575 return -EAGAIN /*FIXME*/;
1579 printk(MYIOC_s_INFO_FMT
1580 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1581 ioc->name, pdev, pci_name(pdev), device_state);
1583 /* call per device driver suspend entry point */
1584 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1585 if(MptDeviceDriverHandlers[ii] &&
1586 MptDeviceDriverHandlers[ii]->suspend) {
1587 MptDeviceDriverHandlers[ii]->suspend(pdev, state);
1591 pci_save_state(pdev, ioc->PciState);
1593 /* put ioc into READY_STATE */
1594 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1595 printk(MYIOC_s_ERR_FMT
1596 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1599 /* disable interrupts */
1600 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1603 /* Clear any lingering interrupt */
1604 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1606 pci_disable_device(pdev);
1607 pci_set_power_state(pdev, device_state);
1612 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1614 * mptbase_resume - Fusion MPT base driver resume routine.
1619 mptbase_resume(struct pci_dev *pdev)
1621 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1622 u32 device_state = pdev->current_state;
1626 printk(MYIOC_s_INFO_FMT
1627 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1628 ioc->name, pdev, pci_name(pdev), device_state);
1630 pci_set_power_state(pdev, 0);
1631 pci_restore_state(pdev, ioc->PciState);
1632 pci_enable_device(pdev);
1634 /* enable interrupts */
1635 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1638 /* F/W not running */
1639 if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
1640 /* enable domain validation flags */
1641 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
1642 ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
1646 printk(MYIOC_s_INFO_FMT
1647 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1649 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1650 CHIPREG_READ32(&ioc->chip->Doorbell));
1652 /* bring ioc to operational state */
1653 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1654 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1655 printk(MYIOC_s_INFO_FMT
1656 "pci-resume: Cannot recover, error:[%x]\n",
1657 ioc->name, recovery_state);
1659 printk(MYIOC_s_INFO_FMT
1660 "pci-resume: success\n", ioc->name);
1663 /* call per device driver resume entry point */
1664 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1665 if(MptDeviceDriverHandlers[ii] &&
1666 MptDeviceDriverHandlers[ii]->resume) {
1667 MptDeviceDriverHandlers[ii]->resume(pdev);
1675 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1677 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1678 * @ioc: Pointer to MPT adapter structure
1679 * @reason: Event word / reason
1680 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1682 * This routine performs all the steps necessary to bring the IOC
1683 * to a OPERATIONAL state.
1685 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1690 * -1 if failed to get board READY
1691 * -2 if READY but IOCFacts Failed
1692 * -3 if READY but PrimeIOCFifos Failed
1693 * -4 if READY but IOCInit Failed
1696 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1698 int hard_reset_done = 0;
1699 int alt_ioc_ready = 0;
1705 int reset_alt_ioc_active = 0;
1707 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1708 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1710 /* Disable reply interrupts (also blocks FreeQ) */
1711 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1715 if (ioc->alt_ioc->active)
1716 reset_alt_ioc_active = 1;
1718 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1719 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1720 ioc->alt_ioc->active = 0;
1724 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1727 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1728 if (hard_reset_done == -4) {
1729 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1732 if (reset_alt_ioc_active && ioc->alt_ioc) {
1733 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1734 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1735 ioc->alt_ioc->name));
1736 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
1737 ioc->alt_ioc->active = 1;
1741 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1747 /* hard_reset_done = 0 if a soft reset was performed
1748 * and 1 if a hard reset was performed.
1750 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1751 if ((r = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1754 printk(KERN_WARNING MYNAM
1755 ": alt-%s: (%d) Not ready WARNING!\n",
1756 ioc->alt_ioc->name, r);
1759 /* Get IOC facts! Allow 1 retry */
1760 if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0)
1761 r = GetIocFacts(ioc, sleepFlag, reason);
1765 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1766 MptDisplayIocCapabilities(ioc);
1769 if (alt_ioc_ready) {
1770 if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1771 /* Retry - alt IOC was initialized once
1773 r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1777 reset_alt_ioc_active = 0;
1778 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1779 MptDisplayIocCapabilities(ioc->alt_ioc);
1783 /* Prime reply & request queues!
1784 * (mucho alloc's) Must be done prior to
1785 * init as upper addresses are needed for init.
1786 * If fails, continue with alt-ioc processing
1788 if ((ret == 0) && ((r = PrimeIocFifos(ioc)) != 0))
1791 /* May need to check/upload firmware & data here!
1792 * If fails, continue with alt-ioc processing
1794 if ((ret == 0) && ((r = SendIocInit(ioc, sleepFlag)) != 0))
1797 if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1798 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1799 ioc->alt_ioc->name, r);
1801 reset_alt_ioc_active = 0;
1804 if (alt_ioc_ready) {
1805 if ((r = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1807 reset_alt_ioc_active = 0;
1808 printk(KERN_WARNING MYNAM
1809 ": alt-%s: (%d) init failure WARNING!\n",
1810 ioc->alt_ioc->name, r);
1814 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1815 if (ioc->upload_fw) {
1816 ddlprintk((MYIOC_s_INFO_FMT
1817 "firmware upload required!\n", ioc->name));
1819 /* Controller is not operational, cannot do upload
1822 r = mpt_do_upload(ioc, sleepFlag);
1824 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1827 /* Handle the alt IOC too */
1828 if ((alt_ioc_ready) && (ioc->alt_ioc->upload_fw)){
1829 ddlprintk((MYIOC_s_INFO_FMT
1830 "Alt-ioc firmware upload required!\n",
1832 r = mpt_do_upload(ioc->alt_ioc, sleepFlag);
1834 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1840 /* Enable! (reply interrupt) */
1841 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1845 if (reset_alt_ioc_active && ioc->alt_ioc) {
1846 /* (re)Enable alt-IOC! (reply interrupt) */
1847 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1848 ioc->alt_ioc->name));
1849 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
1850 ioc->alt_ioc->active = 1;
1853 /* NEW! 20010120 -sralston
1854 * Enable MPT base driver management of EventNotification
1855 * and EventAck handling.
1857 if ((ret == 0) && (!ioc->facts.EventState))
1858 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1860 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1861 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1863 /* (Bugzilla:fibrebugs, #513)
1864 * Bug fix (part 2)! 20010905 -sralston
1865 * Add additional "reason" check before call to GetLanConfigPages
1866 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1867 * recursive scenario; GetLanConfigPages times out, timer expired
1868 * routine calls HardResetHandler, which calls into here again,
1869 * and we try GetLanConfigPages again...
1871 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1872 if ((int)ioc->chip_type <= (int)FC929) {
1874 * Pre-fetch FC port WWN and stuff...
1875 * (FCPortPage0_t stuff)
1877 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1878 (void) GetFcPortPage0(ioc, ii);
1881 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1882 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1884 * Pre-fetch the ports LAN MAC address!
1885 * (LANPage1_t stuff)
1887 (void) GetLanConfigPages(ioc);
1890 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1891 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1892 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1897 /* Get NVRAM and adapter maximums from SPP 0 and 2
1899 mpt_GetScsiPortSettings(ioc, 0);
1901 /* Get version and length of SDP 1
1903 mpt_readScsiDevicePageHeaders(ioc, 0);
1907 if (ioc->facts.MsgVersion >= 0x0102)
1908 mpt_findImVolumes(ioc);
1910 /* Check, and possibly reset, the coalescing value
1912 mpt_read_ioc_pg_1(ioc);
1914 mpt_read_ioc_pg_4(ioc);
1917 GetIoUnitPage2(ioc);
1921 * Call each currently registered protocol IOC reset handler
1922 * with post-reset indication.
1923 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1924 * MptResetHandlers[] registered yet.
1926 if (hard_reset_done) {
1928 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1929 if ((ret == 0) && MptResetHandlers[ii]) {
1930 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1932 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
1936 if (alt_ioc_ready && MptResetHandlers[ii]) {
1937 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1938 ioc->name, ioc->alt_ioc->name, ii));
1939 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
1943 /* FIXME? Examine results here? */
1949 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1951 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1952 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1953 * 929X, 1030 or 1035.
1954 * @ioc: Pointer to MPT adapter structure
1955 * @pdev: Pointer to (struct pci_dev) structure
1957 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1958 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1961 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1963 MPT_ADAPTER *ioc_srch = mpt_adapter_find_first();
1964 unsigned int match_lo, match_hi;
1966 match_lo = pdev->devfn-1;
1967 match_hi = pdev->devfn+1;
1968 dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
1969 ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi));
1971 while (ioc_srch != NULL) {
1972 struct pci_dev *_pcidev = ioc_srch->pcidev;
1974 if ((_pcidev->device == pdev->device) &&
1975 (_pcidev->bus->number == pdev->bus->number) &&
1976 (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
1977 /* Paranoia checks */
1978 if (ioc->alt_ioc != NULL) {
1979 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1980 ioc->name, ioc->alt_ioc->name);
1982 } else if (ioc_srch->alt_ioc != NULL) {
1983 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1984 ioc_srch->name, ioc_srch->alt_ioc->name);
1987 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1988 ioc->name, ioc_srch->name));
1989 ioc_srch->alt_ioc = ioc;
1990 ioc->alt_ioc = ioc_srch;
1993 ioc_srch = mpt_adapter_find_next(ioc_srch);
1997 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1999 * mpt_adapter_disable - Disable misbehaving MPT adapter.
2000 * @this: Pointer to MPT adapter structure
2001 * @free: Free up alloc'd reply, request, etc.
2004 mpt_adapter_disable(MPT_ADAPTER *this, int freeup)
2011 /* Disable the FW */
2012 state = mpt_GetIocState(this, 1);
2013 if (state == MPI_IOC_STATE_OPERATIONAL) {
2014 SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP);
2017 if (this->cached_fw != NULL) {
2018 ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n"));
2020 if ((ret = mpt_downloadboot(this, NO_SLEEP)) < 0) {
2021 printk(KERN_WARNING MYNAM
2022 ": firmware downloadboot failure (%d)!\n", ret);
2026 /* Disable adapter interrupts! */
2027 CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
2029 /* Clear any lingering interrupt */
2030 CHIPREG_WRITE32(&this->chip->IntStatus, 0);
2032 if (freeup && this->fifo_pool != NULL) {
2033 pci_free_consistent(this->pcidev,
2035 this->fifo_pool, this->fifo_pool_dma);
2036 this->reply_frames = NULL;
2037 this->reply_alloc = NULL;
2038 this->req_frames = NULL;
2039 this->req_alloc = NULL;
2040 this->chain_alloc = NULL;
2041 this->fifo_pool = NULL;
2042 this->alloc_total -= this->fifo_pool_sz;
2044 if (freeup && this->sense_buf_pool != NULL) {
2045 sz = (this->req_depth * MPT_SENSE_BUFFER_ALLOC);
2046 pci_free_consistent(this->pcidev, sz,
2047 this->sense_buf_pool, this->sense_buf_pool_dma);
2048 this->sense_buf_pool = NULL;
2049 this->alloc_total -= sz;
2052 if (freeup && this->events != NULL){
2053 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2054 kfree(this->events);
2055 this->events = NULL;
2056 this->alloc_total -= sz;
2059 if (freeup && this->cached_fw != NULL) {
2062 while ((ii < this->num_fw_frags) && (this->cached_fw[ii]!= NULL)) {
2063 sz = this->cached_fw[ii]->size;
2064 pci_free_consistent(this->pcidev, sz,
2065 this->cached_fw[ii]->fw, this->cached_fw[ii]->fw_dma);
2066 this->cached_fw[ii]->fw = NULL;
2067 this->alloc_total -= sz;
2069 kfree(this->cached_fw[ii]);
2070 this->cached_fw[ii] = NULL;
2071 this->alloc_total -= sizeof(fw_image_t);
2076 kfree(this->cached_fw);
2077 this->cached_fw = NULL;
2078 sz = this->num_fw_frags * sizeof(void *);
2079 this->alloc_total -= sz;
2082 if (freeup && this->spi_data.nvram != NULL) {
2083 kfree(this->spi_data.nvram);
2084 this->spi_data.nvram = NULL;
2087 if (freeup && this->spi_data.pIocPg3 != NULL) {
2088 kfree(this->spi_data.pIocPg3);
2089 this->spi_data.pIocPg3 = NULL;
2092 if (freeup && this->spi_data.pIocPg4 != NULL) {
2093 sz = this->spi_data.IocPg4Sz;
2094 pci_free_consistent(this->pcidev, sz,
2095 this->spi_data.pIocPg4,
2096 this->spi_data.IocPg4_dma);
2097 this->spi_data.pIocPg4 = NULL;
2098 this->alloc_total -= sz;
2103 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2105 * mpt_adapter_dispose - Free all resources associated with a MPT
2107 * @this: Pointer to MPT adapter structure
2109 * This routine unregisters h/w resources and frees all alloc'd memory
2110 * associated with a MPT adapter structure.
2113 mpt_adapter_dispose(MPT_ADAPTER *this)
2116 int sz_first, sz_last;
2118 sz_first = this->alloc_total;
2120 if (this->alt_ioc != NULL) {
2121 this->alt_ioc->alt_ioc = NULL;
2122 this->alt_ioc = NULL;
2125 mpt_adapter_disable(this, 1);
2127 if (this->pci_irq != -1) {
2128 free_irq(this->pci_irq, this);
2132 if (this->memmap != NULL)
2133 iounmap((u8 *) this->memmap);
2135 #if defined(CONFIG_MTRR) && 0
2136 if (this->mtrr_reg > 0) {
2137 mtrr_del(this->mtrr_reg, 0, 0);
2138 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name));
2142 /* Zap the adapter lookup ptr! */
2143 mpt_adapters[this->id] = NULL;
2145 sz_last = this->alloc_total;
2146 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2147 this->name, sz_first-sz_last+(int)sizeof(*this), sz_first));
2152 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2154 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2155 * @ioc: Pointer to MPT adapter structure
2158 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2162 printk(KERN_INFO "%s: ", ioc->name);
2163 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2164 printk("%s: ", ioc->prod_name+3);
2165 printk("Capabilities={");
2167 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2168 printk("Initiator");
2172 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2173 printk("%sTarget", i ? "," : "");
2177 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2178 printk("%sLAN", i ? "," : "");
2184 * This would probably evoke more questions than it's worth
2186 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2187 printk("%sLogBusAddr", i ? "," : "");
2195 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2197 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2198 * @ioc: Pointer to MPT_ADAPTER structure
2199 * @force: Force hard KickStart of IOC
2200 * @sleepFlag: Specifies whether the process can sleep
2203 * 1 - DIAG reset and READY
2204 * 0 - READY initially OR soft reset and READY
2205 * -1 - Any failure on KickStart
2206 * -2 - Msg Unit Reset Failed
2207 * -3 - IO Unit Reset Failed
2208 * -4 - IOC owned by a PEER
2211 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2216 int hard_reset_done = 0;
2221 /* Get current [raw] IOC state */
2222 ioc_state = mpt_GetIocState(ioc, 0);
2223 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2226 * Check to see if IOC got left/stuck in doorbell handshake
2227 * grip of death. If so, hard reset the IOC.
2229 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2231 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2235 /* Is it already READY? */
2236 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) {
2237 if ((int)ioc->chip_type <= (int)FC929)
2240 /* Workaround from broken 1030 FW.
2241 * Force a diagnostic reset if fails.
2243 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2251 * Check to see if IOC is in FAULT state.
2253 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2255 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2257 printk(KERN_WARNING " FAULT code = %04xh\n",
2258 ioc_state & MPI_DOORBELL_DATA_MASK);
2262 * Hmmm... Did it get left operational?
2264 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2265 dprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
2269 * If PCI Peer, exit.
2270 * Else, if no fault conditions are present, issue a MessageUnitReset
2271 * Else, fall through to KickStart case
2273 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2274 dprintk((KERN_WARNING MYNAM
2275 ": whoinit 0x%x\n statefault %d force %d\n",
2276 whoinit, statefault, force));
2277 if (whoinit == MPI_WHOINIT_PCI_PEER)
2280 if ((statefault == 0 ) && (force == 0)) {
2281 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2288 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2289 if (hard_reset_done < 0)
2293 * Loop here waiting for IOC to come READY.
2296 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
2298 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2299 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2301 * BIOS or previous driver load left IOC in OP state.
2302 * Reset messaging FIFOs.
2304 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2305 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2308 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2310 * Something is wrong. Try to get IOC back
2313 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2314 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2321 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2322 ioc->name, (ii+5)/HZ);
2326 if (sleepFlag == CAN_SLEEP) {
2327 set_current_state(TASK_INTERRUPTIBLE);
2328 schedule_timeout(1);
2330 mdelay (1); /* 1 msec delay */
2335 if (statefault < 3) {
2336 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2338 statefault==1 ? "stuck handshake" : "IOC FAULT");
2341 return hard_reset_done;
2344 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2346 * mpt_GetIocState - Get the current state of a MPT adapter.
2347 * @ioc: Pointer to MPT_ADAPTER structure
2348 * @cooked: Request raw or cooked IOC state
2350 * Returns all IOC Doorbell register bits if cooked==0, else just the
2351 * Doorbell bits in MPI_IOC_STATE_MASK.
2354 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2359 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2360 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2361 sc = s & MPI_IOC_STATE_MASK;
2364 ioc->last_state = sc;
2366 return cooked ? sc : s;
2369 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2371 * GetIocFacts - Send IOCFacts request to MPT adapter.
2372 * @ioc: Pointer to MPT_ADAPTER structure
2373 * @sleepFlag: Specifies whether the process can sleep
2374 * @reason: If recovery, only update facts.
2376 * Returns 0 for success, non-zero for failure.
2379 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2381 IOCFacts_t get_facts;
2382 IOCFactsReply_t *facts;
2388 /* IOC *must* NOT be in RESET state! */
2389 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2390 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2396 facts = &ioc->facts;
2398 /* Destination (reply area)... */
2399 reply_sz = sizeof(*facts);
2400 memset(facts, 0, reply_sz);
2402 /* Request area (get_facts on the stack right now!) */
2403 req_sz = sizeof(get_facts);
2404 memset(&get_facts, 0, req_sz);
2406 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2407 /* Assert: All other get_facts fields are zero! */
2409 dprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name));
2411 /* No non-zero fields in the get_facts request are greater than
2412 * 1 byte in size, so we can just fire it off as is.
2414 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2415 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2420 * Now byte swap (GRRR) the necessary fields before any further
2421 * inspection of reply contents.
2423 * But need to do some sanity checks on MsgLength (byte) field
2424 * to make sure we don't zero IOC's req_sz!
2426 /* Did we get a valid reply? */
2427 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2428 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2430 * If not been here, done that, save off first WhoInit value
2432 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2433 ioc->FirstWhoInit = facts->WhoInit;
2436 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2437 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2438 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2439 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2440 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2441 status = facts->IOCStatus & MPI_IOCSTATUS_MASK;
2442 /* CHECKME! IOCStatus, IOCLogInfo */
2444 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2445 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2448 * FC f/w version changed between 1.1 and 1.2
2449 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2450 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2452 if (facts->MsgVersion < 0x0102) {
2454 * Handle old FC f/w style, convert to new...
2456 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2457 facts->FWVersion.Word =
2458 ((oldv<<12) & 0xFF000000) |
2459 ((oldv<<8) & 0x000FFF00);
2461 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2463 facts->ProductID = le16_to_cpu(facts->ProductID);
2464 facts->CurrentHostMfaHighAddr =
2465 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2466 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2467 facts->CurrentSenseBufferHighAddr =
2468 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2469 facts->CurReplyFrameSize =
2470 le16_to_cpu(facts->CurReplyFrameSize);
2473 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2474 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2475 * to 14 in MPI-1.01.0x.
2477 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2478 facts->MsgVersion > 0x0100) {
2479 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2482 if (!facts->RequestFrameSize) {
2483 /* Something is wrong! */
2484 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2489 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2491 * Set values for this IOC's request & reply frame sizes,
2492 * and request & reply queue depths...
2494 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2495 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2496 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2497 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2499 dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2500 ioc->name, ioc->reply_sz, ioc->reply_depth));
2501 dprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2502 ioc->name, ioc->req_sz, ioc->req_depth));
2504 /* Get port facts! */
2505 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2509 printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply!\n",
2517 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2519 * GetPortFacts - Send PortFacts request to MPT adapter.
2520 * @ioc: Pointer to MPT_ADAPTER structure
2521 * @portnum: Port number
2522 * @sleepFlag: Specifies whether the process can sleep
2524 * Returns 0 for success, non-zero for failure.
2527 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2529 PortFacts_t get_pfacts;
2530 PortFactsReply_t *pfacts;
2535 /* IOC *must* NOT be in RESET state! */
2536 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2537 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2543 pfacts = &ioc->pfacts[portnum];
2545 /* Destination (reply area)... */
2546 reply_sz = sizeof(*pfacts);
2547 memset(pfacts, 0, reply_sz);
2549 /* Request area (get_pfacts on the stack right now!) */
2550 req_sz = sizeof(get_pfacts);
2551 memset(&get_pfacts, 0, req_sz);
2553 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2554 get_pfacts.PortNumber = portnum;
2555 /* Assert: All other get_pfacts fields are zero! */
2557 dprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2558 ioc->name, portnum));
2560 /* No non-zero fields in the get_pfacts request are greater than
2561 * 1 byte in size, so we can just fire it off as is.
2563 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2564 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2568 /* Did we get a valid reply? */
2570 /* Now byte swap the necessary fields in the response. */
2571 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2572 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2573 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2574 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2575 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2576 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2577 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2578 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2579 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2584 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2586 * SendIocInit - Send IOCInit request to MPT adapter.
2587 * @ioc: Pointer to MPT_ADAPTER structure
2588 * @sleepFlag: Specifies whether the process can sleep
2590 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2592 * Returns 0 for success, non-zero for failure.
2595 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2598 MPIDefaultReply_t init_reply;
2604 memset(&ioc_init, 0, sizeof(ioc_init));
2605 memset(&init_reply, 0, sizeof(init_reply));
2607 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2608 /* ioc_init.ChainOffset = 0; */
2609 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2610 /* ioc_init.Flags = 0; */
2612 /* If we are in a recovery mode and we uploaded the FW image,
2613 * then this pointer is not NULL. Skip the upload a second time.
2614 * Set this flag if cached_fw set for either IOC.
2618 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
2619 if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw))
2620 ioc_init.Flags = MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE;
2624 ddlprintk((MYIOC_s_INFO_FMT "flags %d, upload_fw %d \n",
2625 ioc->name, ioc_init.Flags, ioc->upload_fw));
2627 if ((int)ioc->chip_type <= (int)FC929) {
2628 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2630 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2632 ioc_init.MaxBuses = MPT_MAX_BUS;
2634 /* ioc_init.MsgFlags = 0; */
2635 /* ioc_init.MsgContext = cpu_to_le32(0x00000000); */
2636 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2638 ioc->facts.RequestFrameSize = ioc_init.ReplyFrameSize;
2640 if (sizeof(dma_addr_t) == sizeof(u64)) {
2641 /* Save the upper 32-bits of the request
2642 * (reply) and sense buffers.
2644 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32));
2645 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2647 /* Force 32-bit addressing */
2648 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2649 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2652 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2653 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2655 dprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2656 ioc->name, &ioc_init));
2658 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2659 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2663 /* No need to byte swap the multibyte fields in the reply
2664 * since we don't even look at it's contents.
2667 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0)
2670 /* YIKES! SUPER IMPORTANT!!!
2671 * Poll IocState until _OPERATIONAL while IOC is doing
2672 * LoopInit and TargetDiscovery!
2675 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2676 state = mpt_GetIocState(ioc, 1);
2677 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2678 if (sleepFlag == CAN_SLEEP) {
2679 set_current_state(TASK_INTERRUPTIBLE);
2680 schedule_timeout(1);
2686 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2687 ioc->name, (count+5)/HZ);
2691 state = mpt_GetIocState(ioc, 1);
2694 dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2700 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2702 * SendPortEnable - Send PortEnable request to MPT adapter port.
2703 * @ioc: Pointer to MPT_ADAPTER structure
2704 * @portnum: Port number to enable
2705 * @sleepFlag: Specifies whether the process can sleep
2707 * Send PortEnable to bring IOC to OPERATIONAL state.
2709 * Returns 0 for success, non-zero for failure.
2712 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2714 PortEnable_t port_enable;
2715 MPIDefaultReply_t reply_buf;
2720 /* Destination... */
2721 reply_sz = sizeof(MPIDefaultReply_t);
2722 memset(&reply_buf, 0, reply_sz);
2724 req_sz = sizeof(PortEnable_t);
2725 memset(&port_enable, 0, req_sz);
2727 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2728 port_enable.PortNumber = portnum;
2729 /* port_enable.ChainOffset = 0; */
2730 /* port_enable.MsgFlags = 0; */
2731 /* port_enable.MsgContext = 0; */
2733 dprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2734 ioc->name, portnum, &port_enable));
2736 /* RAID FW may take a long time to enable
2738 if ((int)ioc->chip_type <= (int)FC929) {
2739 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
2740 reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag);
2742 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
2743 reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
2749 /* We do not even look at the reply, so we need not
2750 * swap the multi-byte fields.
2757 * Inputs: size - total FW bytes
2758 * Outputs: frags - number of fragments needed
2759 * Return NULL if failed.
2762 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz)
2764 fw_image_t **cached_fw;
2767 int alloc_total = 0;
2768 int bytes_left, bytes, num_frags;
2773 sz = ioc->num_fw_frags * sizeof(void *);
2774 mem = kmalloc(sz, GFP_ATOMIC);
2779 cached_fw = (fw_image_t **)mem;
2782 /* malloc fragment memory
2783 * fw_image_t struct and dma for fw data
2789 while((bytes_left) && (num_frags < ioc->num_fw_frags)) {
2790 if (cached_fw[ii] == NULL) {
2791 mem = kmalloc(sizeof(fw_image_t), GFP_ATOMIC);
2795 memset(mem, 0, sizeof(fw_image_t));
2796 cached_fw[ii] = (fw_image_t *)mem;
2797 alloc_total += sizeof(fw_image_t);
2800 mem = pci_alloc_consistent(ioc->pcidev, bytes, &fw_dma);
2802 if (bytes > 0x10000)
2804 else if (bytes > 0x8000)
2806 else if (bytes > 0x4000)
2808 else if (bytes > 0x2000)
2810 else if (bytes > 0x1000)
2818 cached_fw[ii]->fw = mem;
2819 cached_fw[ii]->fw_dma = fw_dma;
2820 cached_fw[ii]->size = bytes;
2821 memset(mem, 0, bytes);
2822 alloc_total += bytes;
2824 bytes_left -= bytes;
2833 mpt_free_fw_memory(ioc, cached_fw);
2838 *alloc_sz = alloc_total;
2840 return (void *) cached_fw;
2844 * If alt_img is NULL, delete from ioc structure.
2845 * Else, delete a secondary image in same format.
2848 mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img)
2850 fw_image_t **cached_fw;
2853 int alloc_freed = 0;
2855 if (alt_img != NULL)
2856 cached_fw = alt_img;
2858 cached_fw = ioc->cached_fw;
2860 if (cached_fw == NULL)
2864 while ((ii < ioc->num_fw_frags) && (cached_fw[ii]!= NULL)) {
2865 sz = cached_fw[ii]->size;
2867 pci_free_consistent(ioc->pcidev, sz,
2868 cached_fw[ii]->fw, cached_fw[ii]->fw_dma);
2870 cached_fw[ii]->fw = NULL;
2873 kfree(cached_fw[ii]);
2874 cached_fw[ii] = NULL;
2875 alloc_freed += sizeof(fw_image_t);
2882 sz = ioc->num_fw_frags * sizeof(void *);
2885 if (alt_img == NULL)
2886 ioc->alloc_total -= alloc_freed;
2892 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2894 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2895 * @ioc: Pointer to MPT_ADAPTER structure
2896 * @sleepFlag: Specifies whether the process can sleep
2898 * Returns 0 for success, >0 for handshake failure
2899 * <0 for fw upload failure.
2901 * Remark: If bound IOC and a successful FWUpload was performed
2902 * on the bound IOC, the second image is discarded
2903 * and memory is free'd. Both channels must upload to prevent
2904 * IOC from running in degraded mode.
2907 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2909 u8 request[ioc->req_sz];
2910 u8 reply[sizeof(FWUploadReply_t)];
2911 FWUpload_t *prequest;
2912 FWUploadReply_t *preply;
2913 FWUploadTCSGE_t *ptcsge;
2915 int ii, sz, reply_sz;
2916 int cmdStatus, freeMem = 0;
2917 int num_frags, alloc_sz;
2919 /* If the image size is 0 or if the pointer is
2920 * not NULL (error), we are done.
2922 if (((sz = ioc->facts.FWImageSize) == 0) || ioc->cached_fw)
2925 ioc->num_fw_frags = ioc->req_sz - sizeof(FWUpload_t) + sizeof(dma_addr_t) + sizeof(u32) -1;
2926 ioc->num_fw_frags /= sizeof(dma_addr_t) + sizeof(u32);
2928 ioc->cached_fw = (fw_image_t **) mpt_alloc_fw_memory(ioc,
2929 ioc->facts.FWImageSize, &num_frags, &alloc_sz);
2931 if (ioc->cached_fw == NULL) {
2934 mpt_free_fw_memory(ioc, NULL);
2935 ioc->cached_fw = NULL;
2939 ioc->alloc_total += alloc_sz;
2941 ddlprintk((KERN_INFO MYNAM ": FW Image @ %p, sz=%d bytes\n",
2942 (void *)(ulong)ioc->cached_fw, ioc->facts.FWImageSize));
2944 prequest = (FWUpload_t *)&request;
2945 preply = (FWUploadReply_t *)&reply;
2947 /* Destination... */
2948 memset(prequest, 0, ioc->req_sz);
2950 reply_sz = sizeof(reply);
2951 memset(preply, 0, reply_sz);
2953 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2954 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2955 prequest->MsgContext = 0; /* anything */
2957 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2958 ptcsge->Reserved = 0;
2959 ptcsge->ContextSize = 0;
2960 ptcsge->DetailsLength = 12;
2961 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2962 ptcsge->Reserved1 = 0;
2963 ptcsge->ImageOffset = 0;
2964 ptcsge->ImageSize = cpu_to_le32(sz);
2966 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2968 for (ii = 0; ii < (num_frags-1); ii++) {
2969 mpt_add_sge(&request[sgeoffset], MPT_SGE_FLAGS_SIMPLE_ELEMENT |
2970 MPT_SGE_FLAGS_ADDRESSING | MPT_TRANSFER_IOC_TO_HOST |
2971 (u32) ioc->cached_fw[ii]->size, ioc->cached_fw[ii]->fw_dma);
2973 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2976 mpt_add_sge(&request[sgeoffset],
2977 MPT_SGE_FLAGS_SSIMPLE_READ |(u32) ioc->cached_fw[ii]->size,
2978 ioc->cached_fw[ii]->fw_dma);
2980 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2982 dprintk((MYIOC_s_INFO_FMT "Sending FW Upload (req @ %p) size %d \n",
2983 ioc->name, prequest, sgeoffset));
2985 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2986 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2988 cmdStatus = -EFAULT;
2990 /* Handshake transfer was complete and successful.
2991 * Check the Reply Frame.
2993 int status, transfer_sz;
2994 status = le16_to_cpu(preply->IOCStatus);
2995 if (status == MPI_IOCSTATUS_SUCCESS) {
2996 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2997 if (transfer_sz == sz)
3001 ddlprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
3002 ioc->name, cmdStatus));
3004 /* Check to see if we have a copy of this image in
3005 * host memory already.
3007 if (cmdStatus == 0) {
3009 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
3013 /* We already have a copy of this image or
3014 * we had some type of an error - either the handshake
3015 * failed (i != 0) or the command did not complete successfully.
3017 if (cmdStatus || freeMem) {
3019 ddlprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n",
3020 ioc->name, cmdStatus ? "incomplete" : "duplicate"));
3021 mpt_free_fw_memory(ioc, NULL);
3022 ioc->cached_fw = NULL;
3028 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3030 * mpt_downloadboot - DownloadBoot code
3031 * @ioc: Pointer to MPT_ADAPTER structure
3032 * @flag: Specify which part of IOC memory is to be uploaded.
3033 * @sleepFlag: Specifies whether the process can sleep
3035 * FwDownloadBoot requires Programmed IO access.
3037 * Returns 0 for success
3038 * -1 FW Image size is 0
3039 * -2 No valid cached_fw Pointer
3040 * <0 for fw upload failure.
3043 mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
3045 MpiFwHeader_t *FwHdr;
3046 MpiExtImageHeader_t *ExtHdr;
3047 fw_image_t **pCached=NULL;
3059 int max_idx, fw_idx, ext_idx;
3062 ddlprintk((MYIOC_s_INFO_FMT "DbGb0: downloadboot entered.\n",
3065 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3067 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3068 ddlprintk((MYIOC_s_INFO_FMT "DbGb1: diag0=%08x, diag1=%08x\n",
3069 ioc->name, diag0val, diag1val));
3072 ddlprintk((MYIOC_s_INFO_FMT "fw size 0x%x, ioc FW Ptr %p\n",
3073 ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
3075 ddlprintk((MYIOC_s_INFO_FMT "alt ioc FW Ptr %p\n",
3076 ioc->name, ioc->alt_ioc->cached_fw));
3078 /* Get dma_addr and data transfer size.
3080 if ((fw_sz = ioc->facts.FWImageSize) == 0)
3083 /* Get the DMA from ioc or ioc->alt_ioc */
3084 if (ioc->cached_fw != NULL)
3085 pCached = (fw_image_t **)ioc->cached_fw;
3086 else if (ioc->alt_ioc && (ioc->alt_ioc->cached_fw != NULL))
3087 pCached = (fw_image_t **)ioc->alt_ioc->cached_fw;
3091 ddlprintk((MYIOC_s_INFO_FMT "DbGb2: FW Image @ %p\n",
3092 ioc->name, pCached));
3094 /* Write magic sequence to WriteSequence register
3095 * until enter diagnostic mode
3097 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3098 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3099 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3100 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3101 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3102 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3103 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3104 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3107 if (sleepFlag == CAN_SLEEP) {
3108 set_current_state(TASK_INTERRUPTIBLE);
3109 schedule_timeout(100 * HZ / 1000);
3116 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3117 ioc->name, diag0val);
3122 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3125 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3126 ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
3127 ioc->name, diag0val, diag1val));
3129 ddlprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3130 ioc->name, diag0val));
3133 /* Set the DiagRwEn and Disable ARM bits */
3134 diag0val |= (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM);
3135 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3139 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3141 ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
3142 ioc->name, diag0val, diag1val));
3145 /* max_idx = 1 + maximum valid buffer index
3148 while (pCached[max_idx])
3152 FwHdr = (MpiFwHeader_t *) pCached[fw_idx]->fw;
3153 ptru32 = (u32 *) FwHdr;
3154 count = (FwHdr->ImageSize + 3)/4;
3155 nextImage = FwHdr->NextImageHeaderOffset;
3157 /* Write the LoadStartAddress to the DiagRw Address Register
3158 * using Programmed IO
3160 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->LoadStartAddress);
3161 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
3162 ioc->name, FwHdr->LoadStartAddress));
3164 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x u32's @ %p\n",
3165 ioc->name, count, ptru32));
3166 left_u32s = pCached[fw_idx]->size/4;
3168 if (left_u32s == 0) {
3170 if (fw_idx >= max_idx) {
3176 ptru32 = (u32 *) pCached[fw_idx]->fw;
3177 left_u32s = pCached[fw_idx]->size / 4;
3180 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
3184 /* left_u32s, fw_idx and ptru32 are all valid
3188 ext_offset = nextImage;
3189 while (ext_offset > pCached[ext_idx]->size) {
3191 if (ext_idx >= max_idx) {
3197 ext_offset -= pCached[ext_idx]->size;
3199 ptru32 = (u32 *) ((char *)pCached[ext_idx]->fw + ext_offset);
3200 left_u32s = pCached[ext_idx]->size - ext_offset;
3202 if ((left_u32s * 4) >= sizeof(MpiExtImageHeader_t)) {
3203 ExtHdr = (MpiExtImageHeader_t *) ptru32;
3204 count = (ExtHdr->ImageSize + 3 )/4;
3205 nextImage = ExtHdr->NextImageHeaderOffset;
3206 load_addr = ExtHdr->LoadStartAddress;
3208 u32 * ptmp = (u32 *)pCached[ext_idx+1]->fw;
3210 switch (left_u32s) {
3212 count = *(ptru32 + 2);
3213 nextImage = *(ptru32 + 3);
3214 load_addr = *(ptru32 + 4);
3217 count = *(ptru32 + 2);
3218 nextImage = *(ptru32 + 3);
3222 count = *(ptru32 + 2);
3224 load_addr = *(ptmp + 1);
3228 nextImage = *(ptmp + 1);
3229 load_addr = *(ptmp + 2);
3233 count = *(ptmp + 1);
3234 nextImage = *(ptmp + 2);
3235 load_addr = *(ptmp + 3);
3248 count = (count +3)/4;
3251 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x u32's @ %p\n",
3252 ioc->name, count, ptru32));
3253 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3256 if (left_u32s == 0) {
3258 if (fw_idx >= max_idx) {
3264 ptru32 = (u32 *) pCached[fw_idx]->fw;
3265 left_u32s = pCached[fw_idx]->size / 4;
3268 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
3273 /* Write the IopResetVectorRegAddr */
3274 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr! \n", ioc->name));
3275 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->IopResetRegAddr);
3277 /* Write the IopResetVectorValue */
3278 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value! \n", ioc->name));
3279 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, FwHdr->IopResetVectorValue);
3281 /* Clear the internal flash bad bit - autoincrementing register,
3282 * so must do two writes.
3284 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3285 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3286 diagRwData |= 0x4000000;
3287 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3288 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3290 /* clear the RW enable and DISARM bits */
3291 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3292 diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_FLASH_BAD_SIG);
3293 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3295 /* Write 0xFF to reset the sequencer */
3296 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3301 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3303 * KickStart - Perform hard reset of MPT adapter.
3304 * @ioc: Pointer to MPT_ADAPTER structure
3305 * @force: Force hard reset
3306 * @sleepFlag: Specifies whether the process can sleep
3308 * This routine places MPT adapter in diagnostic mode via the
3309 * WriteSequence register, and then performs a hard reset of adapter
3310 * via the Diagnostic register.
3312 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3313 * or NO_SLEEP (interrupt thread, use mdelay)
3314 * force - 1 if doorbell active, board fault state
3315 * board operational, IOC_RECOVERY or
3316 * IOC_BRINGUP and there is an alt_ioc.
3320 * 1 - hard reset, READY
3321 * 0 - no reset due to History bit, READY
3322 * -1 - no reset due to History bit but not READY
3323 * OR reset but failed to come READY
3324 * -2 - no reset, could not enter DIAG mode
3325 * -3 - reset but bad FW bit
3328 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3330 int hard_reset_done = 0;
3334 dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3335 if ((int)ioc->chip_type > (int)FC929) {
3336 /* Always issue a Msg Unit Reset first. This will clear some
3337 * SCSI bus hang conditions.
3339 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3341 if (sleepFlag == CAN_SLEEP) {
3342 set_current_state(TASK_INTERRUPTIBLE);
3343 schedule_timeout(HZ);
3349 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3350 if (hard_reset_done < 0)
3351 return hard_reset_done;
3353 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3356 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 20; /* 20 seconds */
3357 for (cnt=0; cnt<cntdn; cnt++) {
3358 if ((ioc_state = mpt_GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) {
3359 dprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3361 return hard_reset_done;
3363 if (sleepFlag == CAN_SLEEP) {
3364 set_current_state(TASK_INTERRUPTIBLE);
3365 schedule_timeout(1);
3371 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset!\n",
3376 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3378 * mpt_diag_reset - Perform hard reset of the adapter.
3379 * @ioc: Pointer to MPT_ADAPTER structure
3380 * @ignore: Set if to honor and clear to ignore
3381 * the reset history bit
3382 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3383 * else set to NO_SLEEP (use mdelay instead)
3385 * This routine places the adapter in diagnostic mode via the
3386 * WriteSequence register and then performs a hard reset of adapter
3387 * via the Diagnostic register. Adapter should be in ready state
3388 * upon successful completion.
3390 * Returns: 1 hard reset successful
3391 * 0 no reset performed because reset history bit set
3392 * -2 enabling diagnostic mode failed
3393 * -3 diagnostic reset failed
3396 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3400 int hard_reset_done = 0;
3406 /* Clear any existing interrupts */
3407 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3409 /* Use "Diagnostic reset" method! (only thing available!) */
3410 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3414 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3415 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3416 ioc->name, diag0val, diag1val));
3419 /* Do the reset if we are told to ignore the reset history
3420 * or if the reset history is 0
3422 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3423 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3424 /* Write magic sequence to WriteSequence register
3425 * Loop until in diagnostic mode
3427 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3428 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3429 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3430 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3431 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3432 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3435 if (sleepFlag == CAN_SLEEP) {
3436 set_current_state(TASK_INTERRUPTIBLE);
3437 schedule_timeout(100 * HZ / 1000);
3444 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3445 ioc->name, diag0val);
3450 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3452 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3453 ioc->name, diag0val));
3458 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3459 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3460 ioc->name, diag0val, diag1val));
3462 /* Write the PreventIocBoot bit */
3463 if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
3464 diag0val |= MPI_DIAG_PREVENT_IOC_BOOT;
3465 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3469 * Disable the ARM (Bug fix)
3472 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3476 * Now hit the reset bit in the Diagnostic register
3477 * (THE BIG HAMMER!) (Clears DRWE bit).
3479 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3480 hard_reset_done = 1;
3481 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3485 * Call each currently registered protocol IOC reset handler
3486 * with pre-reset indication.
3487 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3488 * MptResetHandlers[] registered yet.
3494 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3495 if (MptResetHandlers[ii]) {
3496 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3498 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
3500 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3501 ioc->name, ioc->alt_ioc->name, ii));
3502 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
3506 /* FIXME? Examine results here? */
3509 if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
3510 /* If the DownloadBoot operation fails, the
3511 * IOC will be left unusable. This is a fatal error
3512 * case. _diag_reset will return < 0
3514 for (count = 0; count < 30; count ++) {
3515 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3518 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3519 dprintk((MYIOC_s_INFO_FMT
3520 "DbG2b: diag0=%08x, diag1=%08x\n",
3521 ioc->name, diag0val, diag1val));
3523 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3528 if (sleepFlag == CAN_SLEEP) {
3529 set_current_state(TASK_INTERRUPTIBLE);
3530 schedule_timeout(HZ);
3535 if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) {
3536 printk(KERN_WARNING MYNAM
3537 ": firmware downloadboot failure (%d)!\n", count);
3541 /* Wait for FW to reload and for board
3542 * to go to the READY state.
3543 * Maximum wait is 60 seconds.
3544 * If fail, no error will check again
3545 * with calling program.
3547 for (count = 0; count < 60; count ++) {
3548 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3549 doorbell &= MPI_IOC_STATE_MASK;
3551 if (doorbell == MPI_IOC_STATE_READY) {
3556 if (sleepFlag == CAN_SLEEP) {
3557 set_current_state(TASK_INTERRUPTIBLE);
3558 schedule_timeout(HZ);
3566 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3569 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3570 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3571 ioc->name, diag0val, diag1val));
3574 /* Clear RESET_HISTORY bit! Place board in the
3575 * diagnostic mode to update the diag register.
3577 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3579 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3580 /* Write magic sequence to WriteSequence register
3581 * Loop until in diagnostic mode
3583 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3584 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3585 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3586 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3587 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3590 if (sleepFlag == CAN_SLEEP) {
3591 set_current_state(TASK_INTERRUPTIBLE);
3592 schedule_timeout(100 * HZ / 1000);
3599 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3600 ioc->name, diag0val);
3603 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3605 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3606 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3607 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3608 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3609 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3613 /* Disable Diagnostic Mode
3615 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3617 /* Check FW reload status flags.
3619 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3620 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3621 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3622 ioc->name, diag0val);
3628 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3629 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3630 ioc->name, diag0val, diag1val));
3634 * Reset flag that says we've enabled event notification
3636 ioc->facts.EventState = 0;
3639 ioc->alt_ioc->facts.EventState = 0;
3641 return hard_reset_done;
3644 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3646 * SendIocReset - Send IOCReset request to MPT adapter.
3647 * @ioc: Pointer to MPT_ADAPTER structure
3648 * @reset_type: reset type, expected values are
3649 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3651 * Send IOCReset request to the MPT adapter.
3653 * Returns 0 for success, non-zero for failure.
3656 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3662 dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3663 ioc->name, reset_type));
3664 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3665 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3668 /* FW ACK'd request, wait for READY state
3671 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3673 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3677 if (sleepFlag != CAN_SLEEP)
3680 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3681 ioc->name, (count+5)/HZ);
3685 if (sleepFlag == CAN_SLEEP) {
3686 set_current_state(TASK_INTERRUPTIBLE);
3687 schedule_timeout(1);
3689 mdelay (1); /* 1 msec delay */
3694 * Cleanup all event stuff for this IOC; re-issue EventNotification
3695 * request if needed.
3697 if (ioc->facts.Function)
3698 ioc->facts.EventState = 0;
3703 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3705 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3706 * @ioc: Pointer to MPT_ADAPTER structure
3708 * This routine allocates memory for the MPT reply and request frame
3709 * pools (if necessary), and primes the IOC reply FIFO with
3712 * Returns 0 for success, non-zero for failure.
3715 PrimeIocFifos(MPT_ADAPTER *ioc)
3719 unsigned long flags;
3720 dma_addr_t aligned_mem_dma;
3723 int chain_buffer_sz, reply_buffer_sz, request_buffer_sz;
3724 int scale, num_sge, num_chain;
3726 /* request buffer size, rounding UP to nearest 4-kB boundary */
3727 request_buffer_sz = (ioc->req_sz * ioc->req_depth) + 128;
3728 request_buffer_sz = ((request_buffer_sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
3730 /* reply buffer size */
3731 reply_buffer_sz = (ioc->reply_sz * ioc->reply_depth) + 128;
3733 /* chain buffer size, copied from from mptscsih_initChainBuffers()
3735 * Calculate the number of chain buffers needed(plus 1) per I/O
3736 * then multiply the the maximum number of simultaneous cmds
3738 * num_sge = num sge in request frame + last chain buffer
3739 * scale = num sge per chain buffer if no chain element
3742 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3743 if (sizeof(dma_addr_t) == sizeof(u64))
3744 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3746 num_sge = 1 + scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3749 while (MPT_SCSI_SG_DEPTH - num_sge > 0) {
3751 num_sge += (scale - 1);
3755 if ((int)ioc->chip_type > (int) FC929)
3756 num_chain *= MPT_SCSI_CAN_QUEUE;
3758 num_chain *= MPT_FC_CAN_QUEUE;
3760 chain_buffer_sz = num_chain * ioc->req_sz;
3762 if(ioc->fifo_pool == NULL) {
3764 ioc->fifo_pool_sz = request_buffer_sz +
3765 reply_buffer_sz + chain_buffer_sz;
3767 ioc->fifo_pool = pci_alloc_consistent(ioc->pcidev,
3768 ioc->fifo_pool_sz, &ioc->fifo_pool_dma);
3770 if( ioc->fifo_pool == NULL)
3773 ioc->alloc_total += ioc->fifo_pool_sz;
3774 memset(ioc->fifo_pool, 0, ioc->fifo_pool_sz);
3776 /* reply fifo pointers */
3777 ioc->reply_alloc = ioc->fifo_pool;
3778 ioc->reply_alloc_dma = ioc->fifo_pool_dma;
3779 /* request fifo pointers */
3780 ioc->req_alloc = ioc->reply_alloc+reply_buffer_sz;
3781 ioc->req_alloc_dma = ioc->reply_alloc_dma+reply_buffer_sz;
3782 /* chain buffer pointers */
3783 ioc->chain_alloc = ioc->req_alloc+request_buffer_sz;
3784 ioc->chain_alloc_dma = ioc->req_alloc_dma+request_buffer_sz;
3785 ioc->chain_alloc_sz = chain_buffer_sz;
3787 /* Prime reply FIFO... */
3788 dprintk((KERN_INFO MYNAM ": %s.reply_alloc @ %p[%p], sz=%d bytes\n",
3789 ioc->name, mem, (void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz));
3791 b = (unsigned long) ioc->reply_alloc;
3792 b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
3793 aligned_mem = (u8 *) b;
3794 ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem;
3795 ioc->reply_frames_dma =
3796 (ioc->reply_alloc_dma + (aligned_mem - ioc->reply_alloc));
3798 ioc->reply_frames_low_dma = (u32) (ioc->reply_frames_dma & 0xFFFFFFFF);
3800 /* Request FIFO - WE manage this! */
3801 dprintk((KERN_INFO MYNAM ": %s.req_alloc @ %p[%p], sz=%d bytes\n",
3802 ioc->name, mem, (void *)(ulong)ioc->req_alloc_dma, request_buffer_sz));
3804 b = (unsigned long) ioc->req_alloc;
3805 b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
3806 aligned_mem = (u8 *) b;
3807 ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem;
3808 ioc->req_frames_dma =
3809 (ioc->req_alloc_dma + (aligned_mem - ioc->req_alloc));
3811 ioc->req_frames_low_dma = (u32) (ioc->req_frames_dma & 0xFFFFFFFF);
3813 #if defined(CONFIG_MTRR) && 0
3815 * Enable Write Combining MTRR for IOC's memory region.
3816 * (at least as much as we can; "size and base must be
3817 * multiples of 4 kiB"
3819 ioc->mtrr_reg = mtrr_add(ioc->fifo_pool,
3821 MTRR_TYPE_WRCOMB, 1);
3822 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3823 ioc->name, ioc->fifo_pool, ioc->fifo_pool_sz));
3826 } /* ioc->fifo_pool == NULL */
3828 /* Post Reply frames to FIFO
3830 aligned_mem_dma = ioc->reply_frames_dma;
3831 dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%p]\n",
3832 ioc->name, ioc->reply_frames, (void *)(ulong)aligned_mem_dma));
3834 for (i = 0; i < ioc->reply_depth; i++) {
3835 /* Write each address to the IOC! */
3836 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma);
3837 aligned_mem_dma += ioc->reply_sz;
3841 /* Initialize Request frames linked list
3843 aligned_mem_dma = ioc->req_frames_dma;
3844 aligned_mem = (u8 *) ioc->req_frames;
3845 dprintk((KERN_INFO MYNAM ": %s.req_frames @ %p[%p]\n",
3846 ioc->name, aligned_mem, (void *)(ulong)aligned_mem_dma));
3848 spin_lock_irqsave(&ioc->FreeQlock, flags);
3849 Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
3850 for (i = 0; i < ioc->req_depth; i++) {
3851 mf = (MPT_FRAME_HDR *) aligned_mem;
3853 /* Queue REQUESTs *internally*! */
3854 Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
3855 aligned_mem += ioc->req_sz;
3857 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3860 if (ioc->sense_buf_pool == NULL) {
3861 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3862 ioc->sense_buf_pool =
3863 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3864 if (ioc->sense_buf_pool == NULL)
3867 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3868 ioc->alloc_total += sz;
3874 if (ioc->fifo_pool != NULL) {
3875 pci_free_consistent(ioc->pcidev,
3877 ioc->fifo_pool, ioc->fifo_pool_dma);
3878 ioc->reply_frames = NULL;
3879 ioc->reply_alloc = NULL;
3880 ioc->req_frames = NULL;
3881 ioc->req_alloc = NULL;
3882 ioc->chain_alloc = NULL;
3883 ioc->fifo_pool = NULL;
3884 ioc->alloc_total -= ioc->fifo_pool_sz;
3885 #if defined(CONFIG_MTRR) && 0
3886 if (ioc->mtrr_reg > 0) {
3887 mtrr_del(ioc->mtrr_reg, 0, 0);
3888 dprintk((MYIOC_s_INFO_FMT "MTRR region de-registered\n",
3893 if (ioc->sense_buf_pool != NULL) {
3894 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3895 pci_free_consistent(ioc->pcidev,
3897 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3898 ioc->sense_buf_pool = NULL;
3903 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3905 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3906 * from IOC via doorbell handshake method.
3907 * @ioc: Pointer to MPT_ADAPTER structure
3908 * @reqBytes: Size of the request in bytes
3909 * @req: Pointer to MPT request frame
3910 * @replyBytes: Expected size of the reply in bytes
3911 * @u16reply: Pointer to area where reply should be written
3912 * @maxwait: Max wait time for a reply (in seconds)
3913 * @sleepFlag: Specifies whether the process can sleep
3915 * NOTES: It is the callers responsibility to byte-swap fields in the
3916 * request which are greater than 1 byte in size. It is also the
3917 * callers responsibility to byte-swap response fields which are
3918 * greater than 1 byte in size.
3920 * Returns 0 for success, non-zero for failure.
3923 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3924 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3926 MPIDefaultReply_t *mptReply;
3931 * Get ready to cache a handshake reply
3933 ioc->hs_reply_idx = 0;
3934 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3935 mptReply->MsgLength = 0;
3938 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3939 * then tell IOC that we want to handshake a request of N words.
3940 * (WRITE u32val to Doorbell reg).
3942 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3943 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3944 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3945 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3948 * Wait for IOC's doorbell handshake int
3950 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3953 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start, WaitCnt=%d%s\n",
3954 ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3956 /* Read doorbell and check for active bit */
3957 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3961 * Clear doorbell int (WRITE 0 to IntStatus reg),
3962 * then wait for IOC to ACKnowledge that it's ready for
3963 * our handshake request.
3965 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3966 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3971 u8 *req_as_bytes = (u8 *) req;
3974 * Stuff request words via doorbell handshake,
3975 * with ACK from IOC for each.
3977 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3978 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3979 (req_as_bytes[(ii*4) + 1] << 8) |
3980 (req_as_bytes[(ii*4) + 2] << 16) |
3981 (req_as_bytes[(ii*4) + 3] << 24));
3983 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3984 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3988 dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3989 DBG_DUMP_REQUEST_FRAME_HDR(req)
3991 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3992 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3995 * Wait for completion of doorbell handshake reply from the IOC
3997 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
4001 * Copy out the cached reply...
4003 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
4004 u16reply[ii] = ioc->hs_reply[ii];
4012 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4014 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
4015 * in it's IntStatus register.
4016 * @ioc: Pointer to MPT_ADAPTER structure
4017 * @howlong: How long to wait (in seconds)
4018 * @sleepFlag: Specifies whether the process can sleep
4020 * This routine waits (up to ~2 seconds max) for IOC doorbell
4021 * handshake ACKnowledge.
4023 * Returns a negative value on failure, else wait loop count.
4026 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4032 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
4034 if (sleepFlag == CAN_SLEEP) {
4036 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4037 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4039 set_current_state(TASK_INTERRUPTIBLE);
4040 schedule_timeout(1);
4045 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4046 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4054 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (cnt=%d)\n",
4059 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout(%d)!\n",
4060 ioc->name, (count+5)/HZ);
4064 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4066 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
4067 * in it's IntStatus register.
4068 * @ioc: Pointer to MPT_ADAPTER structure
4069 * @howlong: How long to wait (in seconds)
4070 * @sleepFlag: Specifies whether the process can sleep
4072 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
4074 * Returns a negative value on failure, else wait loop count.
4077 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4083 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
4084 if (sleepFlag == CAN_SLEEP) {
4086 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4087 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4089 set_current_state(TASK_INTERRUPTIBLE);
4090 schedule_timeout(1);
4095 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4096 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4104 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d)\n",
4109 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout(%d)!\n",
4110 ioc->name, (count+5)/HZ);
4114 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4116 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
4117 * @ioc: Pointer to MPT_ADAPTER structure
4118 * @howlong: How long to wait (in seconds)
4119 * @sleepFlag: Specifies whether the process can sleep
4121 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4122 * Reply is cached to IOC private area large enough to hold a maximum
4123 * of 128 bytes of reply data.
4125 * Returns a negative value on failure, else size of reply in WORDS.
4128 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4133 u16 *hs_reply = ioc->hs_reply;
4134 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4137 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4140 * Get first two u16's so we can look at IOC's intended reply MsgLength
4143 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4146 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4147 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4148 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4151 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4152 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4156 dhsprintk((MYIOC_s_INFO_FMT "First handshake reply word=%08x%s\n",
4157 ioc->name, le32_to_cpu(*(u32 *)hs_reply),
4158 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4161 * If no error (and IOC said MsgLength is > 0), piece together
4162 * reply 16 bits at a time.
4164 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4165 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4167 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4168 /* don't overflow our IOC hs_reply[] buffer! */
4169 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4170 hs_reply[u16cnt] = hword;
4171 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4174 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4176 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4179 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4184 else if (u16cnt != (2 * mptReply->MsgLength)) {
4187 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4192 dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4193 DBG_DUMP_REPLY_FRAME(mptReply)
4195 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY (sz=%d)\n",
4196 ioc->name, u16cnt/2));
4200 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4202 * GetLanConfigPages - Fetch LANConfig pages.
4203 * @ioc: Pointer to MPT_ADAPTER structure
4205 * Return: 0 for success
4206 * -ENOMEM if no memory available
4207 * -EPERM if not allowed due to ISR context
4208 * -EAGAIN if no msg frames currently available
4209 * -EFAULT for non-successful reply or no reply (timeout)
4212 GetLanConfigPages(MPT_ADAPTER *ioc)
4214 ConfigPageHeader_t hdr;
4216 LANPage0_t *ppage0_alloc;
4217 dma_addr_t page0_dma;
4218 LANPage1_t *ppage1_alloc;
4219 dma_addr_t page1_dma;
4224 /* Get LAN Page 0 header */
4225 hdr.PageVersion = 0;
4228 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4231 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4236 if ((rc = mpt_config(ioc, &cfg)) != 0)
4239 if (hdr.PageLength > 0) {
4240 data_sz = hdr.PageLength * 4;
4241 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4244 memset((u8 *)ppage0_alloc, 0, data_sz);
4245 cfg.physAddr = page0_dma;
4246 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4248 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4250 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4251 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4255 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4258 * Normalize endianness of structure data,
4259 * by byte-swapping all > 1 byte fields!
4268 /* Get LAN Page 1 header */
4269 hdr.PageVersion = 0;
4272 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4275 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4279 if ((rc = mpt_config(ioc, &cfg)) != 0)
4282 if (hdr.PageLength == 0)
4285 data_sz = hdr.PageLength * 4;
4287 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4289 memset((u8 *)ppage1_alloc, 0, data_sz);
4290 cfg.physAddr = page1_dma;
4291 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4293 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4295 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4296 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4299 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4302 * Normalize endianness of structure data,
4303 * by byte-swapping all > 1 byte fields!
4311 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4313 * GetFcPortPage0 - Fetch FCPort config Page0.
4314 * @ioc: Pointer to MPT_ADAPTER structure
4315 * @portnum: IOC Port number
4317 * Return: 0 for success
4318 * -ENOMEM if no memory available
4319 * -EPERM if not allowed due to ISR context
4320 * -EAGAIN if no msg frames currently available
4321 * -EFAULT for non-successful reply or no reply (timeout)
4324 GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4326 ConfigPageHeader_t hdr;
4328 FCPortPage0_t *ppage0_alloc;
4329 FCPortPage0_t *pp0dest;
4330 dma_addr_t page0_dma;
4335 /* Get FCPort Page 0 header */
4336 hdr.PageVersion = 0;
4339 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
4342 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4344 cfg.pageAddr = portnum;
4347 if ((rc = mpt_config(ioc, &cfg)) != 0)
4350 if (hdr.PageLength == 0)
4353 data_sz = hdr.PageLength * 4;
4355 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4357 memset((u8 *)ppage0_alloc, 0, data_sz);
4358 cfg.physAddr = page0_dma;
4359 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4361 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4363 pp0dest = &ioc->fc_port_page0[portnum];
4364 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
4365 memcpy(pp0dest, ppage0_alloc, copy_sz);
4368 * Normalize endianness of structure data,
4369 * by byte-swapping all > 1 byte fields!
4371 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
4372 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
4373 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
4374 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
4375 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
4376 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
4377 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
4378 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
4379 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
4380 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
4381 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
4382 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
4383 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
4384 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
4385 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
4386 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
4390 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4396 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4398 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4399 * @ioc: Pointer to MPT_ADAPTER structure
4401 * Returns: 0 for success
4402 * -ENOMEM if no memory available
4403 * -EPERM if not allowed due to ISR context
4404 * -EAGAIN if no msg frames currently available
4405 * -EFAULT for non-successful reply or no reply (timeout)
4408 GetIoUnitPage2(MPT_ADAPTER *ioc)
4410 ConfigPageHeader_t hdr;
4412 IOUnitPage2_t *ppage_alloc;
4413 dma_addr_t page_dma;
4417 /* Get the page header */
4418 hdr.PageVersion = 0;
4421 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4424 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4429 if ((rc = mpt_config(ioc, &cfg)) != 0)
4432 if (hdr.PageLength == 0)
4435 /* Read the config page */
4436 data_sz = hdr.PageLength * 4;
4438 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4440 memset((u8 *)ppage_alloc, 0, data_sz);
4441 cfg.physAddr = page_dma;
4442 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4444 /* If Good, save data */
4445 if ((rc = mpt_config(ioc, &cfg)) == 0)
4446 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4448 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4454 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4455 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4456 * @ioc: Pointer to a Adapter Strucutre
4457 * @portnum: IOC port number
4459 * Return: -EFAULT if read of config page header fails
4461 * If read of SCSI Port Page 0 fails,
4462 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4463 * Adapter settings: async, narrow
4465 * If read of SCSI Port Page 2 fails,
4466 * Adapter settings valid
4467 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4472 * CHECK - what type of locking mechanisms should be used????
4475 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4480 ConfigPageHeader_t header;
4486 if (!ioc->spi_data.nvram) {
4489 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4490 mem = kmalloc(sz, GFP_ATOMIC);
4494 ioc->spi_data.nvram = (int *) mem;
4496 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4497 ioc->name, ioc->spi_data.nvram, sz));
4500 /* Invalidate NVRAM information
4502 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4503 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4506 /* Read SPP0 header, allocate memory, then read page.
4508 header.PageVersion = 0;
4509 header.PageLength = 0;
4510 header.PageNumber = 0;
4511 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4514 cfg.pageAddr = portnum;
4515 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4517 cfg.timeout = 0; /* use default */
4518 if (mpt_config(ioc, &cfg) != 0)
4521 if (header.PageLength > 0) {
4522 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4524 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4525 cfg.physAddr = buf_dma;
4526 if (mpt_config(ioc, &cfg) != 0) {
4527 ioc->spi_data.maxBusWidth = MPT_NARROW;
4528 ioc->spi_data.maxSyncOffset = 0;
4529 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4530 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4533 /* Save the Port Page 0 data
4535 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4536 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4537 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4539 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 )
4540 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4542 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4543 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4545 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4546 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4547 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4549 ioc->spi_data.maxSyncOffset = 0;
4550 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4553 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4555 /* Update the minSyncFactor based on bus type.
4557 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4558 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4560 if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
4561 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4565 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4570 /* SCSI Port Page 2 - Read the header then the page.
4572 header.PageVersion = 0;
4573 header.PageLength = 0;
4574 header.PageNumber = 2;
4575 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4578 cfg.pageAddr = portnum;
4579 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4581 if (mpt_config(ioc, &cfg) != 0)
4584 if (header.PageLength > 0) {
4585 /* Allocate memory and read SCSI Port Page 2
4587 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4589 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4590 cfg.physAddr = buf_dma;
4591 if (mpt_config(ioc, &cfg) != 0) {
4592 /* Nvram data is left with INVALID mark
4596 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4597 MpiDeviceInfo_t *pdevice = NULL;
4599 /* Save the Port Page 2 data
4600 * (reformat into a 32bit quantity)
4602 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4603 ioc->spi_data.PortFlags = data;
4604 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4605 pdevice = &pPP2->DeviceSettings[ii];
4606 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4607 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4608 ioc->spi_data.nvram[ii] = data;
4612 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4616 /* Update Adapter limits with those from NVRAM
4617 * Comment: Don't need to do this. Target performance
4618 * parameters will never exceed the adapters limits.
4624 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4625 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4626 * @ioc: Pointer to a Adapter Strucutre
4627 * @portnum: IOC port number
4629 * Return: -EFAULT if read of config page header fails
4633 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4636 ConfigPageHeader_t header;
4638 /* Read the SCSI Device Page 1 header
4640 header.PageVersion = 0;
4641 header.PageLength = 0;
4642 header.PageNumber = 1;
4643 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4646 cfg.pageAddr = portnum;
4647 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4650 if (mpt_config(ioc, &cfg) != 0)
4653 ioc->spi_data.sdp1version = cfg.hdr->PageVersion;
4654 ioc->spi_data.sdp1length = cfg.hdr->PageLength;
4656 header.PageVersion = 0;
4657 header.PageLength = 0;
4658 header.PageNumber = 0;
4659 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4660 if (mpt_config(ioc, &cfg) != 0)
4663 ioc->spi_data.sdp0version = cfg.hdr->PageVersion;
4664 ioc->spi_data.sdp0length = cfg.hdr->PageLength;
4666 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4667 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4669 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4670 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4674 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4676 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4677 * @ioc: Pointer to a Adapter Strucutre
4678 * @portnum: IOC port number
4682 * -EFAULT if read of config page header fails or data pointer not NULL
4683 * -ENOMEM if pci_alloc failed
4686 mpt_findImVolumes(MPT_ADAPTER *ioc)
4690 ConfigPageIoc2RaidVol_t *pIocRv;
4691 dma_addr_t ioc2_dma;
4693 ConfigPageHeader_t header;
4700 /* Read IOCP2 header then the page.
4702 header.PageVersion = 0;
4703 header.PageLength = 0;
4704 header.PageNumber = 2;
4705 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4709 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4712 if (mpt_config(ioc, &cfg) != 0)
4715 if (header.PageLength == 0)
4718 iocpage2sz = header.PageLength * 4;
4719 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4723 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4724 cfg.physAddr = ioc2_dma;
4725 if (mpt_config(ioc, &cfg) != 0)
4728 if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) {
4729 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4731 ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem;
4736 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4738 /* Identify RAID Volume Id's */
4739 nVols = pIoc2->NumActiveVolumes;
4745 /* At least 1 RAID Volume
4747 pIocRv = pIoc2->RaidVolume;
4748 ioc->spi_data.isRaid = 0;
4749 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4750 vid = pIocRv->VolumeID;
4751 vbus = pIocRv->VolumeBus;
4752 vioc = pIocRv->VolumeIOC;
4757 ioc->spi_data.isRaid |= (1 << vid);
4759 /* Error! Always bus 0
4765 /* Identify Hidden Physical Disk Id's */
4766 nPhys = pIoc2->NumActivePhysDisks;
4768 /* No physical disks.
4771 mpt_read_ioc_pg_3(ioc);
4775 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4781 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4786 ConfigPageHeader_t header;
4787 dma_addr_t ioc3_dma;
4790 /* Free the old page
4792 if (ioc->spi_data.pIocPg3) {
4793 kfree(ioc->spi_data.pIocPg3);
4794 ioc->spi_data.pIocPg3 = NULL;
4797 /* There is at least one physical disk.
4798 * Read and save IOC Page 3
4800 header.PageVersion = 0;
4801 header.PageLength = 0;
4802 header.PageNumber = 3;
4803 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4807 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4810 if (mpt_config(ioc, &cfg) != 0)
4813 if (header.PageLength == 0)
4816 /* Read Header good, alloc memory
4818 iocpage3sz = header.PageLength * 4;
4819 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4823 /* Read the Page and save the data
4824 * into malloc'd memory.
4826 cfg.physAddr = ioc3_dma;
4827 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4828 if (mpt_config(ioc, &cfg) == 0) {
4829 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4831 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4832 ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
4836 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4842 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4846 ConfigPageHeader_t header;
4847 dma_addr_t ioc4_dma;
4850 /* Read and save IOC Page 4
4852 header.PageVersion = 0;
4853 header.PageLength = 0;
4854 header.PageNumber = 4;
4855 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4859 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4862 if (mpt_config(ioc, &cfg) != 0)
4865 if (header.PageLength == 0)
4868 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4869 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4870 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4874 ioc4_dma = ioc->spi_data.IocPg4_dma;
4875 iocpage4sz = ioc->spi_data.IocPg4Sz;
4878 /* Read the Page into dma memory.
4880 cfg.physAddr = ioc4_dma;
4881 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4882 if (mpt_config(ioc, &cfg) == 0) {
4883 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4884 ioc->spi_data.IocPg4_dma = ioc4_dma;
4885 ioc->spi_data.IocPg4Sz = iocpage4sz;
4887 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4888 ioc->spi_data.pIocPg4 = NULL;
4893 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4897 ConfigPageHeader_t header;
4898 dma_addr_t ioc1_dma;
4902 /* Check the Coalescing Timeout in IOC Page 1
4904 header.PageVersion = 0;
4905 header.PageLength = 0;
4906 header.PageNumber = 1;
4907 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4911 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4914 if (mpt_config(ioc, &cfg) != 0)
4917 if (header.PageLength == 0)
4920 /* Read Header good, alloc memory
4922 iocpage1sz = header.PageLength * 4;
4923 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4927 /* Read the Page and check coalescing timeout
4929 cfg.physAddr = ioc1_dma;
4930 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4931 if (mpt_config(ioc, &cfg) == 0) {
4933 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4934 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4935 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4937 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4940 if (tmp > MPT_COALESCING_TIMEOUT) {
4941 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4943 /* Write NVRAM and current
4946 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4947 if (mpt_config(ioc, &cfg) == 0) {
4948 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
4949 ioc->name, MPT_COALESCING_TIMEOUT));
4951 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
4952 if (mpt_config(ioc, &cfg) == 0) {
4953 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
4954 ioc->name, MPT_COALESCING_TIMEOUT));
4956 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
4961 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4967 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4971 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
4976 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4978 * SendEventNotification - Send EventNotification (on or off) request
4980 * @ioc: Pointer to MPT_ADAPTER structure
4981 * @EvSwitch: Event switch flags
4984 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
4986 EventNotification_t *evnp;
4988 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc->id);
4990 dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
4994 memset(evnp, 0, sizeof(*evnp));
4996 dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch));
4998 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
4999 evnp->ChainOffset = 0;
5001 evnp->Switch = EvSwitch;
5003 mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)evnp);
5008 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5010 * SendEventAck - Send EventAck request to MPT adapter.
5011 * @ioc: Pointer to MPT_ADAPTER structure
5012 * @evnp: Pointer to original EventNotification request
5015 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5019 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
5020 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n",
5024 memset(pAck, 0, sizeof(*pAck));
5026 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5028 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5029 pAck->ChainOffset = 0;
5031 pAck->Event = evnp->Event;
5032 pAck->EventContext = evnp->EventContext;
5034 mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)pAck);
5039 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5041 * mpt_config - Generic function to issue config message
5042 * @ioc - Pointer to an adapter structure
5043 * @cfg - Pointer to a configuration structure. Struct contains
5044 * action, page address, direction, physical address
5045 * and pointer to a configuration page header
5046 * Page header is updated.
5048 * Returns 0 for success
5049 * -EPERM if not allowed due to ISR context
5050 * -EAGAIN if no msg frames currently available
5051 * -EFAULT for non-successful reply or no reply (timeout)
5054 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5058 unsigned long flags;
5063 /* (Bugzilla:fibrebugs, #513)
5064 * Bug fix (part 1)! 20010905 -sralston
5065 * Prevent calling wait_event() (below), if caller happens
5066 * to be in ISR context, because that is fatal!
5068 in_isr = in_interrupt();
5070 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5075 /* Get and Populate a free Frame
5077 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
5078 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5082 pReq = (Config_t *)mf;
5083 pReq->Action = pCfg->action;
5085 pReq->ChainOffset = 0;
5086 pReq->Function = MPI_FUNCTION_CONFIG;
5087 pReq->ExtPageLength = 0;
5088 pReq->ExtPageType = 0;
5090 for (ii=0; ii < 8; ii++)
5091 pReq->Reserved2[ii] = 0;
5093 pReq->Header.PageVersion = pCfg->hdr->PageVersion;
5094 pReq->Header.PageLength = pCfg->hdr->PageLength;
5095 pReq->Header.PageNumber = pCfg->hdr->PageNumber;
5096 pReq->Header.PageType = (pCfg->hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5097 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5099 /* Add a SGE to the config request.
5102 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5104 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5106 flagsLength |= pCfg->hdr->PageLength * 4;
5108 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5110 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5111 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5113 /* Append pCfg pointer to end of mf
5115 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5117 /* Initalize the timer
5119 init_timer(&pCfg->timer);
5120 pCfg->timer.data = (unsigned long) ioc;
5121 pCfg->timer.function = mpt_timer_expired;
5122 pCfg->wait_done = 0;
5124 /* Set the timer; ensure 10 second minimum */
5125 if (pCfg->timeout < 10)
5126 pCfg->timer.expires = jiffies + HZ*10;
5128 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5130 /* Add to end of Q, set timer and then issue this command */
5131 spin_lock_irqsave(&ioc->FreeQlock, flags);
5132 Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
5133 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5135 add_timer(&pCfg->timer);
5136 mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
5137 wait_event(mpt_waitq, pCfg->wait_done);
5139 /* mf has been freed - do not access */
5146 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5148 * mpt_toolbox - Generic function to issue toolbox message
5149 * @ioc - Pointer to an adapter structure
5150 * @cfg - Pointer to a toolbox structure. Struct contains
5151 * action, page address, direction, physical address
5152 * and pointer to a configuration page header
5153 * Page header is updated.
5155 * Returns 0 for success
5156 * -EPERM if not allowed due to ISR context
5157 * -EAGAIN if no msg frames currently available
5158 * -EFAULT for non-successful reply or no reply (timeout)
5161 mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5163 ToolboxIstwiReadWriteRequest_t *pReq;
5165 unsigned long flags;
5170 /* (Bugzilla:fibrebugs, #513)
5171 * Bug fix (part 1)! 20010905 -sralston
5172 * Prevent calling wait_event() (below), if caller happens
5173 * to be in ISR context, because that is fatal!
5175 in_isr = in_interrupt();
5177 dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
5182 /* Get and Populate a free Frame
5184 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
5185 dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
5189 pReq = (ToolboxIstwiReadWriteRequest_t *)mf;
5190 pReq->Tool = pCfg->action;
5192 pReq->ChainOffset = 0;
5193 pReq->Function = MPI_FUNCTION_TOOLBOX;
5194 pReq->Reserved1 = 0;
5195 pReq->Reserved2 = 0;
5197 pReq->Flags = pCfg->dir;
5199 pReq->Reserved3 = 0;
5200 pReq->NumAddressBytes = 0x01;
5201 pReq->Reserved4 = 0;
5202 pReq->DataLength = 0x04;
5203 pReq->DeviceAddr = 0xB0;
5207 pReq->Reserved5 = 0;
5209 /* Add a SGE to the config request.
5212 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
5214 mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
5216 dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
5217 ioc->name, pReq->Tool));
5219 /* Append pCfg pointer to end of mf
5221 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5223 /* Initalize the timer
5225 init_timer(&pCfg->timer);
5226 pCfg->timer.data = (unsigned long) ioc;
5227 pCfg->timer.function = mpt_timer_expired;
5228 pCfg->wait_done = 0;
5230 /* Set the timer; ensure 10 second minimum */
5231 if (pCfg->timeout < 10)
5232 pCfg->timer.expires = jiffies + HZ*10;
5234 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5236 /* Add to end of Q, set timer and then issue this command */
5237 spin_lock_irqsave(&ioc->FreeQlock, flags);
5238 Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
5239 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5241 add_timer(&pCfg->timer);
5242 mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
5243 wait_event(mpt_waitq, pCfg->wait_done);
5245 /* mf has been freed - do not access */
5252 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5254 * mpt_timer_expired - Call back for timer process.
5255 * Used only internal config functionality.
5256 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5259 mpt_timer_expired(unsigned long data)
5261 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5263 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5265 /* Perform a FW reload */
5266 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5267 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5269 /* No more processing.
5270 * Hard reset clean-up will wake up
5271 * process and free all resources.
5273 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5278 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5280 * mpt_ioc_reset - Base cleanup for hard reset
5281 * @ioc: Pointer to the adapter structure
5282 * @reset_phase: Indicates pre- or post-reset functionality
5284 * Remark: Free's resources with internally generated commands.
5287 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5290 unsigned long flags;
5292 dprintk((KERN_WARNING MYNAM
5293 ": IOC %s_reset routed to MPT base driver!\n",
5294 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5295 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5297 if (reset_phase == MPT_IOC_SETUP_RESET) {
5299 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5300 /* If the internal config Q is not empty -
5301 * delete timer. MF resources will be freed when
5302 * the FIFO's are primed.
5304 spin_lock_irqsave(&ioc->FreeQlock, flags);
5305 if (! Q_IS_EMPTY(&ioc->configQ)){
5306 pCfg = (CONFIGPARMS *)ioc->configQ.head;
5308 del_timer(&pCfg->timer);
5309 pCfg = (CONFIGPARMS *) (pCfg->linkage.forw);
5310 } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
5312 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5317 /* Search the configQ for internal commands.
5318 * Flush the Q, and wake up all suspended threads.
5320 spin_lock_irqsave(&ioc->FreeQlock, flags);
5321 if (! Q_IS_EMPTY(&ioc->configQ)){
5322 pCfg = (CONFIGPARMS *)ioc->configQ.head;
5324 pNext = (CONFIGPARMS *) pCfg->linkage.forw;
5326 Q_DEL_ITEM(&pCfg->linkage);
5328 pCfg->status = MPT_CONFIG_ERROR;
5329 pCfg->wait_done = 1;
5330 wake_up(&mpt_waitq);
5333 } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
5335 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5338 return 1; /* currently means nothing really */
5342 #ifdef CONFIG_PROC_FS /* { */
5343 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5345 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5347 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5349 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5351 * Returns 0 for success, non-zero for failure.
5354 procmpt_create(void)
5357 struct proc_dir_entry *ent;
5361 * BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
5362 * (single level) to multi level (e.g. "driver/message/fusion")
5363 * something here needs to change. -sralston
5365 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5366 if (mpt_proc_root_dir == NULL)
5369 for (ii=0; ii < MPT_PROC_ENTRIES; ii++) {
5370 ent = create_proc_entry(mpt_proc_list[ii].name,
5371 S_IFREG|S_IRUGO, mpt_proc_root_dir);
5373 printk(KERN_WARNING MYNAM
5374 ": WARNING - Could not create /proc/mpt/%s entry\n",
5375 mpt_proc_list[ii].name);
5378 ent->read_proc = mpt_proc_list[ii].f;
5382 ioc = mpt_adapter_find_first();
5383 while (ioc != NULL) {
5384 struct proc_dir_entry *dent;
5386 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
5388 if ((dent = proc_mkdir(ioc->name, mpt_proc_root_dir)) != NULL) {
5390 * And populate it with mpt_ioc_proc_list[] entries.
5392 for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) {
5393 ent = create_proc_entry(mpt_ioc_proc_list[ii].name,
5394 S_IFREG|S_IRUGO, dent);
5396 printk(KERN_WARNING MYNAM
5397 ": WARNING - Could not create /proc/mpt/%s/%s entry!\n",
5399 mpt_ioc_proc_list[ii].name);
5402 ent->read_proc = mpt_ioc_proc_list[ii].f;
5406 printk(MYIOC_s_WARN_FMT "Could not create /proc/mpt/%s subdir entry!\n",
5407 ioc->name, mpt_ioc_proc_list[ii].name);
5409 ioc = mpt_adapter_find_next(ioc);
5415 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5417 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5419 * Returns 0 for success, non-zero for failure.
5422 procmpt_destroy(void)
5427 if (!mpt_proc_root_dir)
5431 * BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
5432 * (single level) to multi level (e.g. "driver/message/fusion")
5433 * something here needs to change. -sralston
5436 ioc = mpt_adapter_find_first();
5437 while (ioc != NULL) {
5441 namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
5444 * Tear down each "/proc/mpt/iocN" subdirectory.
5446 for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) {
5447 (void) sprintf(pname+namelen, "/%s", mpt_ioc_proc_list[ii].name);
5448 remove_proc_entry(pname, NULL);
5450 remove_proc_entry(ioc->name, mpt_proc_root_dir);
5451 ioc = mpt_adapter_find_next(ioc);
5454 for (ii=0; ii < MPT_PROC_ENTRIES; ii++)
5455 remove_proc_entry(mpt_proc_list[ii].name, mpt_proc_root_dir);
5457 if (atomic_read((atomic_t *)&mpt_proc_root_dir->count) == 0) {
5458 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5459 mpt_proc_root_dir = NULL;
5466 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5468 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5469 * or from /proc/mpt/iocN/summary.
5470 * @buf: Pointer to area to write information
5471 * @start: Pointer to start pointer
5472 * @offset: Offset to start writing
5474 * @eof: Pointer to EOF integer
5477 * Returns number of characters written to process performing the read.
5480 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5487 ioc = mpt_adapter_find_first();
5494 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5497 if ((out-buf) >= request) {
5502 ioc = mpt_adapter_find_next(ioc);
5504 ioc = NULL; /* force exit for iocN */
5508 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5511 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5513 * procmpt_version_read - Handle read request from /proc/mpt/version.
5514 * @buf: Pointer to area to write information
5515 * @start: Pointer to start pointer
5516 * @offset: Offset to start writing
5518 * @eof: Pointer to EOF integer
5521 * Returns number of characters written to process performing the read.
5524 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5527 int scsi, lan, ctl, targ, dmp;
5531 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5532 len += sprintf(buf+len, " Fusion MPT base driver\n");
5534 scsi = lan = ctl = targ = dmp = 0;
5535 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5537 if (MptCallbacks[ii]) {
5538 switch (MptDriverClass[ii]) {
5539 case MPTSCSIH_DRIVER:
5540 if (!scsi++) drvname = "SCSI host";
5543 if (!lan++) drvname = "LAN";
5546 if (!targ++) drvname = "SCSI target";
5549 if (!ctl++) drvname = "ioctl";
5552 if (!dmp++) drvname = "DMP";
5557 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5559 * Handle isense special case, because it
5560 * doesn't do a formal mpt_register call.
5562 if (isense_idx == ii)
5563 len += sprintf(buf+len, " Fusion MPT isense driver\n");
5567 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5570 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5572 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5573 * @buf: Pointer to area to write information
5574 * @start: Pointer to start pointer
5575 * @offset: Offset to start writing
5577 * @eof: Pointer to EOF integer
5580 * Returns number of characters written to process performing the read.
5583 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5585 MPT_ADAPTER *ioc = data;
5591 mpt_get_fw_exp_ver(expVer, ioc);
5593 len = sprintf(buf, "%s:", ioc->name);
5594 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5595 len += sprintf(buf+len, " (f/w download boot flag set)");
5596 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5597 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5599 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5600 ioc->facts.ProductID,
5602 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5603 if (ioc->facts.FWImageSize)
5604 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5605 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5606 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5607 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5609 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5610 ioc->facts.CurrentHostMfaHighAddr);
5611 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5612 ioc->facts.CurrentSenseBufferHighAddr);
5614 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5615 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5617 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5618 (void *)ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma);
5620 * Rounding UP to nearest 4-kB boundary here...
5622 sz = (ioc->req_sz * ioc->req_depth) + 128;
5623 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5624 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5625 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5626 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5627 4*ioc->facts.RequestFrameSize,
5628 ioc->facts.GlobalCredits);
5630 len += sprintf(buf+len, " ReplyFrames @ 0x%p (Dma @ 0x%p)\n",
5631 (void *)ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma);
5632 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5633 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5634 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5635 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5636 ioc->facts.CurReplyFrameSize,
5637 ioc->facts.ReplyQueueDepth);
5639 len += sprintf(buf+len, " MaxDevices = %d\n",
5640 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5641 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5644 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5645 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5647 ioc->facts.NumberOfPorts);
5648 if ((int)ioc->chip_type <= (int)FC929) {
5649 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5650 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5651 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5652 a[5], a[4], a[3], a[2], a[1], a[0]);
5654 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5655 ioc->fc_port_page0[p].WWNN.High,
5656 ioc->fc_port_page0[p].WWNN.Low,
5657 ioc->fc_port_page0[p].WWPN.High,
5658 ioc->fc_port_page0[p].WWPN.Low);
5662 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5665 #endif /* CONFIG_PROC_FS } */
5667 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5669 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5672 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5673 sprintf(buf, " (Exp %02d%02d)",
5674 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5675 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5678 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5679 strcat(buf, " [MDBG]");
5683 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5685 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5686 * @ioc: Pointer to MPT_ADAPTER structure
5687 * @buffer: Pointer to buffer where IOC summary info should be written
5688 * @size: Pointer to number of bytes we wrote (set by this routine)
5689 * @len: Offset at which to start writing in buffer
5690 * @showlan: Display LAN stuff?
5692 * This routine writes (english readable) ASCII text, which represents
5693 * a summary of IOC information, to a buffer.
5696 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5701 mpt_get_fw_exp_ver(expVer, ioc);
5704 * Shorter summary of attached ioc's...
5706 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5709 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5710 ioc->facts.FWVersion.Word,
5712 ioc->facts.NumberOfPorts,
5715 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5716 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5717 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5718 a[5], a[4], a[3], a[2], a[1], a[0]);
5722 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5724 y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5728 y += sprintf(buffer+len+y, " (disabled)");
5730 y += sprintf(buffer+len+y, "\n");
5735 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5739 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5741 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5742 * Management call based on input arg values. If TaskMgmt fails,
5743 * return associated SCSI request.
5744 * @ioc: Pointer to MPT_ADAPTER structure
5745 * @sleepFlag: Indicates if sleep or schedule must be called.
5747 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5748 * or a non-interrupt thread. In the former, must not call schedule().
5750 * Remark: A return of -1 is a FATAL error case, as it means a
5751 * FW reload/initialization failed.
5753 * Returns 0 for SUCCESS or -1 if FAILED.
5756 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5759 unsigned long flags;
5761 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5763 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5764 printk("MF count 0x%x !\n", ioc->mfcnt);
5767 /* Reset the adapter. Prevent more than 1 call to
5768 * mpt_do_ioc_recovery at any instant in time.
5770 spin_lock_irqsave(&ioc->diagLock, flags);
5771 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5772 spin_unlock_irqrestore(&ioc->diagLock, flags);
5775 ioc->diagPending = 1;
5777 spin_unlock_irqrestore(&ioc->diagLock, flags);
5779 /* FIXME: If do_ioc_recovery fails, repeat....
5782 /* The SCSI driver needs to adjust timeouts on all current
5783 * commands prior to the diagnostic reset being issued.
5784 * Prevents timeouts occuring during a diagnostic reset...very bad.
5785 * For all other protocol drivers, this is a no-op.
5791 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5792 if (MptResetHandlers[ii]) {
5793 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5795 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
5797 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5798 ioc->name, ioc->alt_ioc->name, ii));
5799 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5805 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5806 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5811 ioc->alt_ioc->reload_fw = 0;
5813 spin_lock_irqsave(&ioc->diagLock, flags);
5814 ioc->diagPending = 0;
5816 ioc->alt_ioc->diagPending = 0;
5817 spin_unlock_irqrestore(&ioc->diagLock, flags);
5819 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5824 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5826 EventDescriptionStr(u8 event, u32 evData0)
5831 case MPI_EVENT_NONE:
5834 case MPI_EVENT_LOG_DATA:
5837 case MPI_EVENT_STATE_CHANGE:
5838 ds = "State Change";
5840 case MPI_EVENT_UNIT_ATTENTION:
5841 ds = "Unit Attention";
5843 case MPI_EVENT_IOC_BUS_RESET:
5844 ds = "IOC Bus Reset";
5846 case MPI_EVENT_EXT_BUS_RESET:
5847 ds = "External Bus Reset";
5849 case MPI_EVENT_RESCAN:
5850 ds = "Bus Rescan Event";
5851 /* Ok, do we need to do anything here? As far as
5852 I can tell, this is when a new device gets added
5855 case MPI_EVENT_LINK_STATUS_CHANGE:
5856 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5857 ds = "Link Status(FAILURE) Change";
5859 ds = "Link Status(ACTIVE) Change";
5861 case MPI_EVENT_LOOP_STATE_CHANGE:
5862 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5863 ds = "Loop State(LIP) Change";
5864 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5865 ds = "Loop State(LPE) Change"; /* ??? */
5867 ds = "Loop State(LPB) Change"; /* ??? */
5869 case MPI_EVENT_LOGOUT:
5872 case MPI_EVENT_EVENT_CHANGE:
5874 ds = "Events(ON) Change";
5876 ds = "Events(OFF) Change";
5878 case MPI_EVENT_INTEGRATED_RAID:
5879 ds = "Integrated Raid";
5882 * MPT base "custom" events may be added here...
5891 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5893 * ProcessEventNotification - Route a received EventNotificationReply to
5894 * all currently regeistered event handlers.
5895 * @ioc: Pointer to MPT_ADAPTER structure
5896 * @pEventReply: Pointer to EventNotification reply frame
5897 * @evHandlers: Pointer to integer, number of event handlers
5899 * Returns sum of event handlers return values.
5902 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
5914 * Do platform normalization of values
5916 event = le32_to_cpu(pEventReply->Event) & 0xFF;
5917 // evCtx = le32_to_cpu(pEventReply->EventContext);
5918 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
5920 evData0 = le32_to_cpu(pEventReply->Data[0]);
5923 evStr = EventDescriptionStr(event, evData0);
5924 dprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
5929 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
5930 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
5931 for (ii = 0; ii < evDataLen; ii++)
5932 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
5937 * Do general / base driver event processing
5940 case MPI_EVENT_NONE: /* 00 */
5941 case MPI_EVENT_LOG_DATA: /* 01 */
5942 case MPI_EVENT_STATE_CHANGE: /* 02 */
5943 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
5944 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
5945 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
5946 case MPI_EVENT_RESCAN: /* 06 */
5947 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
5948 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
5949 case MPI_EVENT_LOGOUT: /* 09 */
5950 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
5951 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: /* 0C */
5954 case MPI_EVENT_EVENT_CHANGE: /* 0A */
5956 u8 evState = evData0 & 0xFF;
5958 /* CHECKME! What if evState unexpectedly says OFF (0)? */
5960 /* Update EventState field in cached IocFacts */
5961 if (ioc->facts.Function) {
5962 ioc->facts.EventState = evState;
5969 * Should this event be logged? Events are written sequentially.
5970 * When buffer is full, start again at the top.
5972 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
5975 idx = ioc->eventContext % ioc->eventLogSize;
5977 ioc->events[idx].event = event;
5978 ioc->events[idx].eventContext = ioc->eventContext;
5980 for (ii = 0; ii < 2; ii++) {
5982 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
5984 ioc->events[idx].data[ii] = 0;
5987 ioc->eventContext++;
5992 * Call each currently registered protocol event handler.
5994 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5995 if (MptEvHandlers[ii]) {
5996 dprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
5998 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6002 /* FIXME? Examine results here? */
6005 * If needed, send (a single) EventAck.
6007 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6008 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6009 printk(MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6014 *evHandlers = handlers;
6018 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6020 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6021 * @ioc: Pointer to MPT_ADAPTER structure
6022 * @log_info: U32 LogInfo reply word from the IOC
6024 * Refer to lsi/fc_log.h.
6027 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6029 static char *subcl_str[8] = {
6030 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6031 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6033 u8 subcl = (log_info >> 24) & 0x7;
6034 // u32 SubCl = log_info & 0x27000000;
6036 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}",
6037 ioc->name, log_info, subcl_str[subcl]);
6040 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6042 * mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
6043 * @ioc: Pointer to MPT_ADAPTER structure
6044 * @mr: Pointer to MPT reply frame
6045 * @log_info: U32 LogInfo word from the IOC
6047 * Refer to lsi/sp_log.h.
6050 mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
6052 u32 info = log_info & 0x00FF0000;
6053 char *desc = "unknown";
6057 desc = "bug! MID not found";
6058 if (ioc->reload_fw == 0)
6063 desc = "Parity Error";
6067 desc = "ASYNC Outbound Overrun";
6071 desc = "SYNC Offset Error";
6079 desc = "Msg In Overflow";
6087 desc = "Outbound DMA Overrun";
6091 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6094 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6096 * mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI
6097 * OpCode strings from the (optional) isense module.
6098 * @ascqTable: Pointer to ASCQ_Table_t structure
6099 * @ascqtbl_sz: Number of entries in ASCQ_Table
6100 * @opsTable: Pointer to array of SCSI OpCode strings (char pointers)
6102 * Specialized driver registration routine for the isense driver.
6105 mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable)
6109 if (ascqTable && ascqtbl_sz && opsTable) {
6110 mpt_v_ASCQ_TablePtr = ascqTable;
6111 mpt_ASCQ_TableSz = ascqtbl_sz;
6112 mpt_ScsiOpcodesPtr = opsTable;
6113 printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n");
6114 isense_idx = last_drv_idx;
6120 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6122 * mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI
6123 * OpCode strings from the isense driver.
6125 * Specialized driver deregistration routine for the isense driver.
6128 mpt_deregister_ascqops_strings(void)
6130 mpt_v_ASCQ_TablePtr = NULL;
6131 mpt_ASCQ_TableSz = 0;
6132 mpt_ScsiOpcodesPtr = NULL;
6133 printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
6137 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6139 EXPORT_SYMBOL(mpt_adapters);
6140 EXPORT_SYMBOL(mpt_proc_root_dir);
6141 EXPORT_SYMBOL(DmpService);
6142 EXPORT_SYMBOL(mpt_register);
6143 EXPORT_SYMBOL(mpt_deregister);
6144 EXPORT_SYMBOL(mpt_event_register);
6145 EXPORT_SYMBOL(mpt_event_deregister);
6146 EXPORT_SYMBOL(mpt_reset_register);
6147 EXPORT_SYMBOL(mpt_reset_deregister);
6148 EXPORT_SYMBOL(mpt_device_driver_register);
6149 EXPORT_SYMBOL(mpt_device_driver_deregister);
6150 EXPORT_SYMBOL(mpt_get_msg_frame);
6151 EXPORT_SYMBOL(mpt_put_msg_frame);
6152 EXPORT_SYMBOL(mpt_free_msg_frame);
6153 EXPORT_SYMBOL(mpt_add_sge);
6154 EXPORT_SYMBOL(mpt_add_chain);
6155 EXPORT_SYMBOL(mpt_send_handshake_request);
6156 EXPORT_SYMBOL(mpt_handshake_req_reply_wait);
6157 EXPORT_SYMBOL(mpt_adapter_find_first);
6158 EXPORT_SYMBOL(mpt_adapter_find_next);
6159 EXPORT_SYMBOL(mpt_verify_adapter);
6160 EXPORT_SYMBOL(mpt_GetIocState);
6161 EXPORT_SYMBOL(mpt_print_ioc_summary);
6162 EXPORT_SYMBOL(mpt_lan_index);
6163 EXPORT_SYMBOL(mpt_stm_index);
6164 EXPORT_SYMBOL(mpt_HardResetHandler);
6165 EXPORT_SYMBOL(mpt_config);
6166 EXPORT_SYMBOL(mpt_toolbox);
6167 EXPORT_SYMBOL(mpt_findImVolumes);
6168 EXPORT_SYMBOL(mpt_read_ioc_pg_3);
6169 EXPORT_SYMBOL(mpt_alloc_fw_memory);
6170 EXPORT_SYMBOL(mpt_free_fw_memory);
6172 EXPORT_SYMBOL(mpt_register_ascqops_strings);
6173 EXPORT_SYMBOL(mpt_deregister_ascqops_strings);
6174 EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr);
6175 EXPORT_SYMBOL(mpt_ASCQ_TableSz);
6176 EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
6179 static struct pci_driver mptbase_driver = {
6181 .id_table = mptbase_pci_table,
6182 .probe = mptbase_probe,
6183 .remove = __devexit_p(mptbase_remove),
6185 .shutdown = mptbase_shutdown,
6188 .suspend = mptbase_suspend,
6189 .resume = mptbase_resume,
6193 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6195 * fusion_init - Fusion MPT base driver initialization routine.
6197 * Returns 0 for success, non-zero for failure.
6205 if (FusionInitCalled++) {
6206 dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n"));
6210 show_mptmod_ver(my_NAME, my_VERSION);
6211 printk(KERN_INFO COPYRIGHT "\n");
6213 Q_INIT(&MptAdapters, MPT_ADAPTER); /* set to empty */
6214 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6215 MptCallbacks[i] = NULL;
6216 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6217 MptEvHandlers[i] = NULL;
6218 MptResetHandlers[i] = NULL;
6223 /* NEW! 20010120 -sralston
6224 * Register ourselves (mptbase) in order to facilitate
6225 * EventNotification handling.
6227 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6229 /* Register for hard reset handling callbacks.
6231 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6232 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6237 r = pci_module_init(&mptbase_driver);
6241 #ifdef CONFIG_PROC_FS
6242 (void) procmpt_create();
6248 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6250 * fusion_exit - Perform driver unload cleanup.
6252 * This routine frees all resources associated with each MPT adapter
6253 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6259 dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6261 /* Whups? 20010120 -sralston
6262 * Moved this *above* removal of all MptAdapters!
6264 #ifdef CONFIG_PROC_FS
6265 (void) procmpt_destroy();
6267 pci_unregister_driver(&mptbase_driver);
6268 mpt_reset_deregister(mpt_base_index);
6272 module_init(fusion_init);
6273 module_exit(fusion_exit);