initial commit with v2.6.9
[linux-2.6.9-moxart.git] / drivers / message / fusion / mptbase.c
blob70a44c9d2f7414ccdc742e105ca9da0256352bae
1 /*
2 * linux/drivers/message/fusion/mptbase.c
3 * High performance SCSI + LAN / Fibre Channel device drivers.
4 * This is the Fusion MPT base driver which supports multiple
5 * (SCSI + LAN) specialized protocol drivers.
6 * For use with PCI chip/adapter(s):
7 * LSIFC9xx/LSI409xx Fibre Channel
8 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
10 * Credits:
11 * There are lots of people not mentioned below that deserve credit
12 * and thanks but won't get it here - sorry in advance that you
13 * got overlooked.
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,
33 * etc.
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.
45 * THANK YOU!
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.
65 NO WARRANTY
66 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
67 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
68 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
69 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
70 solely responsible for determining the appropriateness of using and
71 distributing the Program and assumes all risks associated with its
72 exercise of rights under this Agreement, including but not limited to
73 the risks and costs of program errors, damage to or loss of data,
74 programs or equipment, and unavailability or interruption of operations.
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 */
104 #include <asm/io.h>
105 #ifdef CONFIG_MTRR
106 #include <asm/mtrr.h>
107 #endif
108 #ifdef __sparc__
109 #include <asm/irq.h> /* needed for __irq_itoa() proto */
110 #endif
112 #include "mptbase.h"
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
126 #ifdef MFCNT
127 static int mfcounter = 0;
128 #define PRINT_MF_COUNT 20000
129 #endif
131 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
133 * Public data...
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 #define WHOINIT_UNKNOWN 0xAA
144 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
146 * Private data...
148 /* Adapter link list */
149 LIST_HEAD(ioc_list);
150 /* Callback lookup table */
151 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
152 /* Protocol driver class lookup table */
153 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
154 /* Event handler lookup table */
155 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
156 /* Reset handler lookup table */
157 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
158 static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
160 static int FusionInitCalled = 0;
161 static int mpt_base_index = -1;
162 static int last_drv_idx = -1;
164 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
166 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
168 * Forward protos...
170 static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
171 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
173 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
174 static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
175 static void mpt_adapter_disable(MPT_ADAPTER *ioc);
176 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
178 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
179 static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
180 //static u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
181 static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
182 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
183 static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
184 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
185 static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
186 static int mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag);
187 static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
188 static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
189 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
190 static int PrimeIocFifos(MPT_ADAPTER *ioc);
191 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
192 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
193 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
194 static int GetLanConfigPages(MPT_ADAPTER *ioc);
195 static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
196 static int GetIoUnitPage2(MPT_ADAPTER *ioc);
197 static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
198 static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
199 static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
200 static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
201 static void mpt_timer_expired(unsigned long data);
202 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
203 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
205 #ifdef CONFIG_PROC_FS
206 static int procmpt_summary_read(char *buf, char **start, off_t offset,
207 int request, int *eof, void *data);
208 static int procmpt_version_read(char *buf, char **start, off_t offset,
209 int request, int *eof, void *data);
210 static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
211 int request, int *eof, void *data);
212 #endif
213 static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
215 //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
216 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
217 static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
218 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
219 static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
221 /* module entry point */
222 static int __devinit mptbase_probe (struct pci_dev *, const struct pci_device_id *);
223 static void __devexit mptbase_remove(struct pci_dev *);
224 static void mptbase_shutdown(struct device * );
225 static int __init fusion_init (void);
226 static void __exit fusion_exit (void);
228 /****************************************************************************
229 * Supported hardware
232 static struct pci_device_id mptbase_pci_table[] = {
233 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
234 PCI_ANY_ID, PCI_ANY_ID },
235 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
236 PCI_ANY_ID, PCI_ANY_ID },
237 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
238 PCI_ANY_ID, PCI_ANY_ID },
239 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
240 PCI_ANY_ID, PCI_ANY_ID },
241 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
242 PCI_ANY_ID, PCI_ANY_ID },
243 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
244 PCI_ANY_ID, PCI_ANY_ID },
245 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
246 PCI_ANY_ID, PCI_ANY_ID },
247 {0} /* Terminating entry */
249 MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
251 #define CHIPREG_READ32(addr) readl_relaxed(addr)
252 #define CHIPREG_READ32_dmasync(addr) readl(addr)
253 #define CHIPREG_WRITE32(addr,val) writel(val, addr)
254 #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
255 #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
257 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
259 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
260 * @irq: irq number (not used)
261 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
262 * @r: pt_regs pointer (not used)
264 * This routine is registered via the request_irq() kernel API call,
265 * and handles all interrupts generated from a specific MPT adapter
266 * (also referred to as a IO Controller or IOC).
267 * This routine must clear the interrupt from the adapter and does
268 * so by reading the reply FIFO. Multiple replies may be processed
269 * per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
270 * which is currently set to 32 in mptbase.h.
272 * This routine handles register-level access of the adapter but
273 * dispatches (calls) a protocol-specific callback routine to handle
274 * the protocol-specific details of the MPT request completion.
276 static irqreturn_t
277 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
279 MPT_ADAPTER *ioc;
280 MPT_FRAME_HDR *mf;
281 MPT_FRAME_HDR *mr;
282 u32 pa;
283 int req_idx;
284 int cb_idx;
285 int type;
286 int freeme;
288 ioc = (MPT_ADAPTER *)bus_id;
291 * Drain the reply FIFO!
293 * NOTES: I've seen up to 10 replies processed in this loop, so far...
294 * Update: I've seen up to 9182 replies processed in this loop! ??
295 * Update: Limit ourselves to processing max of N replies
296 * (bottom of loop).
298 while (1) {
300 if ((pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)
301 return IRQ_HANDLED;
303 cb_idx = 0;
304 freeme = 0;
307 * Check for non-TURBO reply!
309 if (pa & MPI_ADDRESS_REPLY_A_BIT) {
310 u32 reply_dma_low;
311 u16 ioc_stat;
313 /* non-TURBO reply! Hmmm, something may be up...
314 * Newest turbo reply mechanism; get address
315 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
318 /* Map DMA address of reply header to cpu address.
319 * pa is 32 bits - but the dma address may be 32 or 64 bits
320 * get offset based only only the low addresses
322 reply_dma_low = (pa = (pa << 1));
323 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
324 (reply_dma_low - ioc->reply_frames_low_dma));
326 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
327 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
328 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
330 dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x\n",
331 ioc->name, mr, req_idx));
332 DBG_DUMP_REPLY_FRAME(mr)
334 /* NEW! 20010301 -sralston
335 * Check/log IOC log info
337 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
338 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
339 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
340 if ((int)ioc->chip_type <= (int)FC929)
341 mpt_fc_log_info(ioc, log_info);
342 else
343 mpt_sp_log_info(ioc, log_info);
345 if (ioc_stat & MPI_IOCSTATUS_MASK) {
346 if ((int)ioc->chip_type <= (int)FC929)
348 else
349 mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
351 } else {
353 * Process turbo (context) reply...
355 dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa));
356 type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
357 if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
358 cb_idx = mpt_stm_index;
359 mf = NULL;
360 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
361 } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
362 cb_idx = mpt_lan_index;
364 * BUG FIX! 20001218 -sralston
365 * Blind set of mf to NULL here was fatal
366 * after lan_reply says "freeme"
367 * Fix sort of combined with an optimization here;
368 * added explicit check for case where lan_reply
369 * was just returning 1 and doing nothing else.
370 * For this case skip the callback, but set up
371 * proper mf value first here:-)
373 if ((pa & 0x58000000) == 0x58000000) {
374 req_idx = pa & 0x0000FFFF;
375 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
376 freeme = 1;
378 * IMPORTANT! Invalidate the callback!
380 cb_idx = 0;
381 } else {
382 mf = NULL;
384 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
385 } else {
386 req_idx = pa & 0x0000FFFF;
387 cb_idx = (pa & 0x00FF0000) >> 16;
388 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
389 mr = NULL;
391 pa = 0; /* No reply flush! */
394 #ifdef MPT_DEBUG_IRQ
395 if ((int)ioc->chip_type > (int)FC929) {
396 /* Verify mf, mr are reasonable.
398 if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
399 || (mf < ioc->req_frames)) ) {
400 printk(MYIOC_s_WARN_FMT
401 "mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx);
402 cb_idx = 0;
403 pa = 0;
404 freeme = 0;
406 if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth))
407 || (mr < ioc->reply_frames)) ) {
408 printk(MYIOC_s_WARN_FMT
409 "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr);
410 cb_idx = 0;
411 pa = 0;
412 freeme = 0;
414 if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) {
415 printk(MYIOC_s_WARN_FMT
416 "mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx);
417 cb_idx = 0;
418 pa = 0;
419 freeme = 0;
422 #endif
424 /* Check for (valid) IO callback! */
425 if (cb_idx) {
426 /* Do the callback! */
427 freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);
430 if (pa) {
431 /* Flush (non-TURBO) reply with a WRITE! */
432 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
435 if (freeme) {
436 unsigned long flags;
438 /* Put Request back on FreeQ! */
439 spin_lock_irqsave(&ioc->FreeQlock, flags);
440 Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
441 #ifdef MFCNT
442 ioc->mfcnt--;
443 #endif
444 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
447 mb();
448 } /* drain reply FIFO */
450 return IRQ_HANDLED;
453 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
455 * mpt_base_reply - MPT base driver's callback routine; all base driver
456 * "internal" request/reply processing is routed here.
457 * Currently used for EventNotification and EventAck handling.
458 * @ioc: Pointer to MPT_ADAPTER structure
459 * @mf: Pointer to original MPT request frame
460 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
462 * Returns 1 indicating original alloc'd request frame ptr
463 * should be freed, or 0 if it shouldn't.
465 static int
466 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
468 int freereq = 1;
469 u8 func;
471 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
473 if ((mf == NULL) ||
474 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
475 printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n",
476 ioc->name, (void *)mf);
477 return 1;
480 if (reply == NULL) {
481 dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n",
482 ioc->name));
483 return 1;
486 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
487 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
488 DBG_DUMP_REQUEST_FRAME_HDR(mf)
491 func = reply->u.hdr.Function;
492 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
493 ioc->name, func));
495 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
496 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
497 int evHandlers = 0;
498 int results;
500 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
501 if (results != evHandlers) {
502 /* CHECKME! Any special handling needed here? */
503 devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
504 ioc->name, evHandlers, results));
508 * Hmmm... It seems that EventNotificationReply is an exception
509 * to the rule of one reply per request.
511 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
512 freereq = 0;
514 #ifdef CONFIG_PROC_FS
515 // LogEvent(ioc, pEvReply);
516 #endif
518 } else if (func == MPI_FUNCTION_EVENT_ACK) {
519 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
520 ioc->name));
521 } else if (func == MPI_FUNCTION_CONFIG ||
522 func == MPI_FUNCTION_TOOLBOX) {
523 CONFIGPARMS *pCfg;
524 unsigned long flags;
526 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
527 ioc->name, mf, reply));
529 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
531 if (pCfg) {
532 /* disable timer and remove from linked list */
533 del_timer(&pCfg->timer);
535 spin_lock_irqsave(&ioc->FreeQlock, flags);
536 Q_DEL_ITEM(&pCfg->linkage);
537 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
540 * If IOC Status is SUCCESS, save the header
541 * and set the status code to GOOD.
543 pCfg->status = MPT_CONFIG_ERROR;
544 if (reply) {
545 ConfigReply_t *pReply = (ConfigReply_t *)reply;
546 u16 status;
548 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
549 dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
550 status, le32_to_cpu(pReply->IOCLogInfo)));
552 pCfg->status = status;
553 if (status == MPI_IOCSTATUS_SUCCESS) {
554 pCfg->hdr->PageVersion = pReply->Header.PageVersion;
555 pCfg->hdr->PageLength = pReply->Header.PageLength;
556 pCfg->hdr->PageNumber = pReply->Header.PageNumber;
557 pCfg->hdr->PageType = pReply->Header.PageType;
562 * Wake up the original calling thread
564 pCfg->wait_done = 1;
565 wake_up(&mpt_waitq);
567 } else {
568 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
569 ioc->name, func);
573 * Conditionally tell caller to free the original
574 * EventNotification/EventAck/unexpected request frame!
576 return freereq;
579 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
581 * mpt_register - Register protocol-specific main callback handler.
582 * @cbfunc: callback function pointer
583 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
585 * This routine is called by a protocol-specific driver (SCSI host,
586 * LAN, SCSI target) to register it's reply callback routine. Each
587 * protocol-specific driver must do this before it will be able to
588 * use any IOC resources, such as obtaining request frames.
590 * NOTES: The SCSI protocol driver currently calls this routine thrice
591 * in order to register separate callbacks; one for "normal" SCSI IO;
592 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
594 * Returns a positive integer valued "handle" in the
595 * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
596 * Any non-positive return value (including zero!) should be considered
597 * an error by the caller.
600 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
602 int i;
604 last_drv_idx = -1;
606 #ifndef MODULE
608 * Handle possibility of the mptscsih_detect() routine getting
609 * called *before* fusion_init!
611 if (!FusionInitCalled) {
612 dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n"));
614 * NOTE! We'll get recursion here, as fusion_init()
615 * calls mpt_register()!
617 fusion_init();
618 FusionInitCalled++;
620 #endif
623 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
624 * (slot/handle 0 is reserved!)
626 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
627 if (MptCallbacks[i] == NULL) {
628 MptCallbacks[i] = cbfunc;
629 MptDriverClass[i] = dclass;
630 MptEvHandlers[i] = NULL;
631 last_drv_idx = i;
632 break;
636 return last_drv_idx;
639 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
641 * mpt_deregister - Deregister a protocol drivers resources.
642 * @cb_idx: previously registered callback handle
644 * Each protocol-specific driver should call this routine when it's
645 * module is unloaded.
647 void
648 mpt_deregister(int cb_idx)
650 if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
651 MptCallbacks[cb_idx] = NULL;
652 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
653 MptEvHandlers[cb_idx] = NULL;
655 last_drv_idx++;
659 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
661 * mpt_event_register - Register protocol-specific event callback
662 * handler.
663 * @cb_idx: previously registered (via mpt_register) callback handle
664 * @ev_cbfunc: callback function
666 * This routine can be called by one or more protocol-specific drivers
667 * if/when they choose to be notified of MPT events.
669 * Returns 0 for success.
672 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
674 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
675 return -1;
677 MptEvHandlers[cb_idx] = ev_cbfunc;
678 return 0;
681 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
683 * mpt_event_deregister - Deregister protocol-specific event callback
684 * handler.
685 * @cb_idx: previously registered callback handle
687 * Each protocol-specific driver should call this routine
688 * when it does not (or can no longer) handle events,
689 * or when it's module is unloaded.
691 void
692 mpt_event_deregister(int cb_idx)
694 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
695 return;
697 MptEvHandlers[cb_idx] = NULL;
700 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
702 * mpt_reset_register - Register protocol-specific IOC reset handler.
703 * @cb_idx: previously registered (via mpt_register) callback handle
704 * @reset_func: reset function
706 * This routine can be called by one or more protocol-specific drivers
707 * if/when they choose to be notified of IOC resets.
709 * Returns 0 for success.
712 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
714 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
715 return -1;
717 MptResetHandlers[cb_idx] = reset_func;
718 return 0;
721 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
723 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
724 * @cb_idx: previously registered callback handle
726 * Each protocol-specific driver should call this routine
727 * when it does not (or can no longer) handle IOC reset handling,
728 * or when it's module is unloaded.
730 void
731 mpt_reset_deregister(int cb_idx)
733 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
734 return;
736 MptResetHandlers[cb_idx] = NULL;
739 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
741 * mpt_device_driver_register - Register device driver hooks
744 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
746 MPT_ADAPTER *ioc;
747 int error=0;
749 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
750 error= -EINVAL;
751 return error;
754 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
756 /* call per pci device probe entry point */
757 list_for_each_entry(ioc, &ioc_list, list) {
758 if(dd_cbfunc->probe) {
759 error = dd_cbfunc->probe(ioc->pcidev,
760 ioc->pcidev->driver->id_table);
761 if(error != 0)
762 return error;
766 return error;
769 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
771 * mpt_device_driver_deregister - DeRegister device driver hooks
773 void
774 mpt_device_driver_deregister(int cb_idx)
776 struct mpt_pci_driver *dd_cbfunc;
777 MPT_ADAPTER *ioc;
779 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
780 return;
782 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
784 list_for_each_entry(ioc, &ioc_list, list) {
785 if (dd_cbfunc->remove)
786 dd_cbfunc->remove(ioc->pcidev);
789 MptDeviceDriverHandlers[cb_idx] = NULL;
793 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
795 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
796 * allocated per MPT adapter.
797 * @handle: Handle of registered MPT protocol driver
798 * @ioc: Pointer to MPT adapter structure
800 * Returns pointer to a MPT request frame or %NULL if none are available
801 * or IOC is not active.
803 MPT_FRAME_HDR*
804 mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
806 MPT_FRAME_HDR *mf;
807 unsigned long flags;
808 u16 req_idx; /* Request index */
810 /* validate handle and ioc identifier */
812 #ifdef MFCNT
813 if (!ioc->active)
814 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
815 #endif
817 /* If interrupts are not attached, do not return a request frame */
818 if (!ioc->active)
819 return NULL;
821 spin_lock_irqsave(&ioc->FreeQlock, flags);
822 if (! Q_IS_EMPTY(&ioc->FreeQ)) {
823 int req_offset;
825 mf = ioc->FreeQ.head;
826 Q_DEL_ITEM(&mf->u.frame.linkage);
827 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
828 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
829 /* u16! */
830 req_idx = cpu_to_le16(req_offset / ioc->req_sz);
831 mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
832 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
833 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
834 #ifdef MFCNT
835 ioc->mfcnt++;
836 #endif
838 else
839 mf = NULL;
840 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
842 #ifdef MFCNT
843 if (mf == NULL)
844 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
845 mfcounter++;
846 if (mfcounter == PRINT_MF_COUNT)
847 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
848 #endif
850 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
851 ioc->name, handle, ioc->id, mf));
852 return mf;
855 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
857 * mpt_put_msg_frame - Send a protocol specific MPT request frame
858 * to a IOC.
859 * @handle: Handle of registered MPT protocol driver
860 * @ioc: Pointer to MPT adapter structure
861 * @mf: Pointer to MPT request frame
863 * This routine posts a MPT request frame to the request post FIFO of a
864 * specific MPT adapter.
866 void
867 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
869 u32 mf_dma_addr;
870 int req_offset;
871 u16 req_idx; /* Request index */
873 /* ensure values are reset properly! */
874 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
875 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
876 /* u16! */
877 req_idx = cpu_to_le16(req_offset / ioc->req_sz);
878 mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
879 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
881 #ifdef MPT_DEBUG_MSG_FRAME
883 u32 *m = mf->u.frame.hwhdr.__hdr;
884 int ii, n;
886 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
887 ioc->name, m);
888 n = ioc->req_sz/4 - 1;
889 while (m[n] == 0)
890 n--;
891 for (ii=0; ii<=n; ii++) {
892 if (ii && ((ii%8)==0))
893 printk("\n" KERN_INFO " ");
894 printk(" %08x", le32_to_cpu(m[ii]));
896 printk("\n");
898 #endif
900 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
901 dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
902 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
905 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
907 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
908 * @handle: Handle of registered MPT protocol driver
909 * @ioc: Pointer to MPT adapter structure
910 * @mf: Pointer to MPT request frame
912 * This routine places a MPT request frame back on the MPT adapter's
913 * FreeQ.
915 void
916 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
918 unsigned long flags;
920 /* Put Request back on FreeQ! */
921 spin_lock_irqsave(&ioc->FreeQlock, flags);
922 Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
923 #ifdef MFCNT
924 ioc->mfcnt--;
925 #endif
926 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
929 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
931 * mpt_add_sge - Place a simple SGE at address pAddr.
932 * @pAddr: virtual address for SGE
933 * @flagslength: SGE flags and data transfer length
934 * @dma_addr: Physical address
936 * This routine places a MPT request frame back on the MPT adapter's
937 * FreeQ.
939 void
940 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
942 if (sizeof(dma_addr_t) == sizeof(u64)) {
943 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
944 u32 tmp = dma_addr & 0xFFFFFFFF;
946 pSge->FlagsLength = cpu_to_le32(flagslength);
947 pSge->Address.Low = cpu_to_le32(tmp);
948 tmp = (u32) ((u64)dma_addr >> 32);
949 pSge->Address.High = cpu_to_le32(tmp);
951 } else {
952 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
953 pSge->FlagsLength = cpu_to_le32(flagslength);
954 pSge->Address = cpu_to_le32(dma_addr);
958 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
960 * mpt_add_chain - Place a chain SGE at address pAddr.
961 * @pAddr: virtual address for SGE
962 * @next: nextChainOffset value (u32's)
963 * @length: length of next SGL segment
964 * @dma_addr: Physical address
966 * This routine places a MPT request frame back on the MPT adapter's
967 * FreeQ.
969 void
970 mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
972 if (sizeof(dma_addr_t) == sizeof(u64)) {
973 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
974 u32 tmp = dma_addr & 0xFFFFFFFF;
976 pChain->Length = cpu_to_le16(length);
977 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
979 pChain->NextChainOffset = next;
981 pChain->Address.Low = cpu_to_le32(tmp);
982 tmp = (u32) ((u64)dma_addr >> 32);
983 pChain->Address.High = cpu_to_le32(tmp);
984 } else {
985 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
986 pChain->Length = cpu_to_le16(length);
987 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
988 pChain->NextChainOffset = next;
989 pChain->Address = cpu_to_le32(dma_addr);
993 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
995 * mpt_send_handshake_request - Send MPT request via doorbell
996 * handshake method.
997 * @handle: Handle of registered MPT protocol driver
998 * @ioc: Pointer to MPT adapter structure
999 * @reqBytes: Size of the request in bytes
1000 * @req: Pointer to MPT request frame
1001 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1003 * This routine is used exclusively to send MptScsiTaskMgmt
1004 * requests since they are required to be sent via doorbell handshake.
1006 * NOTE: It is the callers responsibility to byte-swap fields in the
1007 * request which are greater than 1 byte in size.
1009 * Returns 0 for success, non-zero for failure.
1012 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
1014 int r = 0;
1015 u8 *req_as_bytes;
1016 int ii;
1018 /* State is known to be good upon entering
1019 * this function so issue the bus reset
1020 * request.
1024 * Emulate what mpt_put_msg_frame() does /wrt to sanity
1025 * setting cb_idx/req_idx. But ONLY if this request
1026 * is in proper (pre-alloc'd) request buffer range...
1028 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
1029 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
1030 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
1031 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
1032 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
1035 /* Make sure there are no doorbells */
1036 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1038 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1039 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
1040 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
1042 /* Wait for IOC doorbell int */
1043 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
1044 return ii;
1047 /* Read doorbell and check for active bit */
1048 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
1049 return -5;
1051 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
1052 ioc->name, ii));
1054 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1056 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1057 return -2;
1060 /* Send request via doorbell handshake */
1061 req_as_bytes = (u8 *) req;
1062 for (ii = 0; ii < reqBytes/4; ii++) {
1063 u32 word;
1065 word = ((req_as_bytes[(ii*4) + 0] << 0) |
1066 (req_as_bytes[(ii*4) + 1] << 8) |
1067 (req_as_bytes[(ii*4) + 2] << 16) |
1068 (req_as_bytes[(ii*4) + 3] << 24));
1069 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
1070 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1071 r = -3;
1072 break;
1076 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
1077 r = 0;
1078 else
1079 r = -4;
1081 /* Make sure there are no doorbells */
1082 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1084 return r;
1087 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1089 * mpt_verify_adapter - Given a unique IOC identifier, set pointer to
1090 * the associated MPT adapter structure.
1091 * @iocid: IOC unique identifier (integer)
1092 * @iocpp: Pointer to pointer to IOC adapter
1094 * Returns iocid and sets iocpp.
1097 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1099 MPT_ADAPTER *ioc;
1101 list_for_each_entry(ioc,&ioc_list,list) {
1102 if (ioc->id == iocid) {
1103 *iocpp =ioc;
1104 return iocid;
1108 *iocpp = NULL;
1109 return -1;
1112 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1114 * mptbase_probe - Install a PCI intelligent MPT adapter.
1115 * @pdev: Pointer to pci_dev structure
1117 * This routine performs all the steps necessary to bring the IOC of
1118 * a MPT adapter to a OPERATIONAL state. This includes registering
1119 * memory regions, registering the interrupt, and allocating request
1120 * and reply memory pools.
1122 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1123 * MPT adapter.
1125 * Returns 0 for success, non-zero for failure.
1127 * TODO: Add support for polled controllers
1129 static int __devinit
1130 mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1132 MPT_ADAPTER *ioc;
1133 u8 *mem;
1134 unsigned long mem_phys;
1135 unsigned long port;
1136 u32 msize;
1137 u32 psize;
1138 int ii;
1139 int r = -ENODEV;
1140 u64 mask = 0xffffffffffffffffULL;
1141 u8 revision;
1142 u8 pcixcmd;
1143 static int mpt_ids = 0;
1144 #ifdef CONFIG_PROC_FS
1145 struct proc_dir_entry *dent, *ent;
1146 #endif
1148 if (pci_enable_device(pdev))
1149 return r;
1151 dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1153 if (!pci_set_dma_mask(pdev, mask)) {
1154 dprintk((KERN_INFO MYNAM
1155 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
1156 } else if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {
1157 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1158 return r;
1161 if (!pci_set_consistent_dma_mask(pdev, mask))
1162 dprintk((KERN_INFO MYNAM
1163 ": Using 64 bit consistent mask\n"));
1164 else
1165 dprintk((KERN_INFO MYNAM
1166 ": Not using 64 bit consistent mask\n"));
1168 ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1169 if (ioc == NULL) {
1170 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1171 return -ENOMEM;
1173 memset(ioc, 0, sizeof(MPT_ADAPTER));
1174 ioc->alloc_total = sizeof(MPT_ADAPTER);
1175 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1176 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1178 ioc->pcidev = pdev;
1179 ioc->diagPending = 0;
1180 spin_lock_init(&ioc->diagLock);
1182 /* Initialize the event logging.
1184 ioc->eventTypes = 0; /* None */
1185 ioc->eventContext = 0;
1186 ioc->eventLogSize = 0;
1187 ioc->events = NULL;
1189 #ifdef MFCNT
1190 ioc->mfcnt = 0;
1191 #endif
1193 ioc->cached_fw = NULL;
1195 /* Initilize SCSI Config Data structure
1197 memset(&ioc->spi_data, 0, sizeof(ScsiCfgData));
1199 /* Initialize the running configQ head.
1201 Q_INIT(&ioc->configQ, Q_ITEM);
1203 /* Find lookup slot. */
1204 INIT_LIST_HEAD(&ioc->list);
1205 ioc->id = mpt_ids++;
1207 mem_phys = msize = 0;
1208 port = psize = 0;
1209 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1210 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1211 /* Get I/O space! */
1212 port = pci_resource_start(pdev, ii);
1213 psize = pci_resource_len(pdev,ii);
1214 } else {
1215 /* Get memmap */
1216 mem_phys = pci_resource_start(pdev, ii);
1217 msize = pci_resource_len(pdev,ii);
1218 break;
1221 ioc->mem_size = msize;
1223 if (ii == DEVICE_COUNT_RESOURCE) {
1224 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1225 kfree(ioc);
1226 return -EINVAL;
1229 dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1230 dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1232 mem = NULL;
1233 /* Get logical ptr for PciMem0 space */
1234 /*mem = ioremap(mem_phys, msize);*/
1235 mem = ioremap(mem_phys, 0x100);
1236 if (mem == NULL) {
1237 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1238 kfree(ioc);
1239 return -EINVAL;
1241 ioc->memmap = mem;
1242 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1244 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1245 &ioc->facts, &ioc->pfacts[0]));
1247 ioc->mem_phys = mem_phys;
1248 ioc->chip = (SYSIF_REGS*)mem;
1250 /* Save Port IO values in case we need to do downloadboot */
1252 u8 *pmem = (u8*)port;
1253 ioc->pio_mem_phys = port;
1254 ioc->pio_chip = (SYSIF_REGS*)pmem;
1257 ioc->chip_type = FCUNK;
1258 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1259 ioc->chip_type = FC909;
1260 ioc->prod_name = "LSIFC909";
1262 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1263 ioc->chip_type = FC929;
1264 ioc->prod_name = "LSIFC929";
1266 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1267 ioc->chip_type = FC919;
1268 ioc->prod_name = "LSIFC919";
1270 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1271 ioc->chip_type = FC929X;
1272 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1273 if (revision < XL_929) {
1274 ioc->prod_name = "LSIFC929X";
1275 /* 929X Chip Fix. Set Split transactions level
1276 * for PCIX. Set MOST bits to zero.
1278 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1279 pcixcmd &= 0x8F;
1280 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1281 } else {
1282 ioc->prod_name = "LSIFC929XL";
1283 /* 929XL Chip Fix. Set MMRBC to 0x08.
1285 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1286 pcixcmd |= 0x08;
1287 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1290 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1291 ioc->chip_type = FC919X;
1292 ioc->prod_name = "LSIFC919X";
1293 /* 919X Chip Fix. Set Split transactions level
1294 * for PCIX. Set MOST bits to zero.
1296 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1297 pcixcmd &= 0x8F;
1298 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1300 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1301 ioc->chip_type = C1030;
1302 ioc->prod_name = "LSI53C1030";
1303 /* 1030 Chip Fix. Disable Split transactions
1304 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1306 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1307 if (revision < C0_1030) {
1308 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1309 pcixcmd &= 0x8F;
1310 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1313 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1314 ioc->chip_type = C1035;
1315 ioc->prod_name = "LSI53C1035";
1318 sprintf(ioc->name, "ioc%d", ioc->id);
1320 spin_lock_init(&ioc->FreeQlock);
1322 /* Disable all! */
1323 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1324 ioc->active = 0;
1325 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1327 /* Set lookup ptr. */
1328 list_add_tail(&ioc->list, &ioc_list);
1330 ioc->pci_irq = -1;
1331 if (pdev->irq) {
1332 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1334 if (r < 0) {
1335 #ifndef __sparc__
1336 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n",
1337 ioc->name, pdev->irq);
1338 #else
1339 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
1340 ioc->name, __irq_itoa(pdev->irq));
1341 #endif
1342 list_del(&ioc->list);
1343 iounmap(mem);
1344 kfree(ioc);
1345 return -EBUSY;
1348 ioc->pci_irq = pdev->irq;
1350 pci_set_master(pdev); /* ?? */
1351 pci_set_drvdata(pdev, ioc);
1353 #ifndef __sparc__
1354 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
1355 #else
1356 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));
1357 #endif
1360 /* NEW! 20010220 -sralston
1361 * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1363 if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030)
1364 || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X))
1365 mpt_detect_bound_ports(ioc, pdev);
1367 if ((r = mpt_do_ioc_recovery(ioc,
1368 MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) {
1369 printk(KERN_WARNING MYNAM
1370 ": WARNING - %s did not initialize properly! (%d)\n",
1371 ioc->name, r);
1373 list_del(&ioc->list);
1374 free_irq(ioc->pci_irq, ioc);
1375 iounmap(mem);
1376 kfree(ioc);
1377 pci_set_drvdata(pdev, NULL);
1378 return r;
1381 /* call per device driver probe entry point */
1382 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1383 if(MptDeviceDriverHandlers[ii] &&
1384 MptDeviceDriverHandlers[ii]->probe) {
1385 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1389 #ifdef CONFIG_PROC_FS
1391 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1393 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1394 if (dent) {
1395 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1396 if (ent) {
1397 ent->read_proc = procmpt_iocinfo_read;
1398 ent->data = ioc;
1400 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1401 if (ent) {
1402 ent->read_proc = procmpt_summary_read;
1403 ent->data = ioc;
1406 #endif
1408 return 0;
1411 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1413 * mptbase_remove - Remove a PCI intelligent MPT adapter.
1414 * @pdev: Pointer to pci_dev structure
1418 static void __devexit
1419 mptbase_remove(struct pci_dev *pdev)
1421 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1422 char pname[32];
1423 int ii;
1425 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1426 remove_proc_entry(pname, NULL);
1427 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1428 remove_proc_entry(pname, NULL);
1429 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1430 remove_proc_entry(pname, NULL);
1432 /* call per device driver remove entry point */
1433 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1434 if(MptDeviceDriverHandlers[ii] &&
1435 MptDeviceDriverHandlers[ii]->remove) {
1436 MptDeviceDriverHandlers[ii]->remove(pdev);
1440 /* Disable interrupts! */
1441 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1443 ioc->active = 0;
1444 synchronize_irq(pdev->irq);
1446 /* Clear any lingering interrupt */
1447 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1449 CHIPREG_READ32(&ioc->chip->IntStatus);
1451 mpt_adapter_dispose(ioc);
1453 pci_set_drvdata(pdev, NULL);
1456 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1458 * mptbase_shutdown -
1461 static void
1462 mptbase_shutdown(struct device * dev)
1464 int ii;
1466 /* call per device driver shutdown entry point */
1467 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1468 if(MptDeviceDriverHandlers[ii] &&
1469 MptDeviceDriverHandlers[ii]->shutdown) {
1470 MptDeviceDriverHandlers[ii]->shutdown(dev);
1477 /**************************************************************************
1478 * Power Management
1480 #ifdef CONFIG_PM
1481 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1483 * mptbase_suspend - Fusion MPT base driver suspend routine.
1487 static int
1488 mptbase_suspend(struct pci_dev *pdev, u32 state)
1490 u32 device_state;
1491 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1492 int ii;
1494 switch(state)
1496 case 1: /* S1 */
1497 device_state=1; /* D1 */;
1498 break;
1499 case 3: /* S3 */
1500 case 4: /* S4 */
1501 device_state=3; /* D3 */;
1502 break;
1503 default:
1504 return -EAGAIN /*FIXME*/;
1505 break;
1508 printk(MYIOC_s_INFO_FMT
1509 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1510 ioc->name, pdev, pci_name(pdev), device_state);
1512 /* call per device driver suspend entry point */
1513 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1514 if(MptDeviceDriverHandlers[ii] &&
1515 MptDeviceDriverHandlers[ii]->suspend) {
1516 MptDeviceDriverHandlers[ii]->suspend(pdev, state);
1520 pci_save_state(pdev, ioc->PciState);
1522 /* put ioc into READY_STATE */
1523 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1524 printk(MYIOC_s_ERR_FMT
1525 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1528 /* disable interrupts */
1529 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1530 ioc->active = 0;
1532 /* Clear any lingering interrupt */
1533 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1535 pci_disable_device(pdev);
1536 pci_set_power_state(pdev, device_state);
1538 return 0;
1541 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1543 * mptbase_resume - Fusion MPT base driver resume routine.
1547 static int
1548 mptbase_resume(struct pci_dev *pdev)
1550 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1551 u32 device_state = pdev->current_state;
1552 int recovery_state;
1553 int ii;
1555 printk(MYIOC_s_INFO_FMT
1556 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1557 ioc->name, pdev, pci_name(pdev), device_state);
1559 pci_set_power_state(pdev, 0);
1560 pci_restore_state(pdev, ioc->PciState);
1561 pci_enable_device(pdev);
1563 /* enable interrupts */
1564 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1565 ioc->active = 1;
1567 /* F/W not running */
1568 if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
1569 /* enable domain validation flags */
1570 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
1571 ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
1575 printk(MYIOC_s_INFO_FMT
1576 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1577 ioc->name,
1578 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1579 CHIPREG_READ32(&ioc->chip->Doorbell));
1581 /* bring ioc to operational state */
1582 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1583 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1584 printk(MYIOC_s_INFO_FMT
1585 "pci-resume: Cannot recover, error:[%x]\n",
1586 ioc->name, recovery_state);
1587 } else {
1588 printk(MYIOC_s_INFO_FMT
1589 "pci-resume: success\n", ioc->name);
1592 /* call per device driver resume entry point */
1593 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1594 if(MptDeviceDriverHandlers[ii] &&
1595 MptDeviceDriverHandlers[ii]->resume) {
1596 MptDeviceDriverHandlers[ii]->resume(pdev);
1600 return 0;
1602 #endif
1604 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1606 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1607 * @ioc: Pointer to MPT adapter structure
1608 * @reason: Event word / reason
1609 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1611 * This routine performs all the steps necessary to bring the IOC
1612 * to a OPERATIONAL state.
1614 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1615 * MPT adapter.
1617 * Returns:
1618 * 0 for success
1619 * -1 if failed to get board READY
1620 * -2 if READY but IOCFacts Failed
1621 * -3 if READY but PrimeIOCFifos Failed
1622 * -4 if READY but IOCInit Failed
1624 static int
1625 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1627 int hard_reset_done = 0;
1628 int alt_ioc_ready = 0;
1629 int hard;
1630 int rc=0;
1631 int ii;
1632 int handlers;
1633 int ret = 0;
1634 int reset_alt_ioc_active = 0;
1636 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1637 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1639 /* Disable reply interrupts (also blocks FreeQ) */
1640 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1641 ioc->active = 0;
1643 if (ioc->alt_ioc) {
1644 if (ioc->alt_ioc->active)
1645 reset_alt_ioc_active = 1;
1647 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1648 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1649 ioc->alt_ioc->active = 0;
1652 hard = 1;
1653 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1654 hard = 0;
1656 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1657 if (hard_reset_done == -4) {
1658 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1659 ioc->name);
1661 if (reset_alt_ioc_active && ioc->alt_ioc) {
1662 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1663 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1664 ioc->alt_ioc->name));
1665 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
1666 ioc->alt_ioc->active = 1;
1669 } else {
1670 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1671 ioc->name);
1673 return -1;
1676 /* hard_reset_done = 0 if a soft reset was performed
1677 * and 1 if a hard reset was performed.
1679 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1680 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1681 alt_ioc_ready = 1;
1682 else
1683 printk(KERN_WARNING MYNAM
1684 ": alt-%s: Not ready WARNING!\n",
1685 ioc->alt_ioc->name);
1688 for (ii=0; ii<5; ii++) {
1689 /* Get IOC facts! Allow 5 retries */
1690 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1691 break;
1695 if (ii == 5) {
1696 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1697 ret = -2;
1698 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1699 MptDisplayIocCapabilities(ioc);
1702 if (alt_ioc_ready) {
1703 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1704 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1705 /* Retry - alt IOC was initialized once
1707 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1709 if (rc) {
1710 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1711 alt_ioc_ready = 0;
1712 reset_alt_ioc_active = 0;
1713 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1714 MptDisplayIocCapabilities(ioc->alt_ioc);
1718 /* Prime reply & request queues!
1719 * (mucho alloc's) Must be done prior to
1720 * init as upper addresses are needed for init.
1721 * If fails, continue with alt-ioc processing
1723 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1724 ret = -3;
1726 /* May need to check/upload firmware & data here!
1727 * If fails, continue with alt-ioc processing
1729 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1730 ret = -4;
1731 // NEW!
1732 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1733 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1734 ioc->alt_ioc->name, rc);
1735 alt_ioc_ready = 0;
1736 reset_alt_ioc_active = 0;
1739 if (alt_ioc_ready) {
1740 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1741 alt_ioc_ready = 0;
1742 reset_alt_ioc_active = 0;
1743 printk(KERN_WARNING MYNAM
1744 ": alt-%s: (%d) init failure WARNING!\n",
1745 ioc->alt_ioc->name, rc);
1749 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1750 if (ioc->upload_fw) {
1751 ddlprintk((MYIOC_s_INFO_FMT
1752 "firmware upload required!\n", ioc->name));
1754 /* Controller is not operational, cannot do upload
1756 if (ret == 0) {
1757 rc = mpt_do_upload(ioc, sleepFlag);
1758 if (rc != 0)
1759 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
1764 if (ret == 0) {
1765 /* Enable! (reply interrupt) */
1766 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1767 ioc->active = 1;
1770 if (reset_alt_ioc_active && ioc->alt_ioc) {
1771 /* (re)Enable alt-IOC! (reply interrupt) */
1772 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1773 ioc->alt_ioc->name));
1774 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
1775 ioc->alt_ioc->active = 1;
1778 /* NEW! 20010120 -sralston
1779 * Enable MPT base driver management of EventNotification
1780 * and EventAck handling.
1782 if ((ret == 0) && (!ioc->facts.EventState))
1783 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1785 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1786 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1788 /* (Bugzilla:fibrebugs, #513)
1789 * Bug fix (part 2)! 20010905 -sralston
1790 * Add additional "reason" check before call to GetLanConfigPages
1791 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1792 * recursive scenario; GetLanConfigPages times out, timer expired
1793 * routine calls HardResetHandler, which calls into here again,
1794 * and we try GetLanConfigPages again...
1796 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
1797 if ((int)ioc->chip_type <= (int)FC929) {
1799 * Pre-fetch FC port WWN and stuff...
1800 * (FCPortPage0_t stuff)
1802 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1803 (void) GetFcPortPage0(ioc, ii);
1806 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1807 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1809 * Pre-fetch the ports LAN MAC address!
1810 * (LANPage1_t stuff)
1812 (void) GetLanConfigPages(ioc);
1813 #ifdef MPT_DEBUG
1815 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1816 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1817 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1819 #endif
1821 } else {
1822 /* Get NVRAM and adapter maximums from SPP 0 and 2
1824 mpt_GetScsiPortSettings(ioc, 0);
1826 /* Get version and length of SDP 1
1828 mpt_readScsiDevicePageHeaders(ioc, 0);
1830 /* Find IM volumes
1832 if (ioc->facts.MsgVersion >= 0x0102)
1833 mpt_findImVolumes(ioc);
1835 /* Check, and possibly reset, the coalescing value
1837 mpt_read_ioc_pg_1(ioc);
1839 mpt_read_ioc_pg_4(ioc);
1842 GetIoUnitPage2(ioc);
1846 * Call each currently registered protocol IOC reset handler
1847 * with post-reset indication.
1848 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1849 * MptResetHandlers[] registered yet.
1851 if (hard_reset_done) {
1852 rc = handlers = 0;
1853 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1854 if ((ret == 0) && MptResetHandlers[ii]) {
1855 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1856 ioc->name, ii));
1857 rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
1858 handlers++;
1861 if (alt_ioc_ready && MptResetHandlers[ii]) {
1862 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1863 ioc->name, ioc->alt_ioc->name, ii));
1864 rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
1865 handlers++;
1868 /* FIXME? Examine results here? */
1871 return ret;
1874 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1876 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1877 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1878 * 929X, 1030 or 1035.
1879 * @ioc: Pointer to MPT adapter structure
1880 * @pdev: Pointer to (struct pci_dev) structure
1882 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1883 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1885 static void
1886 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1888 unsigned int match_lo, match_hi;
1889 MPT_ADAPTER *ioc_srch;
1891 match_lo = pdev->devfn-1;
1892 match_hi = pdev->devfn+1;
1893 dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
1894 ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi));
1896 list_for_each_entry(ioc_srch, &ioc_list, list) {
1897 struct pci_dev *_pcidev = ioc_srch->pcidev;
1899 if ((_pcidev->device == pdev->device) &&
1900 (_pcidev->bus->number == pdev->bus->number) &&
1901 (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
1902 /* Paranoia checks */
1903 if (ioc->alt_ioc != NULL) {
1904 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1905 ioc->name, ioc->alt_ioc->name);
1906 break;
1907 } else if (ioc_srch->alt_ioc != NULL) {
1908 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1909 ioc_srch->name, ioc_srch->alt_ioc->name);
1910 break;
1912 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1913 ioc->name, ioc_srch->name));
1914 ioc_srch->alt_ioc = ioc;
1915 ioc->alt_ioc = ioc_srch;
1916 break;
1921 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1923 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1924 * @this: Pointer to MPT adapter structure
1926 static void
1927 mpt_adapter_disable(MPT_ADAPTER *ioc)
1929 int sz;
1930 int ret;
1932 if (ioc->cached_fw != NULL) {
1933 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
1934 if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) {
1935 printk(KERN_WARNING MYNAM
1936 ": firmware downloadboot failure (%d)!\n", ret);
1940 /* Disable adapter interrupts! */
1941 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1942 ioc->active = 0;
1943 /* Clear any lingering interrupt */
1944 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1946 if (ioc->alloc != NULL) {
1947 sz = ioc->alloc_sz;
1948 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
1949 ioc->name, ioc->alloc, ioc->alloc_sz));
1950 pci_free_consistent(ioc->pcidev, sz,
1951 ioc->alloc, ioc->alloc_dma);
1952 ioc->reply_frames = NULL;
1953 ioc->req_frames = NULL;
1954 ioc->alloc = NULL;
1955 ioc->alloc_total -= sz;
1958 if (ioc->sense_buf_pool != NULL) {
1959 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
1960 pci_free_consistent(ioc->pcidev, sz,
1961 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
1962 ioc->sense_buf_pool = NULL;
1963 ioc->alloc_total -= sz;
1966 if (ioc->events != NULL){
1967 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
1968 kfree(ioc->events);
1969 ioc->events = NULL;
1970 ioc->alloc_total -= sz;
1973 if (ioc->cached_fw != NULL) {
1974 sz = ioc->facts.FWImageSize;
1975 pci_free_consistent(ioc->pcidev, sz,
1976 ioc->cached_fw, ioc->cached_fw_dma);
1977 ioc->cached_fw = NULL;
1978 ioc->alloc_total -= sz;
1981 if (ioc->spi_data.nvram != NULL) {
1982 kfree(ioc->spi_data.nvram);
1983 ioc->spi_data.nvram = NULL;
1986 if (ioc->spi_data.pIocPg3 != NULL) {
1987 kfree(ioc->spi_data.pIocPg3);
1988 ioc->spi_data.pIocPg3 = NULL;
1991 if (ioc->spi_data.pIocPg4 != NULL) {
1992 sz = ioc->spi_data.IocPg4Sz;
1993 pci_free_consistent(ioc->pcidev, sz,
1994 ioc->spi_data.pIocPg4,
1995 ioc->spi_data.IocPg4_dma);
1996 ioc->spi_data.pIocPg4 = NULL;
1997 ioc->alloc_total -= sz;
2000 if (ioc->ReqToChain != NULL) {
2001 kfree(ioc->ReqToChain);
2002 kfree(ioc->RequestNB);
2003 ioc->ReqToChain = NULL;
2006 if (ioc->ChainToChain != NULL) {
2007 kfree(ioc->ChainToChain);
2008 ioc->ChainToChain = NULL;
2012 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2014 * mpt_adapter_dispose - Free all resources associated with a MPT
2015 * adapter.
2016 * @ioc: Pointer to MPT adapter structure
2018 * This routine unregisters h/w resources and frees all alloc'd memory
2019 * associated with a MPT adapter structure.
2021 static void
2022 mpt_adapter_dispose(MPT_ADAPTER *ioc)
2024 if (ioc != NULL) {
2025 int sz_first, sz_last;
2027 sz_first = ioc->alloc_total;
2029 mpt_adapter_disable(ioc);
2031 if (ioc->pci_irq != -1) {
2032 free_irq(ioc->pci_irq, ioc);
2033 ioc->pci_irq = -1;
2036 if (ioc->memmap != NULL)
2037 iounmap((u8 *) ioc->memmap);
2039 #if defined(CONFIG_MTRR) && 0
2040 if (ioc->mtrr_reg > 0) {
2041 mtrr_del(ioc->mtrr_reg, 0, 0);
2042 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2044 #endif
2046 /* Zap the adapter lookup ptr! */
2047 list_del(&ioc->list);
2049 sz_last = ioc->alloc_total;
2050 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2051 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2052 kfree(ioc);
2056 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2058 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2059 * @ioc: Pointer to MPT adapter structure
2061 static void
2062 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2064 int i = 0;
2066 printk(KERN_INFO "%s: ", ioc->name);
2067 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2068 printk("%s: ", ioc->prod_name+3);
2069 printk("Capabilities={");
2071 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2072 printk("Initiator");
2073 i++;
2076 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2077 printk("%sTarget", i ? "," : "");
2078 i++;
2081 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2082 printk("%sLAN", i ? "," : "");
2083 i++;
2086 #if 0
2088 * This would probably evoke more questions than it's worth
2090 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2091 printk("%sLogBusAddr", i ? "," : "");
2092 i++;
2094 #endif
2096 printk("}\n");
2099 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2101 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2102 * @ioc: Pointer to MPT_ADAPTER structure
2103 * @force: Force hard KickStart of IOC
2104 * @sleepFlag: Specifies whether the process can sleep
2106 * Returns:
2107 * 1 - DIAG reset and READY
2108 * 0 - READY initially OR soft reset and READY
2109 * -1 - Any failure on KickStart
2110 * -2 - Msg Unit Reset Failed
2111 * -3 - IO Unit Reset Failed
2112 * -4 - IOC owned by a PEER
2114 static int
2115 MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2117 u32 ioc_state;
2118 int statefault = 0;
2119 int cntdn;
2120 int hard_reset_done = 0;
2121 int r;
2122 int ii;
2123 int whoinit;
2125 /* Get current [raw] IOC state */
2126 ioc_state = mpt_GetIocState(ioc, 0);
2127 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2130 * Check to see if IOC got left/stuck in doorbell handshake
2131 * grip of death. If so, hard reset the IOC.
2133 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2134 statefault = 1;
2135 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2136 ioc->name);
2139 /* Is it already READY? */
2140 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) {
2141 if ((int)ioc->chip_type <= (int)FC929)
2142 return 0;
2143 else {
2144 return 0;
2145 /* Workaround from broken 1030 FW.
2146 * Force a diagnostic reset if fails.
2148 /* if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2149 return 0;
2150 else
2151 statefault = 4; */
2156 * Check to see if IOC is in FAULT state.
2158 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2159 statefault = 2;
2160 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2161 ioc->name);
2162 printk(KERN_WARNING " FAULT code = %04xh\n",
2163 ioc_state & MPI_DOORBELL_DATA_MASK);
2167 * Hmmm... Did it get left operational?
2169 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2170 dinitprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
2171 ioc->name));
2173 /* Check WhoInit.
2174 * If PCI Peer, exit.
2175 * Else, if no fault conditions are present, issue a MessageUnitReset
2176 * Else, fall through to KickStart case
2178 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2179 dprintk((KERN_WARNING MYNAM
2180 ": whoinit 0x%x\n statefault %d force %d\n",
2181 whoinit, statefault, force));
2182 if (whoinit == MPI_WHOINIT_PCI_PEER)
2183 return -4;
2184 else {
2185 if ((statefault == 0 ) && (force == 0)) {
2186 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2187 return 0;
2189 statefault = 3;
2193 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2194 if (hard_reset_done < 0)
2195 return -1;
2198 * Loop here waiting for IOC to come READY.
2200 ii = 0;
2201 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
2203 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2204 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2206 * BIOS or previous driver load left IOC in OP state.
2207 * Reset messaging FIFOs.
2209 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2210 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2211 return -2;
2213 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2215 * Something is wrong. Try to get IOC back
2216 * to a known state.
2218 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2219 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2220 return -3;
2224 ii++; cntdn--;
2225 if (!cntdn) {
2226 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2227 ioc->name, (int)((ii+5)/HZ));
2228 return -ETIME;
2231 if (sleepFlag == CAN_SLEEP) {
2232 set_current_state(TASK_INTERRUPTIBLE);
2233 schedule_timeout(1 * HZ / 1000);
2234 } else {
2235 mdelay (1); /* 1 msec delay */
2240 if (statefault < 3) {
2241 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2242 ioc->name,
2243 statefault==1 ? "stuck handshake" : "IOC FAULT");
2246 return hard_reset_done;
2249 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2251 * mpt_GetIocState - Get the current state of a MPT adapter.
2252 * @ioc: Pointer to MPT_ADAPTER structure
2253 * @cooked: Request raw or cooked IOC state
2255 * Returns all IOC Doorbell register bits if cooked==0, else just the
2256 * Doorbell bits in MPI_IOC_STATE_MASK.
2259 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2261 u32 s, sc;
2263 /* Get! */
2264 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2265 // dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2266 sc = s & MPI_IOC_STATE_MASK;
2268 /* Save! */
2269 ioc->last_state = sc;
2271 return cooked ? sc : s;
2274 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2276 * GetIocFacts - Send IOCFacts request to MPT adapter.
2277 * @ioc: Pointer to MPT_ADAPTER structure
2278 * @sleepFlag: Specifies whether the process can sleep
2279 * @reason: If recovery, only update facts.
2281 * Returns 0 for success, non-zero for failure.
2283 static int
2284 GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2286 IOCFacts_t get_facts;
2287 IOCFactsReply_t *facts;
2288 int r;
2289 int req_sz;
2290 int reply_sz;
2291 int sz;
2292 u32 status, vv;
2293 u8 shiftFactor=1;
2295 /* IOC *must* NOT be in RESET state! */
2296 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2297 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2298 ioc->name,
2299 ioc->last_state );
2300 return -44;
2303 facts = &ioc->facts;
2305 /* Destination (reply area)... */
2306 reply_sz = sizeof(*facts);
2307 memset(facts, 0, reply_sz);
2309 /* Request area (get_facts on the stack right now!) */
2310 req_sz = sizeof(get_facts);
2311 memset(&get_facts, 0, req_sz);
2313 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2314 /* Assert: All other get_facts fields are zero! */
2316 dinitprintk((MYIOC_s_INFO_FMT
2317 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2318 ioc->name, req_sz, reply_sz));
2320 /* No non-zero fields in the get_facts request are greater than
2321 * 1 byte in size, so we can just fire it off as is.
2323 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2324 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2325 if (r != 0)
2326 return r;
2329 * Now byte swap (GRRR) the necessary fields before any further
2330 * inspection of reply contents.
2332 * But need to do some sanity checks on MsgLength (byte) field
2333 * to make sure we don't zero IOC's req_sz!
2335 /* Did we get a valid reply? */
2336 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2337 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2339 * If not been here, done that, save off first WhoInit value
2341 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2342 ioc->FirstWhoInit = facts->WhoInit;
2345 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2346 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2347 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2348 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2349 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2350 status = facts->IOCStatus & MPI_IOCSTATUS_MASK;
2351 /* CHECKME! IOCStatus, IOCLogInfo */
2353 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2354 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2357 * FC f/w version changed between 1.1 and 1.2
2358 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2359 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2361 if (facts->MsgVersion < 0x0102) {
2363 * Handle old FC f/w style, convert to new...
2365 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2366 facts->FWVersion.Word =
2367 ((oldv<<12) & 0xFF000000) |
2368 ((oldv<<8) & 0x000FFF00);
2369 } else
2370 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2372 facts->ProductID = le16_to_cpu(facts->ProductID);
2373 facts->CurrentHostMfaHighAddr =
2374 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2375 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2376 facts->CurrentSenseBufferHighAddr =
2377 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2378 facts->CurReplyFrameSize =
2379 le16_to_cpu(facts->CurReplyFrameSize);
2382 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2383 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2384 * to 14 in MPI-1.01.0x.
2386 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2387 facts->MsgVersion > 0x0100) {
2388 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2391 sz = facts->FWImageSize;
2392 if ( sz & 0x01 )
2393 sz += 1;
2394 if ( sz & 0x02 )
2395 sz += 2;
2396 facts->FWImageSize = sz;
2398 if (!facts->RequestFrameSize) {
2399 /* Something is wrong! */
2400 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2401 ioc->name);
2402 return -55;
2405 r = sz = le32_to_cpu(facts->BlockSize);
2406 vv = ((63 / (sz * 4)) + 1) & 0x03;
2407 ioc->NB_for_64_byte_frame = vv;
2408 while ( sz )
2410 shiftFactor++;
2411 sz = sz >> 1;
2413 ioc->NBShiftFactor = shiftFactor;
2414 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2415 ioc->name, vv, shiftFactor, r));
2417 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2419 * Set values for this IOC's request & reply frame sizes,
2420 * and request & reply queue depths...
2422 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2423 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2424 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2425 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2427 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2428 ioc->name, ioc->reply_sz, ioc->reply_depth));
2429 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2430 ioc->name, ioc->req_sz, ioc->req_depth));
2432 /* Get port facts! */
2433 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2434 return r;
2436 } else {
2437 printk(MYIOC_s_ERR_FMT
2438 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2439 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2440 RequestFrameSize)/sizeof(u32)));
2441 return -66;
2444 return 0;
2447 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2449 * GetPortFacts - Send PortFacts request to MPT adapter.
2450 * @ioc: Pointer to MPT_ADAPTER structure
2451 * @portnum: Port number
2452 * @sleepFlag: Specifies whether the process can sleep
2454 * Returns 0 for success, non-zero for failure.
2456 static int
2457 GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2459 PortFacts_t get_pfacts;
2460 PortFactsReply_t *pfacts;
2461 int ii;
2462 int req_sz;
2463 int reply_sz;
2465 /* IOC *must* NOT be in RESET state! */
2466 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2467 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2468 ioc->name,
2469 ioc->last_state );
2470 return -4;
2473 pfacts = &ioc->pfacts[portnum];
2475 /* Destination (reply area)... */
2476 reply_sz = sizeof(*pfacts);
2477 memset(pfacts, 0, reply_sz);
2479 /* Request area (get_pfacts on the stack right now!) */
2480 req_sz = sizeof(get_pfacts);
2481 memset(&get_pfacts, 0, req_sz);
2483 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2484 get_pfacts.PortNumber = portnum;
2485 /* Assert: All other get_pfacts fields are zero! */
2487 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2488 ioc->name, portnum));
2490 /* No non-zero fields in the get_pfacts request are greater than
2491 * 1 byte in size, so we can just fire it off as is.
2493 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2494 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2495 if (ii != 0)
2496 return ii;
2498 /* Did we get a valid reply? */
2500 /* Now byte swap the necessary fields in the response. */
2501 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2502 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2503 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2504 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2505 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2506 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2507 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2508 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2509 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2511 return 0;
2514 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2516 * SendIocInit - Send IOCInit request to MPT adapter.
2517 * @ioc: Pointer to MPT_ADAPTER structure
2518 * @sleepFlag: Specifies whether the process can sleep
2520 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2522 * Returns 0 for success, non-zero for failure.
2524 static int
2525 SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2527 IOCInit_t ioc_init;
2528 MPIDefaultReply_t init_reply;
2529 u32 state;
2530 int r;
2531 int count;
2532 int cntdn;
2534 memset(&ioc_init, 0, sizeof(ioc_init));
2535 memset(&init_reply, 0, sizeof(init_reply));
2537 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2538 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2540 /* If we are in a recovery mode and we uploaded the FW image,
2541 * then this pointer is not NULL. Skip the upload a second time.
2542 * Set this flag if cached_fw set for either IOC.
2544 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2545 ioc->upload_fw = 1;
2546 else
2547 ioc->upload_fw = 0;
2548 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2549 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2551 if ((int)ioc->chip_type <= (int)FC929) {
2552 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2553 } else {
2554 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
2556 ioc_init.MaxBuses = MPT_MAX_BUS;
2558 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2560 if (sizeof(dma_addr_t) == sizeof(u64)) {
2561 /* Save the upper 32-bits of the request
2562 * (reply) and sense buffers.
2564 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2565 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2566 } else {
2567 /* Force 32-bit addressing */
2568 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2569 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2572 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2573 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
2575 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2576 ioc->name, &ioc_init));
2578 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2579 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
2580 if (r != 0)
2581 return r;
2583 /* No need to byte swap the multibyte fields in the reply
2584 * since we don't even look at it's contents.
2587 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2588 ioc->name, &ioc_init));
2590 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0)
2591 return r;
2593 /* YIKES! SUPER IMPORTANT!!!
2594 * Poll IocState until _OPERATIONAL while IOC is doing
2595 * LoopInit and TargetDiscovery!
2597 count = 0;
2598 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2599 state = mpt_GetIocState(ioc, 1);
2600 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2601 if (sleepFlag == CAN_SLEEP) {
2602 set_current_state(TASK_INTERRUPTIBLE);
2603 schedule_timeout(1 * HZ / 1000);
2604 } else {
2605 mdelay(1);
2608 if (!cntdn) {
2609 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2610 ioc->name, (int)((count+5)/HZ));
2611 return -9;
2614 state = mpt_GetIocState(ioc, 1);
2615 count++;
2617 dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
2618 ioc->name, count));
2620 return r;
2623 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2625 * SendPortEnable - Send PortEnable request to MPT adapter port.
2626 * @ioc: Pointer to MPT_ADAPTER structure
2627 * @portnum: Port number to enable
2628 * @sleepFlag: Specifies whether the process can sleep
2630 * Send PortEnable to bring IOC to OPERATIONAL state.
2632 * Returns 0 for success, non-zero for failure.
2634 static int
2635 SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2637 PortEnable_t port_enable;
2638 MPIDefaultReply_t reply_buf;
2639 int ii;
2640 int req_sz;
2641 int reply_sz;
2643 /* Destination... */
2644 reply_sz = sizeof(MPIDefaultReply_t);
2645 memset(&reply_buf, 0, reply_sz);
2647 req_sz = sizeof(PortEnable_t);
2648 memset(&port_enable, 0, req_sz);
2650 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2651 port_enable.PortNumber = portnum;
2652 /* port_enable.ChainOffset = 0; */
2653 /* port_enable.MsgFlags = 0; */
2654 /* port_enable.MsgContext = 0; */
2656 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2657 ioc->name, portnum, &port_enable));
2659 /* RAID FW may take a long time to enable
2661 if ((int)ioc->chip_type <= (int)FC929) {
2662 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
2663 reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag);
2664 } else {
2665 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
2666 reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
2669 if (ii != 0)
2670 return ii;
2672 /* We do not even look at the reply, so we need not
2673 * swap the multi-byte fields.
2676 return 0;
2680 * ioc: Pointer to MPT_ADAPTER structure
2681 * size - total FW bytes
2683 void
2684 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2686 if (ioc->cached_fw)
2687 return; /* use already allocated memory */
2688 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2689 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2690 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2691 } else {
2692 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2693 ioc->alloc_total += size;
2697 * If alt_img is NULL, delete from ioc structure.
2698 * Else, delete a secondary image in same format.
2700 void
2701 mpt_free_fw_memory(MPT_ADAPTER *ioc)
2703 int sz;
2705 sz = ioc->facts.FWImageSize;
2706 dinitprintk((KERN_WARNING MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
2707 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2708 pci_free_consistent(ioc->pcidev, sz,
2709 ioc->cached_fw, ioc->cached_fw_dma);
2710 ioc->cached_fw = NULL;
2712 return;
2716 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2718 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2719 * @ioc: Pointer to MPT_ADAPTER structure
2720 * @sleepFlag: Specifies whether the process can sleep
2722 * Returns 0 for success, >0 for handshake failure
2723 * <0 for fw upload failure.
2725 * Remark: If bound IOC and a successful FWUpload was performed
2726 * on the bound IOC, the second image is discarded
2727 * and memory is free'd. Both channels must upload to prevent
2728 * IOC from running in degraded mode.
2730 static int
2731 mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2733 u8 request[ioc->req_sz];
2734 u8 reply[sizeof(FWUploadReply_t)];
2735 FWUpload_t *prequest;
2736 FWUploadReply_t *preply;
2737 FWUploadTCSGE_t *ptcsge;
2738 int sgeoffset;
2739 u32 flagsLength;
2740 int ii, sz, reply_sz;
2741 int cmdStatus;
2743 /* If the image size is 0, we are done.
2745 if ((sz = ioc->facts.FWImageSize) == 0)
2746 return 0;
2748 mpt_alloc_fw_memory(ioc, sz);
2750 dinitprintk((KERN_WARNING MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
2751 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2753 if (ioc->cached_fw == NULL) {
2754 /* Major Failure.
2756 return -ENOMEM;
2759 prequest = (FWUpload_t *)&request;
2760 preply = (FWUploadReply_t *)&reply;
2762 /* Destination... */
2763 memset(prequest, 0, ioc->req_sz);
2765 reply_sz = sizeof(reply);
2766 memset(preply, 0, reply_sz);
2768 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2769 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2771 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2772 ptcsge->DetailsLength = 12;
2773 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2774 ptcsge->ImageSize = cpu_to_le32(sz);
2776 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2778 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2779 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2781 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
2782 dinitprintk((KERN_WARNING MYNAM "Sending FW Upload (req @ %p) sgeoffset=%d \n",
2783 prequest, sgeoffset));
2784 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2786 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2787 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2789 dinitprintk((KERN_WARNING MYNAM "FW Upload completed rc=%x \n", ii));
2791 cmdStatus = -EFAULT;
2792 if (ii == 0) {
2793 /* Handshake transfer was complete and successful.
2794 * Check the Reply Frame.
2796 int status, transfer_sz;
2797 status = le16_to_cpu(preply->IOCStatus);
2798 if (status == MPI_IOCSTATUS_SUCCESS) {
2799 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2800 if (transfer_sz == sz)
2801 cmdStatus = 0;
2804 dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
2805 ioc->name, cmdStatus));
2808 if (cmdStatus) {
2810 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2811 ioc->name));
2812 mpt_free_fw_memory(ioc);
2815 return cmdStatus;
2818 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2820 * mpt_downloadboot - DownloadBoot code
2821 * @ioc: Pointer to MPT_ADAPTER structure
2822 * @flag: Specify which part of IOC memory is to be uploaded.
2823 * @sleepFlag: Specifies whether the process can sleep
2825 * FwDownloadBoot requires Programmed IO access.
2827 * Returns 0 for success
2828 * -1 FW Image size is 0
2829 * -2 No valid cached_fw Pointer
2830 * <0 for fw upload failure.
2832 static int
2833 mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
2835 MpiFwHeader_t *pFwHeader;
2836 MpiExtImageHeader_t *pExtImage;
2837 u32 fwSize;
2838 u32 diag0val;
2839 int count;
2840 u32 *ptrFw;
2841 u32 diagRwData;
2842 u32 nextImage;
2843 u32 load_addr;
2844 u32 ioc_state=0;
2846 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n",
2847 ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
2849 if ( ioc->facts.FWImageSize == 0 )
2850 return -1;
2852 if (ioc->cached_fw == NULL)
2853 return -2;
2855 /* prevent a second downloadboot and memory free with alt_ioc */
2856 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
2857 ioc->alt_ioc->cached_fw = NULL;
2859 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2860 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2861 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2862 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2863 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2864 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2866 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2868 /* wait 1 msec */
2869 if (sleepFlag == CAN_SLEEP) {
2870 set_current_state(TASK_INTERRUPTIBLE);
2871 schedule_timeout(1 * HZ / 1000);
2872 } else {
2873 mdelay (1);
2876 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2877 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2879 for (count = 0; count < 30; count ++) {
2880 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2881 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2882 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2883 ioc->name, count));
2884 break;
2886 /* wait 1 sec */
2887 if (sleepFlag == CAN_SLEEP) {
2888 set_current_state(TASK_INTERRUPTIBLE);
2889 schedule_timeout(1000 * HZ / 1000);
2890 } else {
2891 mdelay (1000);
2895 if ( count == 30 ) {
2896 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to RESET_ADAPTER diag0val=%x\n",
2897 ioc->name, diag0val));
2898 return -3;
2901 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2902 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2903 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2904 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2905 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2906 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2908 /* Set the DiagRwEn and Disable ARM bits */
2909 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
2911 pFwHeader = (MpiFwHeader_t *) ioc->cached_fw;
2912 fwSize = (pFwHeader->ImageSize + 3)/4;
2913 ptrFw = (u32 *) pFwHeader;
2915 /* Write the LoadStartAddress to the DiagRw Address Register
2916 * using Programmed IO
2918 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
2919 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
2920 ioc->name, pFwHeader->LoadStartAddress));
2922 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
2923 ioc->name, fwSize*4, ptrFw));
2924 while (fwSize--) {
2925 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2928 nextImage = pFwHeader->NextImageHeaderOffset;
2929 while (nextImage) {
2930 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
2932 load_addr = pExtImage->LoadStartAddress;
2934 fwSize = (pExtImage->ImageSize + 3) >> 2;
2935 ptrFw = (u32 *)pExtImage;
2937 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x bytes @ %p load_addr=%x\n",
2938 ioc->name, fwSize*4, ptrFw, load_addr));
2939 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
2941 while (fwSize--) {
2942 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
2944 nextImage = pExtImage->NextImageHeaderOffset;
2947 /* Write the IopResetVectorRegAddr */
2948 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
2949 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
2951 /* Write the IopResetVectorValue */
2952 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
2953 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
2955 /* Clear the internal flash bad bit - autoincrementing register,
2956 * so must do two writes.
2958 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
2959 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
2960 diagRwData |= 0x4000000;
2961 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
2962 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
2964 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2965 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n",
2966 ioc->name, diag0val));
2967 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
2968 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
2969 ioc->name, diag0val));
2970 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
2972 /* Write 0xFF to reset the sequencer */
2973 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2975 for (count=0; count<HZ*20; count++) {
2976 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
2977 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
2978 ioc->name, count, ioc_state));
2979 if ((SendIocInit(ioc, sleepFlag)) != 0) {
2980 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
2981 ioc->name));
2982 return -EFAULT;
2984 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
2985 ioc->name));
2986 return 0;
2988 if (sleepFlag == CAN_SLEEP) {
2989 set_current_state(TASK_INTERRUPTIBLE);
2990 schedule_timeout(10 * HZ / 1000);
2991 } else {
2992 mdelay (10);
2995 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
2996 ioc->name, ioc_state));
2997 return -EFAULT;
3000 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3002 * KickStart - Perform hard reset of MPT adapter.
3003 * @ioc: Pointer to MPT_ADAPTER structure
3004 * @force: Force hard reset
3005 * @sleepFlag: Specifies whether the process can sleep
3007 * This routine places MPT adapter in diagnostic mode via the
3008 * WriteSequence register, and then performs a hard reset of adapter
3009 * via the Diagnostic register.
3011 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3012 * or NO_SLEEP (interrupt thread, use mdelay)
3013 * force - 1 if doorbell active, board fault state
3014 * board operational, IOC_RECOVERY or
3015 * IOC_BRINGUP and there is an alt_ioc.
3016 * 0 else
3018 * Returns:
3019 * 1 - hard reset, READY
3020 * 0 - no reset due to History bit, READY
3021 * -1 - no reset due to History bit but not READY
3022 * OR reset but failed to come READY
3023 * -2 - no reset, could not enter DIAG mode
3024 * -3 - reset but bad FW bit
3026 static int
3027 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3029 int hard_reset_done = 0;
3030 u32 ioc_state=0;
3031 int cnt,cntdn;
3033 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
3034 if ((int)ioc->chip_type > (int)FC929) {
3035 /* Always issue a Msg Unit Reset first. This will clear some
3036 * SCSI bus hang conditions.
3038 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3040 if (sleepFlag == CAN_SLEEP) {
3041 set_current_state(TASK_INTERRUPTIBLE);
3042 schedule_timeout(1000 * HZ / 1000);
3043 } else {
3044 mdelay (1000);
3048 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3049 if (hard_reset_done < 0)
3050 return hard_reset_done;
3052 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3053 ioc->name));
3055 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3056 for (cnt=0; cnt<cntdn; cnt++) {
3057 ioc_state = mpt_GetIocState(ioc, 1);
3058 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3059 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3060 ioc->name, cnt));
3061 return hard_reset_done;
3063 if (sleepFlag == CAN_SLEEP) {
3064 set_current_state(TASK_INTERRUPTIBLE);
3065 schedule_timeout(10 * HZ / 1000);
3066 } else {
3067 mdelay (10);
3071 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3072 ioc->name, ioc_state);
3073 return -1;
3076 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3078 * mpt_diag_reset - Perform hard reset of the adapter.
3079 * @ioc: Pointer to MPT_ADAPTER structure
3080 * @ignore: Set if to honor and clear to ignore
3081 * the reset history bit
3082 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3083 * else set to NO_SLEEP (use mdelay instead)
3085 * This routine places the adapter in diagnostic mode via the
3086 * WriteSequence register and then performs a hard reset of adapter
3087 * via the Diagnostic register. Adapter should be in ready state
3088 * upon successful completion.
3090 * Returns: 1 hard reset successful
3091 * 0 no reset performed because reset history bit set
3092 * -2 enabling diagnostic mode failed
3093 * -3 diagnostic reset failed
3095 static int
3096 mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3098 u32 diag0val;
3099 u32 doorbell;
3100 int hard_reset_done = 0;
3101 int count = 0;
3102 #ifdef MPT_DEBUG
3103 u32 diag1val = 0;
3104 #endif
3106 /* Clear any existing interrupts */
3107 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3109 /* Use "Diagnostic reset" method! (only thing available!) */
3110 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3112 #ifdef MPT_DEBUG
3113 if (ioc->alt_ioc)
3114 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3115 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3116 ioc->name, diag0val, diag1val));
3117 #endif
3119 /* Do the reset if we are told to ignore the reset history
3120 * or if the reset history is 0
3122 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3123 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3124 /* Write magic sequence to WriteSequence register
3125 * Loop until in diagnostic mode
3127 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3128 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3129 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3130 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3131 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3132 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3134 /* wait 100 msec */
3135 if (sleepFlag == CAN_SLEEP) {
3136 set_current_state(TASK_INTERRUPTIBLE);
3137 schedule_timeout(100 * HZ / 1000);
3138 } else {
3139 mdelay (100);
3142 count++;
3143 if (count > 20) {
3144 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3145 ioc->name, diag0val);
3146 return -2;
3150 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3152 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3153 ioc->name, diag0val));
3156 #ifdef MPT_DEBUG
3157 if (ioc->alt_ioc)
3158 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3159 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3160 ioc->name, diag0val, diag1val));
3161 #endif
3163 * Disable the ARM (Bug fix)
3166 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3167 mdelay (1);
3170 * Now hit the reset bit in the Diagnostic register
3171 * (THE BIG HAMMER!) (Clears DRWE bit).
3173 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3174 hard_reset_done = 1;
3175 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3176 ioc->name));
3179 * Call each currently registered protocol IOC reset handler
3180 * with pre-reset indication.
3181 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3182 * MptResetHandlers[] registered yet.
3185 int ii;
3186 int r = 0;
3188 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3189 if (MptResetHandlers[ii]) {
3190 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3191 ioc->name, ii));
3192 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
3193 if (ioc->alt_ioc) {
3194 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3195 ioc->name, ioc->alt_ioc->name, ii));
3196 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
3200 /* FIXME? Examine results here? */
3203 if (ioc->cached_fw) {
3204 /* If the DownloadBoot operation fails, the
3205 * IOC will be left unusable. This is a fatal error
3206 * case. _diag_reset will return < 0
3208 for (count = 0; count < 30; count ++) {
3209 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3210 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3211 break;
3214 /* wait 1 sec */
3215 if (sleepFlag == CAN_SLEEP) {
3216 set_current_state(TASK_INTERRUPTIBLE);
3217 schedule_timeout(1000 * HZ / 1000);
3218 } else {
3219 mdelay (1000);
3222 if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) {
3223 printk(KERN_WARNING MYNAM
3224 ": firmware downloadboot failure (%d)!\n", count);
3227 } else {
3228 /* Wait for FW to reload and for board
3229 * to go to the READY state.
3230 * Maximum wait is 60 seconds.
3231 * If fail, no error will check again
3232 * with calling program.
3234 for (count = 0; count < 60; count ++) {
3235 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3236 doorbell &= MPI_IOC_STATE_MASK;
3238 if (doorbell == MPI_IOC_STATE_READY) {
3239 break;
3242 /* wait 1 sec */
3243 if (sleepFlag == CAN_SLEEP) {
3244 set_current_state(TASK_INTERRUPTIBLE);
3245 schedule_timeout(1000 * HZ / 1000);
3246 } else {
3247 mdelay (1000);
3253 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3254 #ifdef MPT_DEBUG
3255 if (ioc->alt_ioc)
3256 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3257 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3258 ioc->name, diag0val, diag1val));
3259 #endif
3261 /* Clear RESET_HISTORY bit! Place board in the
3262 * diagnostic mode to update the diag register.
3264 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3265 count = 0;
3266 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3267 /* Write magic sequence to WriteSequence register
3268 * Loop until in diagnostic mode
3270 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3271 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3272 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3273 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3274 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3275 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3277 /* wait 100 msec */
3278 if (sleepFlag == CAN_SLEEP) {
3279 set_current_state(TASK_INTERRUPTIBLE);
3280 schedule_timeout(100 * HZ / 1000);
3281 } else {
3282 mdelay (100);
3285 count++;
3286 if (count > 20) {
3287 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3288 ioc->name, diag0val);
3289 break;
3291 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3293 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3294 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3295 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3296 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3297 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3298 ioc->name);
3301 /* Disable Diagnostic Mode
3303 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3305 /* Check FW reload status flags.
3307 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3308 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3309 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3310 ioc->name, diag0val);
3311 return -3;
3314 #ifdef MPT_DEBUG
3315 if (ioc->alt_ioc)
3316 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3317 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3318 ioc->name, diag0val, diag1val));
3319 #endif
3322 * Reset flag that says we've enabled event notification
3324 ioc->facts.EventState = 0;
3326 if (ioc->alt_ioc)
3327 ioc->alt_ioc->facts.EventState = 0;
3329 return hard_reset_done;
3332 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3334 * SendIocReset - Send IOCReset request to MPT adapter.
3335 * @ioc: Pointer to MPT_ADAPTER structure
3336 * @reset_type: reset type, expected values are
3337 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3339 * Send IOCReset request to the MPT adapter.
3341 * Returns 0 for success, non-zero for failure.
3343 static int
3344 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3346 int r;
3347 u32 state;
3348 int cntdn, count;
3350 drsprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
3351 ioc->name, reset_type));
3352 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3353 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3354 return r;
3356 /* FW ACK'd request, wait for READY state
3358 count = 0;
3359 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3361 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3362 cntdn--;
3363 count++;
3364 if (!cntdn) {
3365 if (sleepFlag != CAN_SLEEP)
3366 count *= 10;
3368 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3369 ioc->name, (int)((count+5)/HZ));
3370 return -ETIME;
3373 if (sleepFlag == CAN_SLEEP) {
3374 set_current_state(TASK_INTERRUPTIBLE);
3375 schedule_timeout(1 * HZ / 1000);
3376 } else {
3377 mdelay (1); /* 1 msec delay */
3381 /* TODO!
3382 * Cleanup all event stuff for this IOC; re-issue EventNotification
3383 * request if needed.
3385 if (ioc->facts.Function)
3386 ioc->facts.EventState = 0;
3388 return 0;
3391 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3393 * initChainBuffers - Allocate memory for and initialize
3394 * chain buffers, chain buffer control arrays and spinlock.
3395 * @hd: Pointer to MPT_SCSI_HOST structure
3396 * @init: If set, initialize the spin lock.
3398 static int
3399 initChainBuffers(MPT_ADAPTER *ioc)
3401 u8 *mem;
3402 int sz, ii, num_chain;
3403 int scale, num_sge, numSGE;
3405 /* ReqToChain size must equal the req_depth
3406 * index = req_idx
3408 if (ioc->ReqToChain == NULL) {
3409 sz = ioc->req_depth * sizeof(int);
3410 mem = kmalloc(sz, GFP_ATOMIC);
3411 if (mem == NULL)
3412 return -1;
3414 ioc->ReqToChain = (int *) mem;
3415 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3416 ioc->name, mem, sz));
3417 mem = kmalloc(sz, GFP_ATOMIC);
3418 if (mem == NULL)
3419 return -1;
3421 ioc->RequestNB = (int *) mem;
3422 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3423 ioc->name, mem, sz));
3425 for (ii = 0; ii < ioc->req_depth; ii++) {
3426 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3429 /* ChainToChain size must equal the total number
3430 * of chain buffers to be allocated.
3431 * index = chain_idx
3433 * Calculate the number of chain buffers needed(plus 1) per I/O
3434 * then multiply the the maximum number of simultaneous cmds
3436 * num_sge = num sge in request frame + last chain buffer
3437 * scale = num sge per chain buffer if no chain element
3439 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3440 if (sizeof(dma_addr_t) == sizeof(u64))
3441 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3442 else
3443 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3445 if (sizeof(dma_addr_t) == sizeof(u64)) {
3446 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3447 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3448 } else {
3449 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3450 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3452 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3453 ioc->name, num_sge, numSGE));
3455 if ( numSGE > MPT_SCSI_SG_DEPTH )
3456 numSGE = MPT_SCSI_SG_DEPTH;
3458 num_chain = 1;
3459 while (numSGE - num_sge > 0) {
3460 num_chain++;
3461 num_sge += (scale - 1);
3463 num_chain++;
3465 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3466 ioc->name, numSGE, num_sge, num_chain));
3468 if ((int) ioc->chip_type > (int) FC929)
3469 num_chain *= MPT_SCSI_CAN_QUEUE;
3470 else
3471 num_chain *= MPT_FC_CAN_QUEUE;
3473 ioc->num_chain = num_chain;
3475 sz = num_chain * sizeof(int);
3476 if (ioc->ChainToChain == NULL) {
3477 mem = kmalloc(sz, GFP_ATOMIC);
3478 if (mem == NULL)
3479 return -1;
3481 ioc->ChainToChain = (int *) mem;
3482 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3483 ioc->name, mem, sz));
3484 } else {
3485 mem = (u8 *) ioc->ChainToChain;
3487 memset(mem, 0xFF, sz);
3488 return num_chain;
3491 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3493 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3494 * @ioc: Pointer to MPT_ADAPTER structure
3496 * This routine allocates memory for the MPT reply and request frame
3497 * pools (if necessary), and primes the IOC reply FIFO with
3498 * reply frames.
3500 * Returns 0 for success, non-zero for failure.
3502 static int
3503 PrimeIocFifos(MPT_ADAPTER *ioc)
3505 MPT_FRAME_HDR *mf;
3506 unsigned long flags;
3507 dma_addr_t alloc_dma;
3508 u8 *mem;
3509 int i, reply_sz, sz, total_size, num_chain;
3511 /* Prime reply FIFO... */
3513 if (ioc->reply_frames == NULL) {
3514 if ( (num_chain = initChainBuffers(ioc)) < 0)
3515 return -1;
3517 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3518 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3519 ioc->name, ioc->reply_sz, ioc->reply_depth));
3520 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3521 ioc->name, reply_sz, reply_sz));
3523 sz = (ioc->req_sz * ioc->req_depth);
3524 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3525 ioc->name, ioc->req_sz, ioc->req_depth));
3526 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3527 ioc->name, sz, sz));
3528 total_size += sz;
3530 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3531 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3532 ioc->name, ioc->req_sz, num_chain));
3533 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3534 ioc->name, sz, sz, num_chain));
3536 total_size += sz;
3537 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3538 if (mem == NULL) {
3539 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3540 ioc->name);
3541 goto out_fail;
3544 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3545 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3547 memset(mem, 0, total_size);
3548 ioc->alloc_total += total_size;
3549 ioc->alloc = mem;
3550 ioc->alloc_dma = alloc_dma;
3551 ioc->alloc_sz = total_size;
3552 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3553 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3555 alloc_dma += reply_sz;
3556 mem += reply_sz;
3558 /* Request FIFO - WE manage this! */
3560 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3561 ioc->req_frames_dma = alloc_dma;
3563 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffers @ %p[%p]\n",
3564 ioc->name, mem, (void *)(ulong)alloc_dma));
3566 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3568 #if defined(CONFIG_MTRR) && 0
3570 * Enable Write Combining MTRR for IOC's memory region.
3571 * (at least as much as we can; "size and base must be
3572 * multiples of 4 kiB"
3574 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3576 MTRR_TYPE_WRCOMB, 1);
3577 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3578 ioc->name, ioc->req_frames_dma, sz));
3579 #endif
3581 for (i = 0; i < ioc->req_depth; i++) {
3582 alloc_dma += ioc->req_sz;
3583 mem += ioc->req_sz;
3586 ioc->ChainBuffer = mem;
3587 ioc->ChainBufferDMA = alloc_dma;
3589 dinitprintk((KERN_INFO MYNAM " :%s.ChainBuffers @ %p(%p)\n",
3590 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3592 /* Initialize the free chain Q.
3595 Q_INIT(&ioc->FreeChainQ, MPT_FRAME_HDR);
3597 /* Post the chain buffers to the FreeChainQ.
3599 mem = (u8 *)ioc->ChainBuffer;
3600 for (i=0; i < num_chain; i++) {
3601 mf = (MPT_FRAME_HDR *) mem;
3602 Q_ADD_TAIL(&ioc->FreeChainQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
3603 mem += ioc->req_sz;
3606 /* Initialize Request frames linked list
3608 alloc_dma = ioc->req_frames_dma;
3609 mem = (u8 *) ioc->req_frames;
3611 spin_lock_irqsave(&ioc->FreeQlock, flags);
3612 Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
3613 for (i = 0; i < ioc->req_depth; i++) {
3614 mf = (MPT_FRAME_HDR *) mem;
3616 /* Queue REQUESTs *internally*! */
3617 Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
3618 mem += ioc->req_sz;
3620 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3622 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3623 ioc->sense_buf_pool =
3624 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3625 if (ioc->sense_buf_pool == NULL) {
3626 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3627 ioc->name);
3628 goto out_fail;
3631 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3632 ioc->alloc_total += sz;
3633 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3634 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3638 /* Post Reply frames to FIFO
3640 alloc_dma = ioc->alloc_dma;
3641 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3642 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3644 for (i = 0; i < ioc->reply_depth; i++) {
3645 /* Write each address to the IOC! */
3646 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3647 alloc_dma += ioc->reply_sz;
3650 return 0;
3652 out_fail:
3653 if (ioc->alloc != NULL) {
3654 sz = ioc->alloc_sz;
3655 pci_free_consistent(ioc->pcidev,
3657 ioc->alloc, ioc->alloc_dma);
3658 ioc->reply_frames = NULL;
3659 ioc->req_frames = NULL;
3660 ioc->alloc_total -= sz;
3662 if (ioc->sense_buf_pool != NULL) {
3663 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3664 pci_free_consistent(ioc->pcidev,
3666 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3667 ioc->sense_buf_pool = NULL;
3669 return -1;
3672 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3674 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3675 * from IOC via doorbell handshake method.
3676 * @ioc: Pointer to MPT_ADAPTER structure
3677 * @reqBytes: Size of the request in bytes
3678 * @req: Pointer to MPT request frame
3679 * @replyBytes: Expected size of the reply in bytes
3680 * @u16reply: Pointer to area where reply should be written
3681 * @maxwait: Max wait time for a reply (in seconds)
3682 * @sleepFlag: Specifies whether the process can sleep
3684 * NOTES: It is the callers responsibility to byte-swap fields in the
3685 * request which are greater than 1 byte in size. It is also the
3686 * callers responsibility to byte-swap response fields which are
3687 * greater than 1 byte in size.
3689 * Returns 0 for success, non-zero for failure.
3692 mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
3693 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
3695 MPIDefaultReply_t *mptReply;
3696 int failcnt = 0;
3697 int t;
3700 * Get ready to cache a handshake reply
3702 ioc->hs_reply_idx = 0;
3703 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3704 mptReply->MsgLength = 0;
3707 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3708 * then tell IOC that we want to handshake a request of N words.
3709 * (WRITE u32val to Doorbell reg).
3711 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3712 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3713 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3714 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3717 * Wait for IOC's doorbell handshake int
3719 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3720 failcnt++;
3722 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3723 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3725 /* Read doorbell and check for active bit */
3726 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3727 return -1;
3730 * Clear doorbell int (WRITE 0 to IntStatus reg),
3731 * then wait for IOC to ACKnowledge that it's ready for
3732 * our handshake request.
3734 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3735 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3736 failcnt++;
3738 if (!failcnt) {
3739 int ii;
3740 u8 *req_as_bytes = (u8 *) req;
3743 * Stuff request words via doorbell handshake,
3744 * with ACK from IOC for each.
3746 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3747 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3748 (req_as_bytes[(ii*4) + 1] << 8) |
3749 (req_as_bytes[(ii*4) + 2] << 16) |
3750 (req_as_bytes[(ii*4) + 3] << 24));
3752 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3753 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3754 failcnt++;
3757 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3758 DBG_DUMP_REQUEST_FRAME_HDR(req)
3760 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3761 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3764 * Wait for completion of doorbell handshake reply from the IOC
3766 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3767 failcnt++;
3769 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3770 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3773 * Copy out the cached reply...
3775 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3776 u16reply[ii] = ioc->hs_reply[ii];
3777 } else {
3778 return -99;
3781 return -failcnt;
3784 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3786 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3787 * in it's IntStatus register.
3788 * @ioc: Pointer to MPT_ADAPTER structure
3789 * @howlong: How long to wait (in seconds)
3790 * @sleepFlag: Specifies whether the process can sleep
3792 * This routine waits (up to ~2 seconds max) for IOC doorbell
3793 * handshake ACKnowledge.
3795 * Returns a negative value on failure, else wait loop count.
3797 static int
3798 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3800 int cntdn;
3801 int count = 0;
3802 u32 intstat=0;
3804 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
3806 if (sleepFlag == CAN_SLEEP) {
3807 while (--cntdn) {
3808 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3809 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3810 break;
3811 set_current_state(TASK_INTERRUPTIBLE);
3812 schedule_timeout(1 * HZ / 1000);
3813 count++;
3815 } else {
3816 while (--cntdn) {
3817 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3818 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3819 break;
3820 mdelay (1);
3821 count++;
3825 if (cntdn) {
3826 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3827 ioc->name, count));
3828 return count;
3831 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3832 ioc->name, count, intstat);
3833 return -1;
3836 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3838 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3839 * in it's IntStatus register.
3840 * @ioc: Pointer to MPT_ADAPTER structure
3841 * @howlong: How long to wait (in seconds)
3842 * @sleepFlag: Specifies whether the process can sleep
3844 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3846 * Returns a negative value on failure, else wait loop count.
3848 static int
3849 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3851 int cntdn;
3852 int count = 0;
3853 u32 intstat=0;
3855 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
3856 if (sleepFlag == CAN_SLEEP) {
3857 while (--cntdn) {
3858 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3859 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3860 break;
3861 set_current_state(TASK_INTERRUPTIBLE);
3862 schedule_timeout(1 * HZ / 1000);
3863 count++;
3865 } else {
3866 while (--cntdn) {
3867 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3868 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3869 break;
3870 mdelay(1);
3871 count++;
3875 if (cntdn) {
3876 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
3877 ioc->name, count, howlong));
3878 return count;
3881 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
3882 ioc->name, count, intstat);
3883 return -1;
3886 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3888 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
3889 * @ioc: Pointer to MPT_ADAPTER structure
3890 * @howlong: How long to wait (in seconds)
3891 * @sleepFlag: Specifies whether the process can sleep
3893 * This routine polls the IOC for a handshake reply, 16 bits at a time.
3894 * Reply is cached to IOC private area large enough to hold a maximum
3895 * of 128 bytes of reply data.
3897 * Returns a negative value on failure, else size of reply in WORDS.
3899 static int
3900 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3902 int u16cnt = 0;
3903 int failcnt = 0;
3904 int t;
3905 u16 *hs_reply = ioc->hs_reply;
3906 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3907 u16 hword;
3909 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
3912 * Get first two u16's so we can look at IOC's intended reply MsgLength
3914 u16cnt=0;
3915 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
3916 failcnt++;
3917 } else {
3918 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
3919 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3920 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3921 failcnt++;
3922 else {
3923 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
3924 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3928 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
3929 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
3930 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3933 * If no error (and IOC said MsgLength is > 0), piece together
3934 * reply 16 bits at a time.
3936 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
3937 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3938 failcnt++;
3939 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
3940 /* don't overflow our IOC hs_reply[] buffer! */
3941 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
3942 hs_reply[u16cnt] = hword;
3943 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3946 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3947 failcnt++;
3948 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3950 if (failcnt) {
3951 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
3952 ioc->name);
3953 return -failcnt;
3955 #if 0
3956 else if (u16cnt != (2 * mptReply->MsgLength)) {
3957 return -101;
3959 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
3960 return -102;
3962 #endif
3964 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
3965 DBG_DUMP_REPLY_FRAME(mptReply)
3967 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
3968 ioc->name, t, u16cnt/2));
3969 return u16cnt/2;
3972 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3974 * GetLanConfigPages - Fetch LANConfig pages.
3975 * @ioc: Pointer to MPT_ADAPTER structure
3977 * Return: 0 for success
3978 * -ENOMEM if no memory available
3979 * -EPERM if not allowed due to ISR context
3980 * -EAGAIN if no msg frames currently available
3981 * -EFAULT for non-successful reply or no reply (timeout)
3983 static int
3984 GetLanConfigPages(MPT_ADAPTER *ioc)
3986 ConfigPageHeader_t hdr;
3987 CONFIGPARMS cfg;
3988 LANPage0_t *ppage0_alloc;
3989 dma_addr_t page0_dma;
3990 LANPage1_t *ppage1_alloc;
3991 dma_addr_t page1_dma;
3992 int rc = 0;
3993 int data_sz;
3994 int copy_sz;
3996 /* Get LAN Page 0 header */
3997 hdr.PageVersion = 0;
3998 hdr.PageLength = 0;
3999 hdr.PageNumber = 0;
4000 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4001 cfg.hdr = &hdr;
4002 cfg.physAddr = -1;
4003 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4004 cfg.dir = 0;
4005 cfg.pageAddr = 0;
4006 cfg.timeout = 0;
4008 if ((rc = mpt_config(ioc, &cfg)) != 0)
4009 return rc;
4011 if (hdr.PageLength > 0) {
4012 data_sz = hdr.PageLength * 4;
4013 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4014 rc = -ENOMEM;
4015 if (ppage0_alloc) {
4016 memset((u8 *)ppage0_alloc, 0, data_sz);
4017 cfg.physAddr = page0_dma;
4018 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4020 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4021 /* save the data */
4022 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4023 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4027 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4029 /* FIXME!
4030 * Normalize endianness of structure data,
4031 * by byte-swapping all > 1 byte fields!
4036 if (rc)
4037 return rc;
4040 /* Get LAN Page 1 header */
4041 hdr.PageVersion = 0;
4042 hdr.PageLength = 0;
4043 hdr.PageNumber = 1;
4044 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4045 cfg.hdr = &hdr;
4046 cfg.physAddr = -1;
4047 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4048 cfg.dir = 0;
4049 cfg.pageAddr = 0;
4051 if ((rc = mpt_config(ioc, &cfg)) != 0)
4052 return rc;
4054 if (hdr.PageLength == 0)
4055 return 0;
4057 data_sz = hdr.PageLength * 4;
4058 rc = -ENOMEM;
4059 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4060 if (ppage1_alloc) {
4061 memset((u8 *)ppage1_alloc, 0, data_sz);
4062 cfg.physAddr = page1_dma;
4063 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4065 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4066 /* save the data */
4067 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4068 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4071 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4073 /* FIXME!
4074 * Normalize endianness of structure data,
4075 * by byte-swapping all > 1 byte fields!
4080 return rc;
4083 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4085 * GetFcPortPage0 - Fetch FCPort config Page0.
4086 * @ioc: Pointer to MPT_ADAPTER structure
4087 * @portnum: IOC Port number
4089 * Return: 0 for success
4090 * -ENOMEM if no memory available
4091 * -EPERM if not allowed due to ISR context
4092 * -EAGAIN if no msg frames currently available
4093 * -EFAULT for non-successful reply or no reply (timeout)
4095 static int
4096 GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
4098 ConfigPageHeader_t hdr;
4099 CONFIGPARMS cfg;
4100 FCPortPage0_t *ppage0_alloc;
4101 FCPortPage0_t *pp0dest;
4102 dma_addr_t page0_dma;
4103 int data_sz;
4104 int copy_sz;
4105 int rc;
4107 /* Get FCPort Page 0 header */
4108 hdr.PageVersion = 0;
4109 hdr.PageLength = 0;
4110 hdr.PageNumber = 0;
4111 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
4112 cfg.hdr = &hdr;
4113 cfg.physAddr = -1;
4114 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4115 cfg.dir = 0;
4116 cfg.pageAddr = portnum;
4117 cfg.timeout = 0;
4119 if ((rc = mpt_config(ioc, &cfg)) != 0)
4120 return rc;
4122 if (hdr.PageLength == 0)
4123 return 0;
4125 data_sz = hdr.PageLength * 4;
4126 rc = -ENOMEM;
4127 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4128 if (ppage0_alloc) {
4129 memset((u8 *)ppage0_alloc, 0, data_sz);
4130 cfg.physAddr = page0_dma;
4131 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4133 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4134 /* save the data */
4135 pp0dest = &ioc->fc_port_page0[portnum];
4136 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
4137 memcpy(pp0dest, ppage0_alloc, copy_sz);
4140 * Normalize endianness of structure data,
4141 * by byte-swapping all > 1 byte fields!
4143 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
4144 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
4145 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
4146 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
4147 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
4148 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
4149 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
4150 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
4151 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
4152 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
4153 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
4154 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
4155 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
4156 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
4157 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
4158 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
4162 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4165 return rc;
4168 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4170 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4171 * @ioc: Pointer to MPT_ADAPTER structure
4173 * Returns: 0 for success
4174 * -ENOMEM if no memory available
4175 * -EPERM if not allowed due to ISR context
4176 * -EAGAIN if no msg frames currently available
4177 * -EFAULT for non-successful reply or no reply (timeout)
4179 static int
4180 GetIoUnitPage2(MPT_ADAPTER *ioc)
4182 ConfigPageHeader_t hdr;
4183 CONFIGPARMS cfg;
4184 IOUnitPage2_t *ppage_alloc;
4185 dma_addr_t page_dma;
4186 int data_sz;
4187 int rc;
4189 /* Get the page header */
4190 hdr.PageVersion = 0;
4191 hdr.PageLength = 0;
4192 hdr.PageNumber = 2;
4193 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4194 cfg.hdr = &hdr;
4195 cfg.physAddr = -1;
4196 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4197 cfg.dir = 0;
4198 cfg.pageAddr = 0;
4199 cfg.timeout = 0;
4201 if ((rc = mpt_config(ioc, &cfg)) != 0)
4202 return rc;
4204 if (hdr.PageLength == 0)
4205 return 0;
4207 /* Read the config page */
4208 data_sz = hdr.PageLength * 4;
4209 rc = -ENOMEM;
4210 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4211 if (ppage_alloc) {
4212 memset((u8 *)ppage_alloc, 0, data_sz);
4213 cfg.physAddr = page_dma;
4214 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4216 /* If Good, save data */
4217 if ((rc = mpt_config(ioc, &cfg)) == 0)
4218 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4220 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4223 return rc;
4226 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4227 /* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4228 * @ioc: Pointer to a Adapter Strucutre
4229 * @portnum: IOC port number
4231 * Return: -EFAULT if read of config page header fails
4232 * or if no nvram
4233 * If read of SCSI Port Page 0 fails,
4234 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4235 * Adapter settings: async, narrow
4236 * Return 1
4237 * If read of SCSI Port Page 2 fails,
4238 * Adapter settings valid
4239 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4240 * Return 1
4241 * Else
4242 * Both valid
4243 * Return 0
4244 * CHECK - what type of locking mechanisms should be used????
4246 static int
4247 mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4249 u8 *pbuf;
4250 dma_addr_t buf_dma;
4251 CONFIGPARMS cfg;
4252 ConfigPageHeader_t header;
4253 int ii;
4254 int data, rc = 0;
4256 /* Allocate memory
4258 if (!ioc->spi_data.nvram) {
4259 int sz;
4260 u8 *mem;
4261 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4262 mem = kmalloc(sz, GFP_ATOMIC);
4263 if (mem == NULL)
4264 return -EFAULT;
4266 ioc->spi_data.nvram = (int *) mem;
4268 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4269 ioc->name, ioc->spi_data.nvram, sz));
4272 /* Invalidate NVRAM information
4274 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4275 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4278 /* Read SPP0 header, allocate memory, then read page.
4280 header.PageVersion = 0;
4281 header.PageLength = 0;
4282 header.PageNumber = 0;
4283 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4284 cfg.hdr = &header;
4285 cfg.physAddr = -1;
4286 cfg.pageAddr = portnum;
4287 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4288 cfg.dir = 0;
4289 cfg.timeout = 0; /* use default */
4290 if (mpt_config(ioc, &cfg) != 0)
4291 return -EFAULT;
4293 if (header.PageLength > 0) {
4294 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4295 if (pbuf) {
4296 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4297 cfg.physAddr = buf_dma;
4298 if (mpt_config(ioc, &cfg) != 0) {
4299 ioc->spi_data.maxBusWidth = MPT_NARROW;
4300 ioc->spi_data.maxSyncOffset = 0;
4301 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4302 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4303 rc = 1;
4304 } else {
4305 /* Save the Port Page 0 data
4307 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4308 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4309 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4311 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4312 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
4313 dinitprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
4314 ioc->name, pPP0->Capabilities));
4316 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4317 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4318 if (data) {
4319 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4320 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4321 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
4322 } else {
4323 ioc->spi_data.maxSyncOffset = 0;
4324 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4327 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4329 /* Update the minSyncFactor based on bus type.
4331 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4332 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4334 if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
4335 ioc->spi_data.minSyncFactor = MPT_ULTRA;
4338 if (pbuf) {
4339 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4344 /* SCSI Port Page 2 - Read the header then the page.
4346 header.PageVersion = 0;
4347 header.PageLength = 0;
4348 header.PageNumber = 2;
4349 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
4350 cfg.hdr = &header;
4351 cfg.physAddr = -1;
4352 cfg.pageAddr = portnum;
4353 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4354 cfg.dir = 0;
4355 if (mpt_config(ioc, &cfg) != 0)
4356 return -EFAULT;
4358 if (header.PageLength > 0) {
4359 /* Allocate memory and read SCSI Port Page 2
4361 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4362 if (pbuf) {
4363 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4364 cfg.physAddr = buf_dma;
4365 if (mpt_config(ioc, &cfg) != 0) {
4366 /* Nvram data is left with INVALID mark
4368 rc = 1;
4369 } else {
4370 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4371 MpiDeviceInfo_t *pdevice = NULL;
4373 /* Save the Port Page 2 data
4374 * (reformat into a 32bit quantity)
4376 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4377 ioc->spi_data.PortFlags = data;
4378 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4379 pdevice = &pPP2->DeviceSettings[ii];
4380 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4381 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4382 ioc->spi_data.nvram[ii] = data;
4386 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4390 /* Update Adapter limits with those from NVRAM
4391 * Comment: Don't need to do this. Target performance
4392 * parameters will never exceed the adapters limits.
4395 return rc;
4398 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4399 /* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4400 * @ioc: Pointer to a Adapter Strucutre
4401 * @portnum: IOC port number
4403 * Return: -EFAULT if read of config page header fails
4404 * or 0 if success.
4406 static int
4407 mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4409 CONFIGPARMS cfg;
4410 ConfigPageHeader_t header;
4412 /* Read the SCSI Device Page 1 header
4414 header.PageVersion = 0;
4415 header.PageLength = 0;
4416 header.PageNumber = 1;
4417 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4418 cfg.hdr = &header;
4419 cfg.physAddr = -1;
4420 cfg.pageAddr = portnum;
4421 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4422 cfg.dir = 0;
4423 cfg.timeout = 0;
4424 if (mpt_config(ioc, &cfg) != 0)
4425 return -EFAULT;
4427 ioc->spi_data.sdp1version = cfg.hdr->PageVersion;
4428 ioc->spi_data.sdp1length = cfg.hdr->PageLength;
4430 header.PageVersion = 0;
4431 header.PageLength = 0;
4432 header.PageNumber = 0;
4433 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4434 if (mpt_config(ioc, &cfg) != 0)
4435 return -EFAULT;
4437 ioc->spi_data.sdp0version = cfg.hdr->PageVersion;
4438 ioc->spi_data.sdp0length = cfg.hdr->PageLength;
4440 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4441 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4443 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4444 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4445 return 0;
4448 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4450 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4451 * @ioc: Pointer to a Adapter Strucutre
4452 * @portnum: IOC port number
4454 * Return:
4455 * 0 on success
4456 * -EFAULT if read of config page header fails or data pointer not NULL
4457 * -ENOMEM if pci_alloc failed
4460 mpt_findImVolumes(MPT_ADAPTER *ioc)
4462 IOCPage2_t *pIoc2;
4463 u8 *mem;
4464 ConfigPageIoc2RaidVol_t *pIocRv;
4465 dma_addr_t ioc2_dma;
4466 CONFIGPARMS cfg;
4467 ConfigPageHeader_t header;
4468 int jj;
4469 int rc = 0;
4470 int iocpage2sz;
4471 u8 nVols, nPhys;
4472 u8 vid, vbus, vioc;
4474 /* Read IOCP2 header then the page.
4476 header.PageVersion = 0;
4477 header.PageLength = 0;
4478 header.PageNumber = 2;
4479 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4480 cfg.hdr = &header;
4481 cfg.physAddr = -1;
4482 cfg.pageAddr = 0;
4483 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4484 cfg.dir = 0;
4485 cfg.timeout = 0;
4486 if (mpt_config(ioc, &cfg) != 0)
4487 return -EFAULT;
4489 if (header.PageLength == 0)
4490 return -EFAULT;
4492 iocpage2sz = header.PageLength * 4;
4493 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4494 if (!pIoc2)
4495 return -ENOMEM;
4497 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4498 cfg.physAddr = ioc2_dma;
4499 if (mpt_config(ioc, &cfg) != 0)
4500 goto done_and_free;
4502 if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) {
4503 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4504 if (mem) {
4505 ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem;
4506 } else {
4507 goto done_and_free;
4510 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4512 /* Identify RAID Volume Id's */
4513 nVols = pIoc2->NumActiveVolumes;
4514 if ( nVols == 0) {
4515 /* No RAID Volume.
4517 goto done_and_free;
4518 } else {
4519 /* At least 1 RAID Volume
4521 pIocRv = pIoc2->RaidVolume;
4522 ioc->spi_data.isRaid = 0;
4523 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4524 vid = pIocRv->VolumeID;
4525 vbus = pIocRv->VolumeBus;
4526 vioc = pIocRv->VolumeIOC;
4528 /* find the match
4530 if (vbus == 0) {
4531 ioc->spi_data.isRaid |= (1 << vid);
4532 } else {
4533 /* Error! Always bus 0
4539 /* Identify Hidden Physical Disk Id's */
4540 nPhys = pIoc2->NumActivePhysDisks;
4541 if (nPhys == 0) {
4542 /* No physical disks.
4544 } else {
4545 mpt_read_ioc_pg_3(ioc);
4548 done_and_free:
4549 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4551 return rc;
4555 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4557 IOCPage3_t *pIoc3;
4558 u8 *mem;
4559 CONFIGPARMS cfg;
4560 ConfigPageHeader_t header;
4561 dma_addr_t ioc3_dma;
4562 int iocpage3sz = 0;
4564 /* Free the old page
4566 if (ioc->spi_data.pIocPg3) {
4567 kfree(ioc->spi_data.pIocPg3);
4568 ioc->spi_data.pIocPg3 = NULL;
4571 /* There is at least one physical disk.
4572 * Read and save IOC Page 3
4574 header.PageVersion = 0;
4575 header.PageLength = 0;
4576 header.PageNumber = 3;
4577 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4578 cfg.hdr = &header;
4579 cfg.physAddr = -1;
4580 cfg.pageAddr = 0;
4581 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4582 cfg.dir = 0;
4583 cfg.timeout = 0;
4584 if (mpt_config(ioc, &cfg) != 0)
4585 return 0;
4587 if (header.PageLength == 0)
4588 return 0;
4590 /* Read Header good, alloc memory
4592 iocpage3sz = header.PageLength * 4;
4593 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4594 if (!pIoc3)
4595 return 0;
4597 /* Read the Page and save the data
4598 * into malloc'd memory.
4600 cfg.physAddr = ioc3_dma;
4601 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4602 if (mpt_config(ioc, &cfg) == 0) {
4603 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4604 if (mem) {
4605 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
4606 ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
4610 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4612 return 0;
4615 static void
4616 mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4618 IOCPage4_t *pIoc4;
4619 CONFIGPARMS cfg;
4620 ConfigPageHeader_t header;
4621 dma_addr_t ioc4_dma;
4622 int iocpage4sz;
4624 /* Read and save IOC Page 4
4626 header.PageVersion = 0;
4627 header.PageLength = 0;
4628 header.PageNumber = 4;
4629 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4630 cfg.hdr = &header;
4631 cfg.physAddr = -1;
4632 cfg.pageAddr = 0;
4633 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4634 cfg.dir = 0;
4635 cfg.timeout = 0;
4636 if (mpt_config(ioc, &cfg) != 0)
4637 return;
4639 if (header.PageLength == 0)
4640 return;
4642 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4643 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4644 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4645 if (!pIoc4)
4646 return;
4647 } else {
4648 ioc4_dma = ioc->spi_data.IocPg4_dma;
4649 iocpage4sz = ioc->spi_data.IocPg4Sz;
4652 /* Read the Page into dma memory.
4654 cfg.physAddr = ioc4_dma;
4655 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4656 if (mpt_config(ioc, &cfg) == 0) {
4657 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4658 ioc->spi_data.IocPg4_dma = ioc4_dma;
4659 ioc->spi_data.IocPg4Sz = iocpage4sz;
4660 } else {
4661 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4662 ioc->spi_data.pIocPg4 = NULL;
4666 static void
4667 mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4669 IOCPage1_t *pIoc1;
4670 CONFIGPARMS cfg;
4671 ConfigPageHeader_t header;
4672 dma_addr_t ioc1_dma;
4673 int iocpage1sz = 0;
4674 u32 tmp;
4676 /* Check the Coalescing Timeout in IOC Page 1
4678 header.PageVersion = 0;
4679 header.PageLength = 0;
4680 header.PageNumber = 1;
4681 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
4682 cfg.hdr = &header;
4683 cfg.physAddr = -1;
4684 cfg.pageAddr = 0;
4685 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4686 cfg.dir = 0;
4687 cfg.timeout = 0;
4688 if (mpt_config(ioc, &cfg) != 0)
4689 return;
4691 if (header.PageLength == 0)
4692 return;
4694 /* Read Header good, alloc memory
4696 iocpage1sz = header.PageLength * 4;
4697 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4698 if (!pIoc1)
4699 return;
4701 /* Read the Page and check coalescing timeout
4703 cfg.physAddr = ioc1_dma;
4704 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4705 if (mpt_config(ioc, &cfg) == 0) {
4707 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4708 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4709 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4711 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4712 ioc->name, tmp));
4714 if (tmp > MPT_COALESCING_TIMEOUT) {
4715 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4717 /* Write NVRAM and current
4719 cfg.dir = 1;
4720 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4721 if (mpt_config(ioc, &cfg) == 0) {
4722 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
4723 ioc->name, MPT_COALESCING_TIMEOUT));
4725 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
4726 if (mpt_config(ioc, &cfg) == 0) {
4727 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
4728 ioc->name, MPT_COALESCING_TIMEOUT));
4729 } else {
4730 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
4731 ioc->name));
4734 } else {
4735 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4736 ioc->name));
4740 } else {
4741 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4745 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
4747 return;
4750 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4752 * SendEventNotification - Send EventNotification (on or off) request
4753 * to MPT adapter.
4754 * @ioc: Pointer to MPT_ADAPTER structure
4755 * @EvSwitch: Event switch flags
4757 static int
4758 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
4760 EventNotification_t *evnp;
4762 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
4763 if (evnp == NULL) {
4764 dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
4765 ioc->name));
4766 return 0;
4768 memset(evnp, 0, sizeof(*evnp));
4770 dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch));
4772 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
4773 evnp->ChainOffset = 0;
4774 evnp->MsgFlags = 0;
4775 evnp->Switch = EvSwitch;
4777 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
4779 return 0;
4782 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4784 * SendEventAck - Send EventAck request to MPT adapter.
4785 * @ioc: Pointer to MPT_ADAPTER structure
4786 * @evnp: Pointer to original EventNotification request
4788 static int
4789 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
4791 EventAck_t *pAck;
4793 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4794 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n",
4795 ioc->name);
4796 return -1;
4798 memset(pAck, 0, sizeof(*pAck));
4800 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
4802 pAck->Function = MPI_FUNCTION_EVENT_ACK;
4803 pAck->ChainOffset = 0;
4804 pAck->MsgFlags = 0;
4805 pAck->Event = evnp->Event;
4806 pAck->EventContext = evnp->EventContext;
4808 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
4810 return 0;
4813 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4815 * mpt_config - Generic function to issue config message
4816 * @ioc - Pointer to an adapter structure
4817 * @cfg - Pointer to a configuration structure. Struct contains
4818 * action, page address, direction, physical address
4819 * and pointer to a configuration page header
4820 * Page header is updated.
4822 * Returns 0 for success
4823 * -EPERM if not allowed due to ISR context
4824 * -EAGAIN if no msg frames currently available
4825 * -EFAULT for non-successful reply or no reply (timeout)
4828 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
4830 Config_t *pReq;
4831 MPT_FRAME_HDR *mf;
4832 unsigned long flags;
4833 int ii, rc;
4834 u32 flagsLength;
4835 int in_isr;
4837 /* (Bugzilla:fibrebugs, #513)
4838 * Bug fix (part 1)! 20010905 -sralston
4839 * Prevent calling wait_event() (below), if caller happens
4840 * to be in ISR context, because that is fatal!
4842 in_isr = in_interrupt();
4843 if (in_isr) {
4844 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
4845 ioc->name));
4846 return -EPERM;
4849 /* Get and Populate a free Frame
4851 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4852 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
4853 ioc->name));
4854 return -EAGAIN;
4856 pReq = (Config_t *)mf;
4857 pReq->Action = pCfg->action;
4858 pReq->Reserved = 0;
4859 pReq->ChainOffset = 0;
4860 pReq->Function = MPI_FUNCTION_CONFIG;
4861 pReq->ExtPageLength = 0;
4862 pReq->ExtPageType = 0;
4863 pReq->MsgFlags = 0;
4864 for (ii=0; ii < 8; ii++)
4865 pReq->Reserved2[ii] = 0;
4867 pReq->Header.PageVersion = pCfg->hdr->PageVersion;
4868 pReq->Header.PageLength = pCfg->hdr->PageLength;
4869 pReq->Header.PageNumber = pCfg->hdr->PageNumber;
4870 pReq->Header.PageType = (pCfg->hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
4871 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
4873 /* Add a SGE to the config request.
4875 if (pCfg->dir)
4876 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
4877 else
4878 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
4880 flagsLength |= pCfg->hdr->PageLength * 4;
4882 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
4884 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
4885 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
4887 /* Append pCfg pointer to end of mf
4889 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
4891 /* Initalize the timer
4893 init_timer(&pCfg->timer);
4894 pCfg->timer.data = (unsigned long) ioc;
4895 pCfg->timer.function = mpt_timer_expired;
4896 pCfg->wait_done = 0;
4898 /* Set the timer; ensure 10 second minimum */
4899 if (pCfg->timeout < 10)
4900 pCfg->timer.expires = jiffies + HZ*10;
4901 else
4902 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
4904 /* Add to end of Q, set timer and then issue this command */
4905 spin_lock_irqsave(&ioc->FreeQlock, flags);
4906 Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
4907 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4909 add_timer(&pCfg->timer);
4910 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4911 wait_event(mpt_waitq, pCfg->wait_done);
4913 /* mf has been freed - do not access */
4915 rc = pCfg->status;
4917 return rc;
4920 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4922 * mpt_toolbox - Generic function to issue toolbox message
4923 * @ioc - Pointer to an adapter structure
4924 * @cfg - Pointer to a toolbox structure. Struct contains
4925 * action, page address, direction, physical address
4926 * and pointer to a configuration page header
4927 * Page header is updated.
4929 * Returns 0 for success
4930 * -EPERM if not allowed due to ISR context
4931 * -EAGAIN if no msg frames currently available
4932 * -EFAULT for non-successful reply or no reply (timeout)
4935 mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
4937 ToolboxIstwiReadWriteRequest_t *pReq;
4938 MPT_FRAME_HDR *mf;
4939 struct pci_dev *pdev;
4940 unsigned long flags;
4941 int rc;
4942 u32 flagsLength;
4943 int in_isr;
4945 /* (Bugzilla:fibrebugs, #513)
4946 * Bug fix (part 1)! 20010905 -sralston
4947 * Prevent calling wait_event() (below), if caller happens
4948 * to be in ISR context, because that is fatal!
4950 in_isr = in_interrupt();
4951 if (in_isr) {
4952 dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
4953 ioc->name));
4954 return -EPERM;
4957 /* Get and Populate a free Frame
4959 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4960 dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
4961 ioc->name));
4962 return -EAGAIN;
4964 pReq = (ToolboxIstwiReadWriteRequest_t *)mf;
4965 pReq->Tool = pCfg->action;
4966 pReq->Reserved = 0;
4967 pReq->ChainOffset = 0;
4968 pReq->Function = MPI_FUNCTION_TOOLBOX;
4969 pReq->Reserved1 = 0;
4970 pReq->Reserved2 = 0;
4971 pReq->MsgFlags = 0;
4972 pReq->Flags = pCfg->dir;
4973 pReq->BusNum = 0;
4974 pReq->Reserved3 = 0;
4975 pReq->NumAddressBytes = 0x01;
4976 pReq->Reserved4 = 0;
4977 pReq->DataLength = 0x04;
4978 pdev = (struct pci_dev *) ioc->pcidev;
4979 if (pdev->devfn & 1)
4980 pReq->DeviceAddr = 0xB2;
4981 else
4982 pReq->DeviceAddr = 0xB0;
4983 pReq->Addr1 = 0;
4984 pReq->Addr2 = 0;
4985 pReq->Addr3 = 0;
4986 pReq->Reserved5 = 0;
4988 /* Add a SGE to the config request.
4991 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
4993 mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
4995 dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
4996 ioc->name, pReq->Tool));
4998 /* Append pCfg pointer to end of mf
5000 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5002 /* Initalize the timer
5004 init_timer(&pCfg->timer);
5005 pCfg->timer.data = (unsigned long) ioc;
5006 pCfg->timer.function = mpt_timer_expired;
5007 pCfg->wait_done = 0;
5009 /* Set the timer; ensure 10 second minimum */
5010 if (pCfg->timeout < 10)
5011 pCfg->timer.expires = jiffies + HZ*10;
5012 else
5013 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5015 /* Add to end of Q, set timer and then issue this command */
5016 spin_lock_irqsave(&ioc->FreeQlock, flags);
5017 Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
5018 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5020 add_timer(&pCfg->timer);
5021 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5022 wait_event(mpt_waitq, pCfg->wait_done);
5024 /* mf has been freed - do not access */
5026 rc = pCfg->status;
5028 return rc;
5031 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5033 * mpt_timer_expired - Call back for timer process.
5034 * Used only internal config functionality.
5035 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5037 static void
5038 mpt_timer_expired(unsigned long data)
5040 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5042 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5044 /* Perform a FW reload */
5045 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5046 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5048 /* No more processing.
5049 * Hard reset clean-up will wake up
5050 * process and free all resources.
5052 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5054 return;
5057 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5059 * mpt_ioc_reset - Base cleanup for hard reset
5060 * @ioc: Pointer to the adapter structure
5061 * @reset_phase: Indicates pre- or post-reset functionality
5063 * Remark: Free's resources with internally generated commands.
5065 static int
5066 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5068 CONFIGPARMS *pCfg;
5069 unsigned long flags;
5071 dprintk((KERN_WARNING MYNAM
5072 ": IOC %s_reset routed to MPT base driver!\n",
5073 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5074 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5076 if (reset_phase == MPT_IOC_SETUP_RESET) {
5078 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5079 /* If the internal config Q is not empty -
5080 * delete timer. MF resources will be freed when
5081 * the FIFO's are primed.
5083 spin_lock_irqsave(&ioc->FreeQlock, flags);
5084 if (! Q_IS_EMPTY(&ioc->configQ)){
5085 pCfg = (CONFIGPARMS *)ioc->configQ.head;
5086 do {
5087 del_timer(&pCfg->timer);
5088 pCfg = (CONFIGPARMS *) (pCfg->linkage.forw);
5089 } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
5091 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5093 } else {
5094 CONFIGPARMS *pNext;
5096 /* Search the configQ for internal commands.
5097 * Flush the Q, and wake up all suspended threads.
5099 spin_lock_irqsave(&ioc->FreeQlock, flags);
5100 if (! Q_IS_EMPTY(&ioc->configQ)){
5101 pCfg = (CONFIGPARMS *)ioc->configQ.head;
5102 do {
5103 pNext = (CONFIGPARMS *) pCfg->linkage.forw;
5105 Q_DEL_ITEM(&pCfg->linkage);
5107 pCfg->status = MPT_CONFIG_ERROR;
5108 pCfg->wait_done = 1;
5109 wake_up(&mpt_waitq);
5111 pCfg = pNext;
5112 } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
5114 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5117 return 1; /* currently means nothing really */
5121 #ifdef CONFIG_PROC_FS /* { */
5122 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5124 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5126 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5128 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5130 * Returns 0 for success, non-zero for failure.
5132 static int
5133 procmpt_create(void)
5135 struct proc_dir_entry *ent;
5137 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5138 if (mpt_proc_root_dir == NULL)
5139 return -ENOTDIR;
5141 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5142 if (ent)
5143 ent->read_proc = procmpt_summary_read;
5145 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5146 if (ent)
5147 ent->read_proc = procmpt_version_read;
5149 return 0;
5152 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5154 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5156 * Returns 0 for success, non-zero for failure.
5158 static void
5159 procmpt_destroy(void)
5161 remove_proc_entry("version", mpt_proc_root_dir);
5162 remove_proc_entry("summary", mpt_proc_root_dir);
5163 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5166 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5168 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5169 * or from /proc/mpt/iocN/summary.
5170 * @buf: Pointer to area to write information
5171 * @start: Pointer to start pointer
5172 * @offset: Offset to start writing
5173 * @request:
5174 * @eof: Pointer to EOF integer
5175 * @data: Pointer
5177 * Returns number of characters written to process performing the read.
5179 static int
5180 procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5182 MPT_ADAPTER *ioc;
5183 char *out = buf;
5184 int len;
5186 if (data) {
5187 int more = 0;
5189 ioc = data;
5190 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5192 out += more;
5193 } else {
5194 list_for_each_entry(ioc, &ioc_list, list) {
5195 int more = 0;
5197 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5199 out += more;
5200 if ((out-buf) >= request)
5201 break;
5205 len = out - buf;
5207 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5210 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5212 * procmpt_version_read - Handle read request from /proc/mpt/version.
5213 * @buf: Pointer to area to write information
5214 * @start: Pointer to start pointer
5215 * @offset: Offset to start writing
5216 * @request:
5217 * @eof: Pointer to EOF integer
5218 * @data: Pointer
5220 * Returns number of characters written to process performing the read.
5222 static int
5223 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5225 int ii;
5226 int scsi, lan, ctl, targ, dmp;
5227 char *drvname;
5228 int len;
5230 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5231 len += sprintf(buf+len, " Fusion MPT base driver\n");
5233 scsi = lan = ctl = targ = dmp = 0;
5234 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5235 drvname = NULL;
5236 if (MptCallbacks[ii]) {
5237 switch (MptDriverClass[ii]) {
5238 case MPTSCSIH_DRIVER:
5239 if (!scsi++) drvname = "SCSI host";
5240 break;
5241 case MPTLAN_DRIVER:
5242 if (!lan++) drvname = "LAN";
5243 break;
5244 case MPTSTM_DRIVER:
5245 if (!targ++) drvname = "SCSI target";
5246 break;
5247 case MPTCTL_DRIVER:
5248 if (!ctl++) drvname = "ioctl";
5249 break;
5250 case MPTDMP_DRIVER:
5251 if (!dmp++) drvname = "DMP";
5252 break;
5255 if (drvname)
5256 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5260 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5263 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5265 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5266 * @buf: Pointer to area to write information
5267 * @start: Pointer to start pointer
5268 * @offset: Offset to start writing
5269 * @request:
5270 * @eof: Pointer to EOF integer
5271 * @data: Pointer
5273 * Returns number of characters written to process performing the read.
5275 static int
5276 procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5278 MPT_ADAPTER *ioc = data;
5279 int len;
5280 char expVer[32];
5281 int sz;
5282 int p;
5284 mpt_get_fw_exp_ver(expVer, ioc);
5286 len = sprintf(buf, "%s:", ioc->name);
5287 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5288 len += sprintf(buf+len, " (f/w download boot flag set)");
5289 // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5290 // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5292 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5293 ioc->facts.ProductID,
5294 ioc->prod_name);
5295 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5296 if (ioc->facts.FWImageSize)
5297 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5298 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5299 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5300 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5302 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5303 ioc->facts.CurrentHostMfaHighAddr);
5304 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5305 ioc->facts.CurrentSenseBufferHighAddr);
5307 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5308 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5310 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5311 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5313 * Rounding UP to nearest 4-kB boundary here...
5315 sz = (ioc->req_sz * ioc->req_depth) + 128;
5316 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5317 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5318 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5319 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5320 4*ioc->facts.RequestFrameSize,
5321 ioc->facts.GlobalCredits);
5323 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5324 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5325 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5326 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5327 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5328 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5329 ioc->facts.CurReplyFrameSize,
5330 ioc->facts.ReplyQueueDepth);
5332 len += sprintf(buf+len, " MaxDevices = %d\n",
5333 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5334 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5336 /* per-port info */
5337 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5338 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5339 p+1,
5340 ioc->facts.NumberOfPorts);
5341 if ((int)ioc->chip_type <= (int)FC929) {
5342 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5343 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5344 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5345 a[5], a[4], a[3], a[2], a[1], a[0]);
5347 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5348 ioc->fc_port_page0[p].WWNN.High,
5349 ioc->fc_port_page0[p].WWNN.Low,
5350 ioc->fc_port_page0[p].WWPN.High,
5351 ioc->fc_port_page0[p].WWPN.Low);
5355 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5358 #endif /* CONFIG_PROC_FS } */
5360 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5361 static void
5362 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5364 buf[0] ='\0';
5365 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5366 sprintf(buf, " (Exp %02d%02d)",
5367 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5368 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5370 /* insider hack! */
5371 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5372 strcat(buf, " [MDBG]");
5376 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5378 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5379 * @ioc: Pointer to MPT_ADAPTER structure
5380 * @buffer: Pointer to buffer where IOC summary info should be written
5381 * @size: Pointer to number of bytes we wrote (set by this routine)
5382 * @len: Offset at which to start writing in buffer
5383 * @showlan: Display LAN stuff?
5385 * This routine writes (english readable) ASCII text, which represents
5386 * a summary of IOC information, to a buffer.
5388 void
5389 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5391 char expVer[32];
5392 int y;
5394 mpt_get_fw_exp_ver(expVer, ioc);
5397 * Shorter summary of attached ioc's...
5399 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5400 ioc->name,
5401 ioc->prod_name,
5402 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5403 ioc->facts.FWVersion.Word,
5404 expVer,
5405 ioc->facts.NumberOfPorts,
5406 ioc->req_depth);
5408 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5409 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5410 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5411 a[5], a[4], a[3], a[2], a[1], a[0]);
5414 #ifndef __sparc__
5415 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5416 #else
5417 y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5418 #endif
5420 if (!ioc->active)
5421 y += sprintf(buffer+len+y, " (disabled)");
5423 y += sprintf(buffer+len+y, "\n");
5425 *size = y;
5428 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5430 * Reset Handling
5432 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5434 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5435 * Management call based on input arg values. If TaskMgmt fails,
5436 * return associated SCSI request.
5437 * @ioc: Pointer to MPT_ADAPTER structure
5438 * @sleepFlag: Indicates if sleep or schedule must be called.
5440 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5441 * or a non-interrupt thread. In the former, must not call schedule().
5443 * Remark: A return of -1 is a FATAL error case, as it means a
5444 * FW reload/initialization failed.
5446 * Returns 0 for SUCCESS or -1 if FAILED.
5449 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5451 int rc;
5452 unsigned long flags;
5454 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5455 #ifdef MFCNT
5456 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5457 printk("MF count 0x%x !\n", ioc->mfcnt);
5458 #endif
5460 /* Reset the adapter. Prevent more than 1 call to
5461 * mpt_do_ioc_recovery at any instant in time.
5463 spin_lock_irqsave(&ioc->diagLock, flags);
5464 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5465 spin_unlock_irqrestore(&ioc->diagLock, flags);
5466 return 0;
5467 } else {
5468 ioc->diagPending = 1;
5470 spin_unlock_irqrestore(&ioc->diagLock, flags);
5472 /* FIXME: If do_ioc_recovery fails, repeat....
5475 /* The SCSI driver needs to adjust timeouts on all current
5476 * commands prior to the diagnostic reset being issued.
5477 * Prevents timeouts occuring during a diagnostic reset...very bad.
5478 * For all other protocol drivers, this is a no-op.
5481 int ii;
5482 int r = 0;
5484 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5485 if (MptResetHandlers[ii]) {
5486 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5487 ioc->name, ii));
5488 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
5489 if (ioc->alt_ioc) {
5490 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5491 ioc->name, ioc->alt_ioc->name, ii));
5492 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5498 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5499 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5500 rc, ioc->name);
5502 ioc->reload_fw = 0;
5503 if (ioc->alt_ioc)
5504 ioc->alt_ioc->reload_fw = 0;
5506 spin_lock_irqsave(&ioc->diagLock, flags);
5507 ioc->diagPending = 0;
5508 if (ioc->alt_ioc)
5509 ioc->alt_ioc->diagPending = 0;
5510 spin_unlock_irqrestore(&ioc->diagLock, flags);
5512 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5514 return rc;
5517 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5518 static char *
5519 EventDescriptionStr(u8 event, u32 evData0)
5521 char *ds;
5523 switch(event) {
5524 case MPI_EVENT_NONE:
5525 ds = "None";
5526 break;
5527 case MPI_EVENT_LOG_DATA:
5528 ds = "Log Data";
5529 break;
5530 case MPI_EVENT_STATE_CHANGE:
5531 ds = "State Change";
5532 break;
5533 case MPI_EVENT_UNIT_ATTENTION:
5534 ds = "Unit Attention";
5535 break;
5536 case MPI_EVENT_IOC_BUS_RESET:
5537 ds = "IOC Bus Reset";
5538 break;
5539 case MPI_EVENT_EXT_BUS_RESET:
5540 ds = "External Bus Reset";
5541 break;
5542 case MPI_EVENT_RESCAN:
5543 ds = "Bus Rescan Event";
5544 /* Ok, do we need to do anything here? As far as
5545 I can tell, this is when a new device gets added
5546 to the loop. */
5547 break;
5548 case MPI_EVENT_LINK_STATUS_CHANGE:
5549 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5550 ds = "Link Status(FAILURE) Change";
5551 else
5552 ds = "Link Status(ACTIVE) Change";
5553 break;
5554 case MPI_EVENT_LOOP_STATE_CHANGE:
5555 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5556 ds = "Loop State(LIP) Change";
5557 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5558 ds = "Loop State(LPE) Change"; /* ??? */
5559 else
5560 ds = "Loop State(LPB) Change"; /* ??? */
5561 break;
5562 case MPI_EVENT_LOGOUT:
5563 ds = "Logout";
5564 break;
5565 case MPI_EVENT_EVENT_CHANGE:
5566 if (evData0)
5567 ds = "Events(ON) Change";
5568 else
5569 ds = "Events(OFF) Change";
5570 break;
5571 case MPI_EVENT_INTEGRATED_RAID:
5572 ds = "Integrated Raid";
5573 break;
5575 * MPT base "custom" events may be added here...
5577 default:
5578 ds = "Unknown";
5579 break;
5581 return ds;
5584 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5586 * ProcessEventNotification - Route a received EventNotificationReply to
5587 * all currently regeistered event handlers.
5588 * @ioc: Pointer to MPT_ADAPTER structure
5589 * @pEventReply: Pointer to EventNotification reply frame
5590 * @evHandlers: Pointer to integer, number of event handlers
5592 * Returns sum of event handlers return values.
5594 static int
5595 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
5597 u16 evDataLen;
5598 u32 evData0 = 0;
5599 // u32 evCtx;
5600 int ii;
5601 int r = 0;
5602 int handlers = 0;
5603 char *evStr;
5604 u8 event;
5607 * Do platform normalization of values
5609 event = le32_to_cpu(pEventReply->Event) & 0xFF;
5610 // evCtx = le32_to_cpu(pEventReply->EventContext);
5611 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
5612 if (evDataLen) {
5613 evData0 = le32_to_cpu(pEventReply->Data[0]);
5616 evStr = EventDescriptionStr(event, evData0);
5617 devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
5618 ioc->name,
5619 evStr,
5620 event));
5622 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
5623 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
5624 for (ii = 0; ii < evDataLen; ii++)
5625 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
5626 printk("\n");
5627 #endif
5630 * Do general / base driver event processing
5632 switch(event) {
5633 case MPI_EVENT_NONE: /* 00 */
5634 case MPI_EVENT_LOG_DATA: /* 01 */
5635 case MPI_EVENT_STATE_CHANGE: /* 02 */
5636 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
5637 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
5638 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
5639 case MPI_EVENT_RESCAN: /* 06 */
5640 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
5641 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
5642 case MPI_EVENT_LOGOUT: /* 09 */
5643 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
5644 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: /* 0C */
5645 default:
5646 break;
5647 case MPI_EVENT_EVENT_CHANGE: /* 0A */
5648 if (evDataLen) {
5649 u8 evState = evData0 & 0xFF;
5651 /* CHECKME! What if evState unexpectedly says OFF (0)? */
5653 /* Update EventState field in cached IocFacts */
5654 if (ioc->facts.Function) {
5655 ioc->facts.EventState = evState;
5658 break;
5662 * Should this event be logged? Events are written sequentially.
5663 * When buffer is full, start again at the top.
5665 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
5666 int idx;
5668 idx = ioc->eventContext % ioc->eventLogSize;
5670 ioc->events[idx].event = event;
5671 ioc->events[idx].eventContext = ioc->eventContext;
5673 for (ii = 0; ii < 2; ii++) {
5674 if (ii < evDataLen)
5675 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
5676 else
5677 ioc->events[idx].data[ii] = 0;
5680 ioc->eventContext++;
5685 * Call each currently registered protocol event handler.
5687 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5688 if (MptEvHandlers[ii]) {
5689 devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
5690 ioc->name, ii));
5691 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
5692 handlers++;
5695 /* FIXME? Examine results here? */
5698 * If needed, send (a single) EventAck.
5700 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
5701 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
5702 devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
5703 ioc->name, ii));
5707 *evHandlers = handlers;
5708 return r;
5711 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5713 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
5714 * @ioc: Pointer to MPT_ADAPTER structure
5715 * @log_info: U32 LogInfo reply word from the IOC
5717 * Refer to lsi/fc_log.h.
5719 static void
5720 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
5722 static char *subcl_str[8] = {
5723 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
5724 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
5726 u8 subcl = (log_info >> 24) & 0x7;
5728 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
5729 ioc->name, log_info, subcl_str[subcl]);
5732 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5734 * mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
5735 * @ioc: Pointer to MPT_ADAPTER structure
5736 * @mr: Pointer to MPT reply frame
5737 * @log_info: U32 LogInfo word from the IOC
5739 * Refer to lsi/sp_log.h.
5741 static void
5742 mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
5744 u32 info = log_info & 0x00FF0000;
5745 char *desc = "unknown";
5747 switch (info) {
5748 case 0x00010000:
5749 desc = "bug! MID not found";
5750 if (ioc->reload_fw == 0)
5751 ioc->reload_fw++;
5752 break;
5754 case 0x00020000:
5755 desc = "Parity Error";
5756 break;
5758 case 0x00030000:
5759 desc = "ASYNC Outbound Overrun";
5760 break;
5762 case 0x00040000:
5763 desc = "SYNC Offset Error";
5764 break;
5766 case 0x00050000:
5767 desc = "BM Change";
5768 break;
5770 case 0x00060000:
5771 desc = "Msg In Overflow";
5772 break;
5774 case 0x00070000:
5775 desc = "DMA Error";
5776 break;
5778 case 0x00080000:
5779 desc = "Outbound DMA Overrun";
5780 break;
5782 case 0x00090000:
5783 desc = "Task Management";
5784 break;
5786 case 0x000A0000:
5787 desc = "Device Problem";
5788 break;
5790 case 0x000B0000:
5791 desc = "Invalid Phase Change";
5792 break;
5794 case 0x000C0000:
5795 desc = "Untagged Table Size";
5796 break;
5800 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
5803 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5805 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
5806 * @ioc: Pointer to MPT_ADAPTER structure
5807 * @ioc_status: U32 IOCStatus word from IOC
5808 * @mf: Pointer to MPT request frame
5810 * Refer to lsi/mpi.h.
5812 static void
5813 mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
5815 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
5816 char *desc = "";
5818 switch (status) {
5819 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
5820 desc = "Invalid Function";
5821 break;
5823 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
5824 desc = "Busy";
5825 break;
5827 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
5828 desc = "Invalid SGL";
5829 break;
5831 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
5832 desc = "Internal Error";
5833 break;
5835 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
5836 desc = "Reserved";
5837 break;
5839 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
5840 desc = "Insufficient Resources";
5841 break;
5843 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
5844 desc = "Invalid Field";
5845 break;
5847 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
5848 desc = "Invalid State";
5849 break;
5851 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
5852 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
5853 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
5854 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
5855 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
5856 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
5857 /* No message for Config IOCStatus values */
5858 break;
5860 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
5861 /* No message for recovered error
5862 desc = "SCSI Recovered Error";
5864 break;
5866 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
5867 desc = "SCSI Invalid Bus";
5868 break;
5870 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
5871 desc = "SCSI Invalid TargetID";
5872 break;
5874 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
5876 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
5877 U8 cdb = pScsiReq->CDB[0];
5878 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
5879 desc = "SCSI Device Not There";
5881 break;
5884 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
5885 desc = "SCSI Data Overrun";
5886 break;
5888 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
5889 /* This error is checked in scsi_io_done(). Skip.
5890 desc = "SCSI Data Underrun";
5892 break;
5894 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
5895 desc = "SCSI I/O Data Error";
5896 break;
5898 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
5899 desc = "SCSI Protocol Error";
5900 break;
5902 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
5903 desc = "SCSI Task Terminated";
5904 break;
5906 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
5907 desc = "SCSI Residual Mismatch";
5908 break;
5910 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
5911 desc = "SCSI Task Management Failed";
5912 break;
5914 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
5915 desc = "SCSI IOC Terminated";
5916 break;
5918 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
5919 desc = "SCSI Ext Terminated";
5920 break;
5922 default:
5923 desc = "Others";
5924 break;
5926 if (desc != "")
5927 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
5930 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5931 EXPORT_SYMBOL(ioc_list);
5932 EXPORT_SYMBOL(mpt_proc_root_dir);
5933 EXPORT_SYMBOL(DmpService);
5934 EXPORT_SYMBOL(mpt_register);
5935 EXPORT_SYMBOL(mpt_deregister);
5936 EXPORT_SYMBOL(mpt_event_register);
5937 EXPORT_SYMBOL(mpt_event_deregister);
5938 EXPORT_SYMBOL(mpt_reset_register);
5939 EXPORT_SYMBOL(mpt_reset_deregister);
5940 EXPORT_SYMBOL(mpt_device_driver_register);
5941 EXPORT_SYMBOL(mpt_device_driver_deregister);
5942 EXPORT_SYMBOL(mpt_get_msg_frame);
5943 EXPORT_SYMBOL(mpt_put_msg_frame);
5944 EXPORT_SYMBOL(mpt_free_msg_frame);
5945 EXPORT_SYMBOL(mpt_add_sge);
5946 EXPORT_SYMBOL(mpt_add_chain);
5947 EXPORT_SYMBOL(mpt_send_handshake_request);
5948 EXPORT_SYMBOL(mpt_handshake_req_reply_wait);
5949 EXPORT_SYMBOL(mpt_verify_adapter);
5950 EXPORT_SYMBOL(mpt_GetIocState);
5951 EXPORT_SYMBOL(mpt_print_ioc_summary);
5952 EXPORT_SYMBOL(mpt_lan_index);
5953 EXPORT_SYMBOL(mpt_stm_index);
5954 EXPORT_SYMBOL(mpt_HardResetHandler);
5955 EXPORT_SYMBOL(mpt_config);
5956 EXPORT_SYMBOL(mpt_toolbox);
5957 EXPORT_SYMBOL(mpt_findImVolumes);
5958 EXPORT_SYMBOL(mpt_read_ioc_pg_3);
5959 EXPORT_SYMBOL(mpt_alloc_fw_memory);
5960 EXPORT_SYMBOL(mpt_free_fw_memory);
5962 static struct pci_driver mptbase_driver = {
5963 .name = "mptbase",
5964 .id_table = mptbase_pci_table,
5965 .probe = mptbase_probe,
5966 .remove = __devexit_p(mptbase_remove),
5967 .driver = {
5968 .shutdown = mptbase_shutdown,
5970 #ifdef CONFIG_PM
5971 .suspend = mptbase_suspend,
5972 .resume = mptbase_resume,
5973 #endif
5976 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5978 * fusion_init - Fusion MPT base driver initialization routine.
5980 * Returns 0 for success, non-zero for failure.
5982 static int __init
5983 fusion_init(void)
5985 int i;
5986 int r;
5988 if (FusionInitCalled++) {
5989 dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n"));
5990 return 0;
5993 show_mptmod_ver(my_NAME, my_VERSION);
5994 printk(KERN_INFO COPYRIGHT "\n");
5996 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
5997 MptCallbacks[i] = NULL;
5998 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
5999 MptEvHandlers[i] = NULL;
6000 MptResetHandlers[i] = NULL;
6003 DmpService = NULL;
6005 /* NEW! 20010120 -sralston
6006 * Register ourselves (mptbase) in order to facilitate
6007 * EventNotification handling.
6009 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6011 /* Register for hard reset handling callbacks.
6013 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6014 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6015 } else {
6016 /* FIXME! */
6019 #ifdef CONFIG_PROC_FS
6020 (void) procmpt_create();
6021 #endif
6022 r = pci_module_init(&mptbase_driver);
6023 if(r)
6024 return(r);
6026 return r;
6029 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6031 * fusion_exit - Perform driver unload cleanup.
6033 * This routine frees all resources associated with each MPT adapter
6034 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6036 static void __exit
6037 fusion_exit(void)
6040 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6042 pci_unregister_driver(&mptbase_driver);
6043 mpt_reset_deregister(mpt_base_index);
6045 #ifdef CONFIG_PROC_FS
6046 procmpt_destroy();
6047 #endif
6051 module_init(fusion_init);
6052 module_exit(fusion_exit);