File: /usr/src/linux/drivers/message/fusion/mptbase.c
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.
9 *
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.
14 *
15 * This driver would not exist if not for Alan Cox's development
16 * of the linux i2o driver.
17 *
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.
22 *
23 * All manner of help from Stephen Shirron (LSI Logic):
24 * low-level FC analysis, debug + various fixes in FCxx firmware,
25 * initial port to alpha platform, various driver code optimizations,
26 * being a faithful sounding board on all sorts of issues & ideas,
27 * etc.
28 *
29 * A huge debt of gratitude is owed to David S. Miller (DaveM)
30 * for fixing much of the stupid and broken stuff in the early
31 * driver while porting to sparc64 platform. THANK YOU!
32 *
33 * Special thanks goes to the I2O LAN driver people at the
34 * University of Helsinki, who, unbeknownst to them, provided
35 * the inspiration and initial structure for this driver.
36 *
37 * A really huge debt of gratitude is owed to Eddie C. Dost
38 * for gobs of hard work fixing and optimizing LAN code.
39 * THANK YOU!
40 *
41 * Copyright (c) 1999-2001 LSI Logic Corporation
42 * Originally By: Steven J. Ralston
43 * (mailto:Steve.Ralston@lsil.com)
44 *
45 * $Id: mptbase.c,v 1.53.4.1 2001/08/24 20:07:05 sralston Exp $
46 */
47 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
48 /*
49 This program is free software; you can redistribute it and/or modify
50 it under the terms of the GNU General Public License as published by
51 the Free Software Foundation; version 2 of the License.
52
53 This program is distributed in the hope that it will be useful,
54 but WITHOUT ANY WARRANTY; without even the implied warranty of
55 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
56 GNU General Public License for more details.
57
58 NO WARRANTY
59 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
60 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
61 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
62 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
63 solely responsible for determining the appropriateness of using and
64 distributing the Program and assumes all risks associated with its
65 exercise of rights under this Agreement, including but not limited to
66 the risks and costs of program errors, damage to or loss of data,
67 programs or equipment, and unavailability or interruption of operations.
68
69 DISCLAIMER OF LIABILITY
70 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
71 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
72 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
73 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
74 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
75 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
76 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
77
78 You should have received a copy of the GNU General Public License
79 along with this program; if not, write to the Free Software
80 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
81 */
82 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
83
84 #include <linux/config.h>
85 #include <linux/version.h>
86 #include <linux/kernel.h>
87 #include <linux/module.h>
88 #include <linux/errno.h>
89 #include <linux/init.h>
90 #include <linux/slab.h>
91 #include <linux/types.h>
92 #include <linux/pci.h>
93 #include <linux/kdev_t.h>
94 #include <linux/blkdev.h>
95 #include <linux/delay.h>
96 #include <linux/proc_fs.h>
97 #include <asm/io.h>
98 #ifdef CONFIG_MTRR
99 #include <asm/mtrr.h>
100 #endif
101
102 #include "mptbase.h"
103
104 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
105 #define my_NAME "Fusion MPT base driver"
106 #define my_VERSION MPT_LINUX_VERSION_COMMON
107 #define MYNAM "mptbase"
108
109 MODULE_AUTHOR(MODULEAUTHOR);
110 MODULE_DESCRIPTION(my_NAME);
111
112 /*
113 * cmd line parameters
114 */
115 MODULE_PARM(PortIo, "0-1i");
116 MODULE_PARM_DESC(PortIo, "[0]=Use mmap, 1=Use port io");
117 MODULE_PARM(HardReset, "0-1i");
118 MODULE_PARM_DESC(HardReset, "0=Disable HardReset, [1]=Enable HardReset");
119 static int PortIo = 0;
120 static int HardReset = 1;
121
122 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
123 /*
124 * Public data...
125 */
126 int mpt_lan_index = 0;
127 int mpt_stm_index = 0;
128
129 void *mpt_v_ASCQ_TablePtr = NULL;
130 const char **mpt_ScsiOpcodesPtr = NULL;
131 int mpt_ASCQ_TableSz = 0;
132
133 #define WHOINIT_UNKNOWN 0xAA
134
135 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
136 /*
137 * Private data...
138 */
139 /* Adapter lookup table */
140 static MPT_ADAPTER *mpt_adapters[MPT_MAX_ADAPTERS] = {0};
141 static MPT_ADAPTER_TRACKER MptAdapters;
142 /* Callback lookup table */
143 static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
144 /* Protocol driver class lookup table */
145 static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
146 /* Event handler lookup table */
147 static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
148 /* Reset handler lookup table */
149 static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
150
151 static int FusionInitCalled = 0;
152 static int mpt_base_index = -1;
153
154 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
155 /*
156 * Forward protos...
157 */
158 static void mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
159 static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
160
161 static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason);
162 static int mpt_adapter_install(struct pci_dev *pdev);
163 static void mpt_detect_929_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);
164 static void mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup);
165 static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
166
167 static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
168 static int MakeIocReady(MPT_ADAPTER *ioc, int force);
169 static u32 GetIocState(MPT_ADAPTER *ioc, int cooked);
170 static int GetIocFacts(MPT_ADAPTER *ioc);
171 static int GetPortFacts(MPT_ADAPTER *ioc, int portnum);
172 static int SendIocInit(MPT_ADAPTER *ioc);
173 static int SendPortEnable(MPT_ADAPTER *ioc, int portnum);
174 static int mpt_fc9x9_reset(MPT_ADAPTER *ioc, int ignore);
175 static int KickStart(MPT_ADAPTER *ioc, int ignore);
176 static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type);
177 static int PrimeIocFifos(MPT_ADAPTER *ioc);
178 static int HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait);
179 static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong);
180 static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong);
181 static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong);
182 static int GetLanConfigPages(MPT_ADAPTER *ioc);
183 static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
184 static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
185
186 static int procmpt_create(void);
187 #ifdef CONFIG_PROC_FS
188 static int procmpt_destroy(void);
189 #endif
190 static int procmpt_read_summary(char *page, char **start, off_t off, int count, int *eof, void *data);
191 static int procmpt_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data);
192 /*static int procmpt_info(char *buf, char **start, off_t offset, int len);*/
193
194 static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
195 static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
196 static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
197
198 static struct proc_dir_entry *procmpt_root_dir = NULL;
199
200 int fusion_init(void);
201 static void fusion_exit(void);
202
203 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
204 /* 20000207 -sralston
205 * GRRRRR... IOSpace (port i/o) register access (for the 909) is back!
206 * 20000517 -sralston
207 * Let's trying going back to default mmap register access...
208 */
209
210 static inline u32 CHIPREG_READ32(volatile u32 *a)
211 {
212 if (PortIo)
213 return inl((unsigned long)a);
214 else
215 return readl(a);
216 }
217
218 static inline void CHIPREG_WRITE32(volatile u32 *a, u32 v)
219 {
220 if (PortIo)
221 outl(v, (unsigned long)a);
222 else
223 writel(v, a);
224 }
225
226
227 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
228 /**
229 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
230 * @irq: irq number (not used)
231 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
232 * @r: pt_regs pointer (not used)
233 *
234 * This routine is registered via the request_irq() kernel API call,
235 * and handles all interrupts generated from a specific MPT adapter
236 * (also referred to as a IO Controller or IOC).
237 * This routine must clear the interrupt from the adapter and does
238 * so by reading the reply FIFO. Multiple replies may be processed
239 * per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
240 * which is currently set to 32 in mptbase.h.
241 *
242 * This routine handles register-level access of the adapter but
243 * dispatches (calls) a protocol-specific callback routine to handle
244 * the protocol-specific details of the MPT request completion.
245 */
246 static void
247 mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
248 {
249 MPT_ADAPTER *ioc;
250 MPT_FRAME_HDR *mf;
251 MPT_FRAME_HDR *mr;
252 u32 pa;
253 u32 *m;
254 int req_idx;
255 int cb_idx;
256 int type;
257 int freeme;
258 int count = 0;
259
260 ioc = bus_id;
261
262 /*
263 * Drain the reply FIFO!
264 *
265 * NOTES: I've seen up to 10 replies processed in this loop, so far...
266 * Update: I've seen up to 9182 replies processed in this loop! ??
267 * Update: Limit ourselves to processing max of N replies
268 * (bottom of loop).
269 */
270 while (1) {
271
272 if ((pa = CHIPREG_READ32(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)
273 return;
274
275 cb_idx = 0;
276 freeme = 0;
277
278 /*
279 * Check for non-TURBO reply!
280 */
281 if (pa & MPI_ADDRESS_REPLY_A_BIT) {
282 dma_addr_t reply_dma_addr;
283 u16 ioc_stat;
284
285 /* non-TURBO reply! Hmmm, something may be up...
286 * Newest turbo reply mechanism; get address
287 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
288 */
289 reply_dma_addr = (pa = (pa << 1));
290
291 /* Map DMA address of reply header to cpu address. */
292 m = (u32 *) ((u8 *)ioc->reply_frames +
293 (reply_dma_addr - ioc->reply_frames_dma));
294
295 mr = (MPT_FRAME_HDR *) m;
296 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
297 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
298 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
299
300 dprintk((KERN_INFO MYNAM ": %s: Got non-TURBO reply=%p\n",
301 ioc->name, mr));
302 DBG_DUMP_REPLY_FRAME(mr)
303
304 /* NEW! 20010301 -sralston
305 * Check/log IOC log info
306 */
307 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
308 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
309 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
310 if ((int)ioc->chip_type <= (int)FC929)
311 mpt_fc_log_info(ioc, log_info);
312 else
313 mpt_sp_log_info(ioc, log_info);
314 }
315 } else {
316 /*
317 * Process turbo (context) reply...
318 */
319 dirqprintk((KERN_INFO MYNAM ": %s: Got TURBO reply(=%08x)\n", ioc->name, pa));
320 type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
321 if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
322 cb_idx = mpt_stm_index;
323 mf = NULL;
324 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
325 } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
326 cb_idx = mpt_lan_index;
327 /*
328 * BUG FIX! 20001218 -sralston
329 * Blind set of mf to NULL here was fatal
330 * after lan_reply says "freeme"
331 * Fix sort of combined with an optimization here;
332 * added explicit check for case where lan_reply
333 * was just returning 1 and doing nothing else.
334 * For this case skip the callback, but set up
335 * proper mf value first here:-)
336 */
337 if ((pa & 0x58000000) == 0x58000000) {
338 req_idx = pa & 0x0000FFFF;
339 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
340 freeme = 1;
341 /*
342 * IMPORTANT! Invalidate the callback!
343 */
344 cb_idx = 0;
345 } else {
346 mf = NULL;
347 }
348 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
349 } else {
350 req_idx = pa & 0x0000FFFF;
351 cb_idx = (pa & 0x00FF0000) >> 16;
352 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
353 mr = NULL;
354 }
355 pa = 0; /* No reply flush! */
356 }
357
358 /* Check for (valid) IO callback! */
359 if (cb_idx) {
360 /* Do the callback! */
361 freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);
362 }
363
364 if (pa) {
365 /* Flush (non-TURBO) reply with a WRITE! */
366 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
367 }
368
369 if (freeme) {
370 unsigned long flags;
371
372 /* Put Request back on FreeQ! */
373 spin_lock_irqsave(&ioc->FreeQlock, flags);
374 Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
375 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
376 }
377
378 count++;
379 dirqprintk((KERN_INFO MYNAM ": %s: ISR processed frame #%d\n", ioc->name, count));
380 mb();
381
382 if (count >= MPT_MAX_REPLIES_PER_ISR) {
383 dirqprintk((KERN_INFO MYNAM ": %s: ISR processed %d replies.",
384 ioc->name, count));
385 dirqprintk((" Giving this ISR a break!\n"));
386 return;
387 }
388
389 } /* drain reply FIFO */
390 }
391
392 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
393 /*
394 * mpt_base_reply - MPT base driver's callback routine; all base driver
395 * "internal" request/reply processing is routed here.
396 * Currently used for EventNotification and EventAck handling.
397 * @ioc: Pointer to MPT_ADAPTER structure
398 * @mf: Pointer to original MPT request frame
399 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
400 *
401 * Returns 1 indicating original alloc'd request frame ptr
402 * should be freed, or 0 if it shouldn't.
403 */
404 static int
405 mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
406 {
407 int freereq = 1;
408 u8 func;
409
410 dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply() called\n", ioc->name));
411
412 if ((mf == NULL) ||
413 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
414 printk(KERN_ERR MYNAM ": %s: ERROR - NULL or BAD request frame ptr! (=%p)\n",
415 ioc->name, mf);
416 return 1;
417 }
418
419 if (reply == NULL) {
420 dprintk((KERN_ERR MYNAM ": %s: ERROR - Unexpected NULL Event (turbo?) reply!\n",
421 ioc->name));
422 return 1;
423 }
424
425 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
426 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
427 DBG_DUMP_REQUEST_FRAME_HDR(mf)
428 }
429
430 func = reply->u.hdr.Function;
431 dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply, Function=%02Xh\n",
432 ioc->name, func));
433
434 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
435 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
436 int evHandlers = 0;
437 int results;
438
439 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
440 if (results != evHandlers) {
441 /* CHECKME! Any special handling needed here? */
442 dprintk((KERN_WARNING MYNAM ": %s: Hmmm... Called %d event handlers, sum results = %d\n",
443 ioc->name, evHandlers, results));
444 }
445
446 /*
447 * Hmmm... It seems that EventNotificationReply is an exception
448 * to the rule of one reply per request.
449 */
450 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
451 freereq = 0;
452 #ifdef CONFIG_PROC_FS
453 // LogEvent(ioc, pEvReply);
454 #endif
455 } else if (func == MPI_FUNCTION_EVENT_ACK) {
456 dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply, EventAck reply received\n",
457 ioc->name));
458 } else {
459 printk(KERN_ERR MYNAM ": %s: ERROR - Unexpected msg function (=%02Xh) reply received!\n",
460 ioc->name, func);
461 }
462
463 /*
464 * Conditionally tell caller to free the original
465 * EventNotification/EventAck/unexpected request frame!
466 */
467 return freereq;
468 }
469
470 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
471 /**
472 * mpt_register - Register protocol-specific main callback handler.
473 * @cbfunc: callback function pointer
474 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
475 *
476 * This routine is called by a protocol-specific driver (SCSI host,
477 * LAN, SCSI target) to register it's reply callback routine. Each
478 * protocol-specific driver must do this before it will be able to
479 * use any IOC resources, such as obtaining request frames.
480 *
481 * NOTES: The SCSI protocol driver currently calls this routine twice
482 * in order to register separate callbacks; one for "normal" SCSI IO
483 * and another for MptScsiTaskMgmt requests.
484 *
485 * Returns a positive integer valued "handle" in the
486 * range (and S.O.D. order) {7,6,...,1} if successful.
487 * Any non-positive return value (including zero!) should be considered
488 * an error by the caller.
489 */
490 int
491 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
492 {
493 int r = -1;
494 int i;
495
496 #ifndef MODULE
497 /*
498 * Handle possibility of the mptscsih_detect() routine getting
499 * called *before* fusion_init!
500 */
501 if (!FusionInitCalled) {
502 dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n"));
503 /*
504 * NOTE! We'll get recursion here, as fusion_init()
505 * calls mpt_register()!
506 */
507 fusion_init();
508 FusionInitCalled++;
509 }
510 #endif
511
512 /*
513 * Search for empty callback slot in this order: {7,6,...,1}
514 * (slot/handle 0 is reserved!)
515 */
516 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
517 if (MptCallbacks[i] == NULL) {
518 MptCallbacks[i] = cbfunc;
519 MptDriverClass[i] = dclass;
520 MptEvHandlers[i] = NULL;
521 r = i;
522 if (cbfunc != mpt_base_reply) {
523 MOD_INC_USE_COUNT;
524 }
525 break;
526 }
527 }
528
529 return r;
530 }
531
532 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
533 /**
534 * mpt_deregister - Deregister a protocol drivers resources.
535 * @cb_idx: previously registered callback handle
536 *
537 * Each protocol-specific driver should call this routine when it's
538 * module is unloaded.
539 */
540 void
541 mpt_deregister(int cb_idx)
542 {
543 if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
544 MptCallbacks[cb_idx] = NULL;
545 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
546 MptEvHandlers[cb_idx] = NULL;
547 if (cb_idx != mpt_base_index) {
548 MOD_DEC_USE_COUNT;
549 }
550 }
551 }
552
553 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
554 /**
555 * mpt_event_register - Register protocol-specific event callback
556 * handler.
557 * @cb_idx: previously registered (via mpt_register) callback handle
558 * @ev_cbfunc: callback function
559 *
560 * This routine can be called by one or more protocol-specific drivers
561 * if/when they choose to be notified of MPT events.
562 *
563 * Returns 0 for success.
564 */
565 int
566 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
567 {
568 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
569 return -1;
570
571 MptEvHandlers[cb_idx] = ev_cbfunc;
572 return 0;
573 }
574
575 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
576 /**
577 * mpt_event_deregister - Deregister protocol-specific event callback
578 * handler.
579 * @cb_idx: previously registered callback handle
580 *
581 * Each protocol-specific driver should call this routine
582 * when it does not (or can no longer) handle events,
583 * or when it's module is unloaded.
584 */
585 void
586 mpt_event_deregister(int cb_idx)
587 {
588 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
589 return;
590
591 MptEvHandlers[cb_idx] = NULL;
592 }
593
594 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
595 /**
596 * mpt_reset_register - Register protocol-specific IOC reset handler.
597 * @cb_idx: previously registered (via mpt_register) callback handle
598 * @reset_func: reset function
599 *
600 * This routine can be called by one or more protocol-specific drivers
601 * if/when they choose to be notified of IOC resets.
602 *
603 * Returns 0 for success.
604 */
605 int
606 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
607 {
608 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
609 return -1;
610
611 MptResetHandlers[cb_idx] = reset_func;
612 return 0;
613 }
614
615 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
616 /**
617 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
618 * @cb_idx: previously registered callback handle
619 *
620 * Each protocol-specific driver should call this routine
621 * when it does not (or can no longer) handle IOC reset handling,
622 * or when it's module is unloaded.
623 */
624 void
625 mpt_reset_deregister(int cb_idx)
626 {
627 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
628 return;
629
630 MptResetHandlers[cb_idx] = NULL;
631 }
632
633 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
634 /**
635 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
636 * allocated per MPT adapter.
637 * @handle: Handle of registered MPT protocol driver
638 * @iocid: IOC unique identifier (integer)
639 *
640 * Returns pointer to a MPT request frame or %NULL if none are available.
641 */
642 MPT_FRAME_HDR*
643 mpt_get_msg_frame(int handle, int iocid)
644 {
645 MPT_FRAME_HDR *mf = NULL;
646 MPT_ADAPTER *iocp;
647 unsigned long flags;
648
649 /* validate handle and ioc identifier */
650 iocp = mpt_adapters[iocid];
651 spin_lock_irqsave(&iocp->FreeQlock, flags);
652 if (! Q_IS_EMPTY(&iocp->FreeQ)) {
653 int req_offset;
654
655 mf = iocp->FreeQ.head;
656 Q_DEL_ITEM(&mf->u.frame.linkage);
657 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
658 req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
659 /* u16! */
660 mf->u.frame.hwhdr.msgctxu.fld.req_idx =
661 cpu_to_le16(req_offset / iocp->req_sz);
662 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
663 }
664 spin_unlock_irqrestore(&iocp->FreeQlock, flags);
665 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
666 iocp->name, handle, iocid, mf));
667 return mf;
668 }
669
670 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
671 /**
672 * mpt_put_msg_frame - Send a protocol specific MPT request frame
673 * to a IOC.
674 * @handle: Handle of registered MPT protocol driver
675 * @iocid: IOC unique identifier (integer)
676 * @mf: Pointer to MPT request frame
677 *
678 * This routine posts a MPT request frame to the request post FIFO of a
679 * specific MPT adapter.
680 */
681 void
682 mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
683 {
684 MPT_ADAPTER *iocp;
685
686 iocp = mpt_adapters[iocid];
687 if (iocp != NULL) {
688 dma_addr_t mf_dma_addr;
689 int req_offset;
690
691 /* ensure values are reset properly! */
692 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
693 req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
694 /* u16! */
695 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz);
696 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
697
698 #ifdef MPT_DEBUG_MSG_FRAME
699 {
700 u32 *m = mf->u.frame.hwhdr.__hdr;
701 int i, n;
702
703 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
704 iocp->name, m);
705 n = iocp->req_sz/4 - 1;
706 while (m[n] == 0)
707 n--;
708 for (i=0; i<=n; i++) {
709 if (i && ((i%8)==0))
710 printk("\n" KERN_INFO " ");
711 printk(" %08x", le32_to_cpu(m[i]));
712 }
713 printk("\n");
714 }
715 #endif
716
717 mf_dma_addr = iocp->req_frames_dma + req_offset;
718 CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);
719 }
720 }
721
722 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
723 /**
724 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
725 * @handle: Handle of registered MPT protocol driver
726 * @iocid: IOC unique identifier (integer)
727 * @mf: Pointer to MPT request frame
728 *
729 * This routine places a MPT request frame back on the MPT adapter's
730 * FreeQ.
731 */
732 void
733 mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf)
734 {
735 MPT_ADAPTER *iocp;
736 unsigned long flags;
737
738 iocp = mpt_adapters[iocid];
739 if (iocp != NULL) {
740 /* Put Request back on FreeQ! */
741 spin_lock_irqsave(&iocp->FreeQlock, flags);
742 Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
743 spin_unlock_irqrestore(&iocp->FreeQlock, flags);
744 }
745 }
746
747 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
748 /**
749 * mpt_send_handshake_request - Send MPT request via doorbell
750 * handshake method.
751 * @handle: Handle of registered MPT protocol driver
752 * @iocid: IOC unique identifier (integer)
753 * @reqBytes: Size of the request in bytes
754 * @req: Pointer to MPT request frame
755 *
756 * This routine is used exclusively by mptscsih to send MptScsiTaskMgmt
757 * requests since they are required to be sent via doorbell handshake.
758 *
759 * NOTE: It is the callers responsibility to byte-swap fields in the
760 * request which are greater than 1 byte in size.
761 *
762 * Returns 0 for success, non-zero for failure.
763 */
764 int
765 mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req)
766 {
767 MPT_ADAPTER *iocp;
768 int r = 0;
769
770 iocp = mpt_adapters[iocid];
771 if (iocp != NULL) {
772 u8 *req_as_bytes;
773 u32 ioc_raw_state;
774 int i;
775
776 /* YIKES! We already know something is amiss.
777 * Do upfront check on IOC state.
778 */
779 ioc_raw_state = GetIocState(iocp, 0);
780 if ((ioc_raw_state & MPI_DOORBELL_ACTIVE) ||
781 ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL)) {
782 printk(KERN_WARNING MYNAM ": %s: Bad IOC state (%08x) WARNING!\n",
783 iocp->name, ioc_raw_state);
784 if ((r = mpt_do_ioc_recovery(iocp, MPT_HOSTEVENT_IOC_RECOVER)) != 0) {
785 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
786 r, iocp->name);
787 return r;
788 }
789 }
790
791 /*
792 * Emulate what mpt_put_msg_frame() does /wrt to sanity
793 * setting cb_idx/req_idx. But ONLY if this request
794 * is in proper (pre-alloc'd) request buffer range...
795 */
796 i = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req);
797 if (reqBytes >= 12 && i >= 0 && i < iocp->req_depth) {
798 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
799 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(i);
800 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
801 }
802
803 /* Make sure there are no doorbells */
804 CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
805
806 CHIPREG_WRITE32(&iocp->chip->Doorbell,
807 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
808 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
809
810 /* Wait for IOC doorbell int */
811 if ((i = WaitForDoorbellInt(iocp, 2)) < 0) {
812 return i;
813 }
814
815 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
816 iocp->name, i));
817
818 CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
819
820 if ((r = WaitForDoorbellAck(iocp, 1)) < 0) {
821 return -2;
822 }
823
824 /* Send request via doorbell handshake */
825 req_as_bytes = (u8 *) req;
826 for (i = 0; i < reqBytes/4; i++) {
827 u32 word;
828
829 word = ((req_as_bytes[(i*4) + 0] << 0) |
830 (req_as_bytes[(i*4) + 1] << 8) |
831 (req_as_bytes[(i*4) + 2] << 16) |
832 (req_as_bytes[(i*4) + 3] << 24));
833 CHIPREG_WRITE32(&iocp->chip->Doorbell, word);
834 if ((r = WaitForDoorbellAck(iocp, 1)) < 0) {
835 r = -3;
836 break;
837 }
838 }
839
840 if ((r = WaitForDoorbellInt(iocp, 2)) >= 0)
841 r = 0;
842 else
843 r = -4;
844
845 /* Make sure there are no doorbells */
846 CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
847 }
848
849 return r;
850 }
851
852 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
853 /**
854 * mpt_adapter_find_first - Find first MPT adapter pointer.
855 *
856 * Returns first MPT adapter pointer or %NULL if no MPT adapters
857 * are present.
858 */
859 MPT_ADAPTER *
860 mpt_adapter_find_first(void)
861 {
862 MPT_ADAPTER *this = NULL;
863
864 if (! Q_IS_EMPTY(&MptAdapters))
865 this = MptAdapters.head;
866
867 return this;
868 }
869
870 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
871 /**
872 * mpt_adapter_find_next - Find next MPT adapter pointer.
873 * @prev: Pointer to previous MPT adapter
874 *
875 * Returns next MPT adapter pointer or %NULL if there are no more.
876 */
877 MPT_ADAPTER *
878 mpt_adapter_find_next(MPT_ADAPTER *prev)
879 {
880 MPT_ADAPTER *next = NULL;
881
882 if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head))
883 next = prev->forw;
884
885 return next;
886 }
887
888 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
889 /**
890 * mpt_pci_scan - Scan PCI devices for MPT adapters.
891 *
892 * Returns count of MPT adapters found, keying off of PCI vendor and
893 * device_id's.
894 */
895 int __init
896 mpt_pci_scan(void)
897 {
898 struct pci_dev *pdev;
899 struct pci_dev *pdev2;
900 int found = 0;
901 int count = 0;
902 int r;
903
904 dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n"));
905
906 /*
907 * NOTE: The 929 (I believe) will appear as 2 separate PCI devices,
908 * one for each channel.
909 */
910 pci_for_each_dev(pdev) {
911 pdev2 = NULL;
912 if (pdev->vendor != 0x1000)
913 continue;
914
915 if ((pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC909) &&
916 (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929) &&
917 (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919) &&
918 #if 0
919 /* FIXME! C103x family */
920 (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) &&
921 (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030_ZC) &&
922 (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1035) &&
923 #endif
924 1) {
925 dprintk((KERN_INFO MYNAM ": Skipping LSI device=%04xh\n", pdev->device));
926 continue;
927 }
928
929 /* GRRRRR
930 * 929 dual function devices may be presented in Func 1,0 order,
931 * but we'd really really rather have them in Func 0,1 order.
932 * Do some kind of look ahead here...
933 */
934 if (pdev->devfn & 1) {
935 pdev2 = pci_peek_next_dev(pdev);
936 if (pdev2 && (pdev2->vendor == 0x1000) &&
937 (PCI_SLOT(pdev2->devfn) == PCI_SLOT(pdev->devfn)) &&
938 (pdev2->device == MPI_MANUFACTPAGE_DEVICEID_FC929) &&
939 (pdev2->bus->number == pdev->bus->number) &&
940 !(pdev2->devfn & 1)) {
941 dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n",
942 pdev2->bus->number, pdev2->devfn, pdev2->class, pdev2->device));
943 found++;
944 if ((r = mpt_adapter_install(pdev2)) == 0)
945 count++;
946 } else {
947 pdev2 = NULL;
948 }
949 }
950
951 dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n",
952 pdev->bus->number, pdev->devfn, pdev->class, pdev->device));
953 found++;
954 if ((r = mpt_adapter_install(pdev)) == 0)
955 count++;
956
957 if (pdev2)
958 pdev = pdev2;
959 }
960
961 printk(KERN_INFO MYNAM ": %d MPT adapter%s found, %d installed.\n",
962 found, (found==1) ? "" : "s", count);
963
964 if (!found || !count) {
965 fusion_exit();
966 return -ENODEV;
967 }
968
969 #ifdef CONFIG_PROC_FS
970 if (procmpt_create() != 0)
971 printk(KERN_WARNING MYNAM ": WARNING! - %s creation failed!\n",
972 MPT_PROCFS_MPTBASEDIR);
973 #endif
974
975 return count;
976 }
977
978 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
979 /**
980 * mpt_verify_adapter - Given a unique IOC identifier, set pointer to
981 * the associated MPT adapter structure.
982 * @iocid: IOC unique identifier (integer)
983 * @iocpp: Pointer to pointer to IOC adapter
984 *
985 * Returns iocid and sets iocpp.
986 */
987 int
988 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
989 {
990 MPT_ADAPTER *p;
991
992 *iocpp = NULL;
993 if (iocid >= MPT_MAX_ADAPTERS)
994 return -1;
995
996 p = mpt_adapters[iocid];
997 if (p == NULL)
998 return -1;
999
1000 *iocpp = p;
1001 return iocid;
1002 }
1003
1004 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1005 /**
1006 * mpt_adapter_install - Install a PCI intelligent MPT adapter.
1007 * @pdev: Pointer to pci_dev structure
1008 *
1009 * This routine performs all the steps necessary to bring the IOC of
1010 * a MPT adapter to a OPERATIONAL state. This includes registering
1011 * memory regions, registering the interrupt, and allocating request
1012 * and reply memory pools.
1013 *
1014 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1015 * MPT adapter.
1016 *
1017 * Returns 0 for success, non-zero for failure.
1018 *
1019 * TODO: Add support for polled controllers
1020 */
1021 static int __init
1022 mpt_adapter_install(struct pci_dev *pdev)
1023 {
1024 MPT_ADAPTER *ioc;
1025 char *myname;
1026 u8 *mem;
1027 unsigned long mem_phys;
1028 unsigned long port;
1029 u32 msize;
1030 u32 psize;
1031 int i;
1032 int r = -ENODEV;
1033 int len;
1034
1035 ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_KERNEL);
1036 if (ioc == NULL) {
1037 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1038 return -ENOMEM;
1039 }
1040 memset(ioc, 0, sizeof(*ioc));
1041 ioc->req_sz = MPT_REQ_SIZE; /* avoid div by zero! */
1042 ioc->alloc_total = sizeof(MPT_ADAPTER);
1043
1044 ioc->pcidev = pdev;
1045
1046 /* Find lookup slot. */
1047 for (i=0; i < MPT_MAX_ADAPTERS; i++) {
1048 if (mpt_adapters[i] == NULL) {
1049 ioc->id = i; /* Assign adapter unique id (lookup) */
1050 break;
1051 }
1052 }
1053 if (i == MPT_MAX_ADAPTERS) {
1054 printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", i);
1055 kfree(ioc);
1056 return -ENFILE;
1057 }
1058
1059 mem_phys = msize = 0;
1060 port = psize = 0;
1061 for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {
1062 if (pdev->PCI_BASEADDR_FLAGS(i) & PCI_BASE_ADDRESS_SPACE_IO) {
1063 /* Get I/O space! */
1064 port = pdev->PCI_BASEADDR_START(i);
1065 psize = PCI_BASEADDR_SIZE(pdev,i);
1066 } else {
1067 /* Get memmap */
1068 mem_phys = pdev->PCI_BASEADDR_START(i);
1069 msize = PCI_BASEADDR_SIZE(pdev,i);
1070 break;
1071 }
1072 }
1073 ioc->mem_size = msize;
1074
1075 if (i == DEVICE_COUNT_RESOURCE) {
1076 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1077 kfree(ioc);
1078 return -EINVAL;
1079 }
1080
1081 dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1082 dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1083 dprintk((KERN_INFO MYNAM ": Using %s register access method\n", PortIo ? "PortIo" : "MemMap"));
1084
1085 mem = NULL;
1086 if (! PortIo) {
1087 /* Get logical ptr for PciMem0 space */
1088 /*mem = ioremap(mem_phys, msize);*/
1089 mem = ioremap(mem_phys, 0x100);
1090 if (mem == NULL) {
1091 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1092 kfree(ioc);
1093 return -EINVAL;
1094 }
1095 ioc->memmap = mem;
1096 }
1097 dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1098
1099 if (PortIo) {
1100 u8 *pmem = (u8*)port;
1101 ioc->mem_phys = port;
1102 ioc->chip = (SYSIF_REGS*)pmem;
1103 } else {
1104 ioc->mem_phys = mem_phys;
1105 ioc->chip = (SYSIF_REGS*)mem;
1106 }
1107
1108 ioc->chip_type = FCUNK;
1109 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1110 ioc->chip_type = FC909;
1111 ioc->prod_name = "LSIFC909";
1112 }
1113 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1114 ioc->chip_type = FC929;
1115 ioc->prod_name = "LSIFC929";
1116 }
1117 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1118 ioc->chip_type = FC919;
1119 ioc->prod_name = "LSIFC919";
1120 }
1121 #if 0
1122 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_53C1030) {
1123 ioc->chip_type = C1030;
1124 ioc->prod_name = "LSI53C1030";
1125 }
1126 #endif
1127
1128 myname = "iocN";
1129 len = strlen(myname);
1130 memcpy(ioc->name, myname, len+1);
1131 ioc->name[len-1] = '0' + ioc->id;
1132
1133 Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
1134 spin_lock_init(&ioc->FreeQlock);
1135
1136 /* Disable all! */
1137 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1138 ioc->active = 0;
1139 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1140
1141 ioc->pci_irq = -1;
1142 if (pdev->irq) {
1143 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1144
1145 if (r < 0) {
1146 printk(KERN_ERR MYNAM ": %s: ERROR - Unable to allocate interrupt %d!\n",
1147 ioc->name, pdev->irq);
1148 iounmap(mem);
1149 kfree(ioc);
1150 return -EBUSY;
1151 }
1152
1153 ioc->pci_irq = pdev->irq;
1154
1155 pci_set_master(pdev); /* ?? */
1156
1157 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
1158 }
1159
1160 /* tack onto tail of our MPT adapter list */
1161 Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER);
1162
1163 /* Set lookup ptr. */
1164 mpt_adapters[ioc->id] = ioc;
1165
1166 /* NEW! 20010220 -sralston
1167 * Check for "929 bound ports" to reduce redundant resets.
1168 */
1169 if (ioc->chip_type == FC929)
1170 mpt_detect_929_bound_ports(ioc, pdev);
1171
1172 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) {
1173 printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n",
1174 ioc->name, r);
1175 }
1176
1177 return r;
1178 }
1179
1180 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1181 /**
1182 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1183 * @ioc: Pointer to MPT adapter structure
1184 * @reason: Event word / reason
1185 *
1186 * This routine performs all the steps necessary to bring the IOC
1187 * to a OPERATIONAL state.
1188 *
1189 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1190 * MPT adapter.
1191 *
1192 * Returns 0 for success.
1193 */
1194 static int
1195 mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason)
1196 {
1197 int hard_reset_done = 0;
1198 int alt_ioc_ready = 0;
1199 int hard;
1200 int r;
1201 int i;
1202 int handlers;
1203
1204 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1205 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1206
1207 /* Disable reply interrupts */
1208 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1209 ioc->active = 0;
1210 /* NOTE: Access to IOC's request FreeQ is now blocked! */
1211
1212 // FIXME? Cleanup all IOC requests here! (or below?)
1213 // But watch out for event associated request?
1214
1215 hard = HardReset;
1216 if (ioc->alt_ioc && (reason == MPT_HOSTEVENT_IOC_BRINGUP))
1217 hard = 0;
1218
1219 if ((hard_reset_done = MakeIocReady(ioc, hard)) < 0) {
1220 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1221 ioc->name);
1222 return -1;
1223 }
1224
1225 // NEW!
1226 #if 0 // Kiss-of-death!?!
1227 if (ioc->alt_ioc) {
1228 // Grrr... Hold off any alt-IOC interrupts (and events) while
1229 // handshaking to <this> IOC, needed because?
1230 /* Disable alt-IOC's reply interrupts for a bit ... */
1231 alt_ioc_intmask = CHIPREG_READ32(&ioc->alt_ioc->chip->IntMask);
1232 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1233 ioc->alt_ioc->active = 0;
1234 /* NOTE: Access to alt-IOC's request FreeQ is now blocked! */
1235 }
1236 #endif
1237
1238 if (hard_reset_done && ioc->alt_ioc) {
1239 if ((r = MakeIocReady(ioc->alt_ioc, 0)) == 0)
1240 alt_ioc_ready = 1;
1241 else
1242 printk(KERN_WARNING MYNAM ": alt-%s: (%d) Not ready WARNING!\n",
1243 ioc->alt_ioc->name, r);
1244 }
1245
1246 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1247 /* Get IOC facts! */
1248 if ((r = GetIocFacts(ioc)) != 0)
1249 return -2;
1250 MptDisplayIocCapabilities(ioc);
1251 }
1252
1253 /*
1254 * Call each currently registered protocol IOC reset handler
1255 * with pre-reset indication.
1256 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1257 * MptResetHandlers[] registered yet.
1258 */
1259 if (hard_reset_done) {
1260 r = handlers = 0;
1261 for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
1262 if (MptResetHandlers[i]) {
1263 dprintk((KERN_INFO MYNAM ": %s: Calling IOC pre_reset handler #%d\n",
1264 ioc->name, i));
1265 r += (*(MptResetHandlers[i]))(ioc, MPT_IOC_PRE_RESET);
1266 handlers++;
1267
1268 if (alt_ioc_ready) {
1269 dprintk((KERN_INFO MYNAM ": %s: Calling alt-IOC pre_reset handler #%d\n",
1270 ioc->alt_ioc->name, i));
1271 r += (*(MptResetHandlers[i]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
1272 handlers++;
1273 }
1274 }
1275 }
1276 /* FIXME? Examine results here? */
1277 }
1278
1279 // May need to check/upload firmware & data here!
1280
1281 if ((r = SendIocInit(ioc)) != 0)
1282 return -3;
1283 // NEW!
1284 if (alt_ioc_ready) {
1285 if ((r = SendIocInit(ioc->alt_ioc)) != 0) {
1286 alt_ioc_ready = 0;
1287 printk(KERN_WARNING MYNAM ": alt-%s: (%d) init failure WARNING!\n",
1288 ioc->alt_ioc->name, r);
1289 }
1290 }
1291
1292 /*
1293 * Call each currently registered protocol IOC reset handler
1294 * with post-reset indication.
1295 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1296 * MptResetHandlers[] registered yet.
1297 */
1298 if (hard_reset_done) {
1299 r = handlers = 0;
1300 for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
1301 if (MptResetHandlers[i]) {
1302 dprintk((KERN_INFO MYNAM ": %s: Calling IOC post_reset handler #%d\n",
1303 ioc->name, i));
1304 r += (*(MptResetHandlers[i]))(ioc, MPT_IOC_POST_RESET);
1305 handlers++;
1306
1307 if (alt_ioc_ready) {
1308 dprintk((KERN_INFO MYNAM ": %s: Calling alt-IOC post_reset handler #%d\n",
1309 ioc->alt_ioc->name, i));
1310 r += (*(MptResetHandlers[i]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
1311 handlers++;
1312 }
1313 }
1314 }
1315 /* FIXME? Examine results here? */
1316 }
1317
1318 /*
1319 * Prime reply & request queues!
1320 * (mucho alloc's)
1321 */
1322 if ((r = PrimeIocFifos(ioc)) != 0)
1323 return -4;
1324 // NEW!
1325 if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1326 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1327 ioc->alt_ioc->name, r);
1328 }
1329
1330 // FIXME! Cleanup all IOC (and alt-IOC?) requests here!
1331
1332 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1333 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1334 /*
1335 * Pre-fetch the ports LAN MAC address!
1336 * (LANPage1_t stuff)
1337 */
1338 (void) GetLanConfigPages(ioc);
1339 #ifdef MPT_DEBUG
1340 {
1341 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1342 dprintk((KERN_INFO MYNAM ": %s: LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1343 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1344 }
1345 #endif
1346 }
1347
1348 /* Enable! (reply interrupt) */
1349 CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
1350 ioc->active = 1;
1351
1352 // NEW!
1353 #if 0 // Kiss-of-death!?!
1354 if (alt_ioc_ready && (r==0)) {
1355 /* (re)Enable alt-IOC! (reply interrupt) */
1356 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1357 ioc->alt_ioc->name));
1358 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
1359 ioc->alt_ioc->active = 1;
1360 }
1361 #endif
1362
1363 /* NEW! 20010120 -sralston
1364 * Enable MPT base driver management of EventNotification
1365 * and EventAck handling.
1366 */
1367 if (!ioc->facts.EventState)
1368 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1369 // NEW!
1370 // FIXME!?!
1371 // if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) {
1372 // (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1373 // }
1374
1375 return 0;
1376 }
1377
1378 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1379 /*
1380 * mpt_detect_929_bound_ports - Search for PCI bus/dev_function
1381 * which matches PCI bus/dev_function (+/-1) for newly discovered 929.
1382 * @ioc: Pointer to MPT adapter structure
1383 * @pdev: Pointer to (struct pci_dev) structure
1384 *
1385 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1386 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1387 */
1388 static void
1389 mpt_detect_929_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1390 {
1391 MPT_ADAPTER *ioc_srch = mpt_adapter_find_first();
1392 unsigned int match_lo, match_hi;
1393
1394 match_lo = pdev->devfn-1;
1395 match_hi = pdev->devfn+1;
1396 dprintk((KERN_INFO MYNAM ": %s: PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
1397 ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi));
1398
1399 while (ioc_srch != NULL) {
1400 struct pci_dev *_pcidev = ioc_srch->pcidev;
1401
1402 if ( (_pcidev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) &&
1403 (_pcidev->bus->number == pdev->bus->number) &&
1404 (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
1405 /* Paranoia checks */
1406 if (ioc->alt_ioc != NULL) {
1407 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1408 ioc->name, ioc->alt_ioc->name);
1409 break;
1410 } else if (ioc_srch->alt_ioc != NULL) {
1411 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
1412 ioc_srch->name, ioc_srch->alt_ioc->name);
1413 break;
1414 }
1415 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
1416 ioc->name, ioc_srch->name));
1417 ioc_srch->alt_ioc = ioc;
1418 ioc->alt_ioc = ioc_srch;
1419 ioc->sod_reset = ioc->alt_ioc->sod_reset;
1420 ioc->last_kickstart = ioc->alt_ioc->last_kickstart;
1421 break;
1422 }
1423 ioc_srch = mpt_adapter_find_next(ioc_srch);
1424 }
1425 }
1426
1427 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1428 /*
1429 * mpt_adapter_disable - Disable misbehaving MPT adapter.
1430 * @this: Pointer to MPT adapter structure
1431 * @free: Free up alloc'd reply, request, etc.
1432 */
1433 static void
1434 mpt_adapter_disable(MPT_ADAPTER *this, int freeup)
1435 {
1436 if (this != NULL) {
1437 int sz;
1438
1439 /* Disable the FW */
1440 if (SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET) != 0)
1441 (void) KickStart(this, 1);
1442
1443 /* Disable adapter interrupts! */
1444 CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
1445 this->active = 0;
1446 /* Clear any lingering interrupt */
1447 CHIPREG_WRITE32(&this->chip->IntStatus, 0);
1448
1449 if (freeup && this->reply_alloc != NULL) {
1450 sz = (this->reply_sz * this->reply_depth) + 128;
1451 pci_free_consistent(this->pcidev, sz,
1452 this->reply_alloc, this->reply_alloc_dma);
1453 this->reply_frames = NULL;
1454 this->reply_alloc = NULL;
1455 this->alloc_total -= sz;
1456 }
1457
1458 if (freeup && this->req_alloc != NULL) {
1459 sz = (this->req_sz * this->req_depth) + 128;
1460 /*
1461 * Rounding UP to nearest 4-kB boundary here...
1462 */
1463 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
1464 pci_free_consistent(this->pcidev, sz,
1465 this->req_alloc, this->req_alloc_dma);
1466 this->req_frames = NULL;
1467 this->req_alloc = NULL;
1468 this->alloc_total -= sz;
1469 }
1470
1471 if (freeup && this->sense_buf_pool != NULL) {
1472 sz = (this->req_depth * 256);
1473 pci_free_consistent(this->pcidev, sz,
1474 this->sense_buf_pool, this->sense_buf_pool_dma);
1475 this->sense_buf_pool = NULL;
1476 this->alloc_total -= sz;
1477 }
1478 }
1479 }
1480
1481 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1482 /*
1483 * mpt_adapter_dispose - Free all resources associated with a MPT
1484 * adapter.
1485 * @this: Pointer to MPT adapter structure
1486 *
1487 * This routine unregisters h/w resources and frees all alloc'd memory
1488 * associated with a MPT adapter structure.
1489 */
1490 static void
1491 mpt_adapter_dispose(MPT_ADAPTER *this)
1492 {
1493 if (this != NULL) {
1494 int sz_first, sz_last;
1495
1496 sz_first = this->alloc_total;
1497
1498 mpt_adapter_disable(this, 1);
1499
1500 if (this->pci_irq != -1) {
1501 free_irq(this->pci_irq, this);
1502 this->pci_irq = -1;
1503 }
1504
1505 if (this->memmap != NULL)
1506 iounmap((u8 *) this->memmap);
1507
1508 #if defined(CONFIG_MTRR) && 0
1509 if (this->mtrr_reg > 0) {
1510 mtrr_del(this->mtrr_reg, 0, 0);
1511 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name));
1512 }
1513 #endif
1514
1515 /* Zap the adapter lookup ptr! */
1516 mpt_adapters[this->id] = NULL;
1517
1518 sz_last = this->alloc_total;
1519 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
1520 this->name, sz_first-sz_last+(int)sizeof(*this), sz_first));
1521 kfree(this);
1522 }
1523 }
1524
1525 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1526 /*
1527 * MptDisplayIocCapabilities - Disply IOC's capacilities.
1528 * @ioc: Pointer to MPT adapter structure
1529 */
1530 static void
1531 MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
1532 {
1533 int i = 0;
1534
1535 printk(KERN_INFO "%s: ", ioc->name);
1536 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
1537 printk("%s: ", ioc->prod_name+3);
1538 printk("Capabilities={");
1539
1540 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
1541 printk("Initiator");
1542 i++;
1543 }
1544
1545 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
1546 printk("%sTarget", i ? "," : "");
1547 i++;
1548 }
1549
1550 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
1551 printk("%sLAN", i ? "," : "");
1552 i++;
1553 }
1554
1555 #if 0
1556 /*
1557 * This would probably evoke more questions than it's worth
1558 */
1559 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
1560 printk("%sLogBusAddr", i ? "," : "");
1561 i++;
1562 }
1563 #endif
1564
1565 printk("}\n");
1566 }
1567
1568 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1569 /*
1570 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
1571 * @ioc: Pointer to MPT_ADAPTER structure
1572 * @kick: Force hard KickStart of IOC
1573 *
1574 * Returns 0 for already-READY, 1 for hard reset success,
1575 * else negative for failure.
1576 */
1577 static int
1578 MakeIocReady(MPT_ADAPTER *ioc, int force)
1579 {
1580 u32 ioc_state;
1581 int statefault = 0;
1582 int cntdn;
1583 int hard_reset_done = 0;
1584 int r;
1585 int i;
1586
1587 /* Get current [raw] IOC state */
1588 ioc_state = GetIocState(ioc, 0);
1589 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
1590
1591 /*
1592 * Check to see if IOC got left/stuck in doorbell handshake
1593 * grip of death. If so, hard reset the IOC.
1594 */
1595 if (ioc_state & MPI_DOORBELL_ACTIVE) {
1596 statefault = 1;
1597 printk(KERN_WARNING MYNAM ": %s: Uh-oh, unexpected doorbell active!\n",
1598 ioc->name);
1599 }
1600
1601 /* Is it already READY? */
1602 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
1603 return 0;
1604
1605 /*
1606 * Check to see if IOC is in FAULT state.
1607 */
1608 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
1609 statefault = 2;
1610 printk(KERN_WARNING MYNAM ": %s: Uh-oh, IOC is in FAULT state!!!\n",
1611 ioc->name);
1612 printk(KERN_WARNING " FAULT code = %04xh\n",
1613 ioc_state & MPI_DOORBELL_DATA_MASK);
1614 }
1615
1616 /*
1617 * Hmmm... Did it get left operational?
1618 */
1619 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
1620 statefault = 3;
1621 dprintk((KERN_WARNING MYNAM ": %s: Hmmm... IOC operational unexpected\n",
1622 ioc->name));
1623 }
1624
1625 hard_reset_done = KickStart(ioc, statefault||force);
1626 if (hard_reset_done < 0)
1627 return -1;
1628
1629 /*
1630 * Loop here waiting for IOC to come READY.
1631 */
1632 i = 0;
1633 cntdn = HZ * 15;
1634 while ((ioc_state = GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
1635 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
1636 /*
1637 * BIOS or previous driver load left IOC in OP state.
1638 * Reset messaging FIFOs.
1639 */
1640 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET)) != 0) {
1641 printk(KERN_ERR MYNAM ": %s: ERROR - IOC msg unit reset failed!\n", ioc->name);
1642 return -2;
1643 }
1644 } else if (ioc_state == MPI_IOC_STATE_RESET) {
1645 /*
1646 * Something is wrong. Try to get IOC back
1647 * to a known state.
1648 */
1649 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET)) != 0) {
1650 printk(KERN_ERR MYNAM ": %s: ERROR - IO unit reset failed!\n", ioc->name);
1651 return -3;
1652 }
1653 }
1654
1655 i++; cntdn--;
1656 if (!cntdn) {
1657 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
1658 ioc->name, (i+5)/HZ);
1659 return -ETIME;
1660 }
1661
1662 current->state = TASK_INTERRUPTIBLE;
1663 schedule_timeout(1);
1664 }
1665
1666 if (statefault < 3) {
1667 printk(KERN_WARNING MYNAM ": %s: Whew! Recovered from %s\n",
1668 ioc->name,
1669 statefault==1 ? "stuck handshake" : "IOC FAULT");
1670 }
1671
1672 return hard_reset_done;
1673 }
1674
1675 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1676 /*
1677 * GetIocState - Get the current state of a MPT adapter.
1678 * @ioc: Pointer to MPT_ADAPTER structure
1679 * @cooked: Request raw or cooked IOC state
1680 *
1681 * Returns all IOC Doorbell register bits if cooked==0, else just the
1682 * Doorbell bits in MPI_IOC_STATE_MASK.
1683 */
1684 static u32
1685 GetIocState(MPT_ADAPTER *ioc, int cooked)
1686 {
1687 u32 s, sc;
1688
1689 /* Get! */
1690 s = CHIPREG_READ32(&ioc->chip->Doorbell);
1691 dprintk((KERN_INFO MYNAM ": %s: raw state = %08x\n", ioc->name, s));
1692 sc = s & MPI_IOC_STATE_MASK;
1693
1694 /* Save! */
1695 ioc->last_state = sc;
1696
1697 return cooked ? sc : s;
1698 }
1699
1700 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1701 /*
1702 * GetIocFacts - Send IOCFacts request to MPT adapter.
1703 * @ioc: Pointer to MPT_ADAPTER structure
1704 *
1705 * Returns 0 for success, non-zero for failure.
1706 */
1707 static int
1708 GetIocFacts(MPT_ADAPTER *ioc)
1709 {
1710 IOCFacts_t get_facts;
1711 IOCFactsReply_t *facts;
1712 int r;
1713 int req_sz;
1714 int reply_sz;
1715 u32 status;
1716
1717 /* IOC *must* NOT be in RESET state! */
1718 if (ioc->last_state == MPI_IOC_STATE_RESET) {
1719 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
1720 ioc->name,
1721 ioc->last_state );
1722 return -44;
1723 }
1724
1725 facts = &ioc->facts;
1726
1727 /* Destination (reply area)... */
1728 reply_sz = sizeof(*facts);
1729 memset(facts, 0, reply_sz);
1730
1731 /* Request area (get_facts on the stack right now!) */
1732 req_sz = sizeof(get_facts);
1733 memset(&get_facts, 0, req_sz);
1734
1735 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
1736 /* Assert: All other get_facts fields are zero! */
1737
1738 dprintk((KERN_INFO MYNAM ": %s: Sending get IocFacts request\n", ioc->name));
1739
1740 /* No non-zero fields in the get_facts request are greater than
1741 * 1 byte in size, so we can just fire it off as is.
1742 */
1743 r = HandShakeReqAndReply(ioc,
1744 req_sz, (u32*)&get_facts,
1745 reply_sz, (u16*)facts, 3);
1746 if (r != 0)
1747 return r;
1748
1749 /*
1750 * Now byte swap (GRRR) the necessary fields before any further
1751 * inspection of reply contents.
1752 *
1753 * But need to do some sanity checks on MsgLength (byte) field
1754 * to make sure we don't zero IOC's req_sz!
1755 */
1756 /* Did we get a valid reply? */
1757 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
1758 /*
1759 * If not been here, done that, save off first WhoInit value
1760 */
1761 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
1762 ioc->FirstWhoInit = facts->WhoInit;
1763
1764 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
1765 facts->MsgContext = le32_to_cpu(facts->MsgContext);
1766 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
1767 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
1768 status = facts->IOCStatus & MPI_IOCSTATUS_MASK;
1769 /* CHECKME! IOCStatus, IOCLogInfo */
1770
1771 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
1772 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
1773 facts->FWVersion = le16_to_cpu(facts->FWVersion);
1774 facts->ProductID = le16_to_cpu(facts->ProductID);
1775 facts->CurrentHostMfaHighAddr =
1776 le32_to_cpu(facts->CurrentHostMfaHighAddr);
1777 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
1778 facts->CurrentSenseBufferHighAddr =
1779 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
1780 facts->CurReplyFrameSize =
1781 le16_to_cpu(facts->CurReplyFrameSize);
1782
1783 /*
1784 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
1785 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
1786 * to 14 in MPI-1.01.0x.
1787 */
1788 if (facts->MsgLength >= sizeof(IOCFactsReply_t)/sizeof(u32) && facts->MsgVersion > 0x0100) {
1789 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
1790 facts->DataImageSize = le32_to_cpu(facts->DataImageSize);
1791 }
1792
1793 if (facts->RequestFrameSize) {
1794 /*
1795 * Set values for this IOC's REQUEST queue size & depth...
1796 */
1797 ioc->req_sz = MIN(MPT_REQ_SIZE, facts->RequestFrameSize * 4);
1798
1799 /*
1800 * Set values for this IOC's REPLY queue size & depth...
1801 *
1802 * BUG? FIX? 20000516 -nromer & sralston
1803 * GRRR... The following did not translate well from MPI v0.09:
1804 * ioc->reply_sz = MIN(MPT_REPLY_SIZE, facts->ReplySize * 4);
1805 * to 0.10:
1806 * ioc->reply_sz = MIN(MPT_REPLY_SIZE, facts->BlockSize * 4);
1807 * Was trying to minimally optimize to smallest possible reply size
1808 * (and greatly reduce kmalloc size). But LAN may need larger reply?
1809 *
1810 * So for now, just set reply size to request size. FIXME?
1811 */
1812 ioc->reply_sz = ioc->req_sz;
1813 } else {
1814 /* Something is wrong! */
1815 printk(KERN_ERR MYNAM ": %s: ERROR - IOC reported invalid 0 request size!\n",
1816 ioc->name);
1817 ioc->req_sz = MPT_REQ_SIZE;
1818 ioc->reply_sz = MPT_REPLY_SIZE;
1819 return -55;
1820 }
1821 ioc->req_depth = MIN(MPT_REQ_DEPTH, facts->GlobalCredits);
1822 ioc->reply_depth = MIN(MPT_REPLY_DEPTH, facts->ReplyQueueDepth);
1823
1824 dprintk((KERN_INFO MYNAM ": %s: reply_sz=%3d, reply_depth=%4d\n",
1825 ioc->name, ioc->reply_sz, ioc->reply_depth));
1826 dprintk((KERN_INFO MYNAM ": %s: req_sz =%3d, req_depth =%4d\n",
1827 ioc->name, ioc->req_sz, ioc->req_depth));
1828
1829 /* Get port facts! */
1830 if ( (r = GetPortFacts(ioc, 0)) != 0 )
1831 return r;
1832 } else {
1833 printk(KERN_ERR MYNAM ": %s: ERROR - Invalid IOC facts reply!\n",
1834 ioc->name);
1835 return -66;
1836 }
1837
1838 return 0;
1839 }
1840
1841 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1842 /*
1843 * GetPortFacts - Send PortFacts request to MPT adapter.
1844 * @ioc: Pointer to MPT_ADAPTER structure
1845 * @portnum: Port number
1846 *
1847 * Returns 0 for success, non-zero for failure.
1848 */
1849 static int
1850 GetPortFacts(MPT_ADAPTER *ioc, int portnum)
1851 {
1852 PortFacts_t get_pfacts;
1853 PortFactsReply_t *pfacts;
1854 int i;
1855 int req_sz;
1856 int reply_sz;
1857
1858 /* IOC *must* NOT be in RESET state! */
1859 if (ioc->last_state == MPI_IOC_STATE_RESET) {
1860 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
1861 ioc->name,
1862 ioc->last_state );
1863 return -4;
1864 }
1865
1866 pfacts = &ioc->pfacts[portnum];
1867
1868 /* Destination (reply area)... */
1869 reply_sz = sizeof(*pfacts);
1870 memset(pfacts, 0, reply_sz);
1871
1872 /* Request area (get_pfacts on the stack right now!) */
1873 req_sz = sizeof(get_pfacts);
1874 memset(&get_pfacts, 0, req_sz);
1875
1876 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
1877 get_pfacts.PortNumber = portnum;
1878 /* Assert: All other get_pfacts fields are zero! */
1879
1880 dprintk((KERN_INFO MYNAM ": %s: Sending get PortFacts(%d) request\n",
1881 ioc->name, portnum));
1882
1883 /* No non-zero fields in the get_pfacts request are greater than
1884 * 1 byte in size, so we can just fire it off as is.
1885 */
1886 i = HandShakeReqAndReply(ioc, req_sz, (u32*)&get_pfacts,
1887 reply_sz, (u16*)pfacts, 3);
1888 if (i != 0)
1889 return i;
1890
1891 /* Did we get a valid reply? */
1892
1893 /* Now byte swap the necessary fields in the response. */
1894 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
1895 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
1896 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
1897 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
1898 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
1899 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
1900 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
1901 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
1902 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
1903
1904 return 0;
1905 }
1906
1907 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1908 /*
1909 * SendIocInit - Send IOCInit request to MPT adapter.
1910 * @ioc: Pointer to MPT_ADAPTER structure
1911 *
1912 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
1913 *
1914 * Returns 0 for success, non-zero for failure.
1915 */
1916 static int
1917 SendIocInit(MPT_ADAPTER *ioc)
1918 {
1919 IOCInit_t ioc_init;
1920 MPIDefaultReply_t init_reply;
1921 u32 state;
1922 int r;
1923 int count;
1924 int cntdn;
1925
1926 memset(&ioc_init, 0, sizeof(ioc_init));
1927 memset(&init_reply, 0, sizeof(init_reply));
1928
1929 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
1930 /* ioc_init.ChainOffset = 0; */
1931 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
1932 /* ioc_init.Flags = 0; */
1933
1934 /*ioc_init.MaxDevices = 16;*/
1935 ioc_init.MaxDevices = 255;
1936 /* ioc_init.MaxBuses = 16; */
1937 ioc_init.MaxBuses = 1;
1938
1939 /* ioc_init.MsgFlags = 0; */
1940 /* ioc_init.MsgContext = cpu_to_le32(0x00000000); */
1941 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
1942 ioc_init.HostMfaHighAddr = cpu_to_le32(0); /* Say we 32-bit! for now */
1943
1944 dprintk((KERN_INFO MYNAM ": %s: Sending IOCInit (req @ %p)\n", ioc->name, &ioc_init));
1945
1946 r = HandShakeReqAndReply(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
1947 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10);
1948 if (r != 0)
1949 return r;
1950
1951 /* No need to byte swap the multibyte fields in the reply
1952 * since we don't even look at it's contents.
1953 */
1954
1955 if ((r = SendPortEnable(ioc, 0)) != 0)
1956 return r;
1957
1958 /* YIKES! SUPER IMPORTANT!!!
1959 * Poll IocState until _OPERATIONAL while IOC is doing
1960 * LoopInit and TargetDiscovery!
1961 */
1962 count = 0;
1963 cntdn = HZ * 60; /* chg'd from 30 to 60 seconds */
1964 state = GetIocState(ioc, 1);
1965 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
1966 current->state = TASK_INTERRUPTIBLE;
1967 schedule_timeout(1);
1968
1969 if (!cntdn) {
1970 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_OP state timeout(%d)!\n",
1971 ioc->name, (count+5)/HZ);
1972 return -9;
1973 }
1974
1975 state = GetIocState(ioc, 1);
1976 count++;
1977 }
1978 dhsprintk((KERN_INFO MYNAM ": %s: INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
1979 ioc->name, count));
1980
1981 return r;
1982 }
1983
1984 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1985 /*
1986 * SendPortEnable - Send PortEnable request to MPT adapter port.
1987 * @ioc: Pointer to MPT_ADAPTER structure
1988 * @portnum: Port number to enable
1989 *
1990 * Send PortEnable to bring IOC to OPERATIONAL state.
1991 *
1992 * Returns 0 for success, non-zero for failure.
1993 */
1994 static int
1995 SendPortEnable(MPT_ADAPTER *ioc, int portnum)
1996 {
1997 PortEnable_t port_enable;
1998 MPIDefaultReply_t reply_buf;
1999 int i;
2000 int req_sz;
2001 int reply_sz;
2002
2003 /* Destination... */
2004 reply_sz = sizeof(MPIDefaultReply_t);
2005 memset(&reply_buf, 0, reply_sz);
2006
2007 req_sz = sizeof(PortEnable_t);
2008 memset(&port_enable, 0, req_sz);
2009
2010 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2011 port_enable.PortNumber = portnum;
2012 /* port_enable.ChainOffset = 0; */
2013 /* port_enable.MsgFlags = 0; */
2014 /* port_enable.MsgContext = 0; */
2015
2016 dprintk((KERN_INFO MYNAM ": %s: Sending Port(%d)Enable (req @ %p)\n",
2017 ioc->name, portnum, &port_enable));
2018
2019 i = HandShakeReqAndReply(ioc, req_sz, (u32*)&port_enable,
2020 reply_sz, (u16*)&reply_buf, 65);
2021 if (i != 0)
2022 return i;
2023
2024 /* We do not even look at the reply, so we need not
2025 * swap the multi-byte fields.
2026 */
2027
2028 return 0;
2029 }
2030
2031 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2032 /*
2033 * KickStart - Perform hard reset of MPT adapter.
2034 * @ioc: Pointer to MPT_ADAPTER structure
2035 * @force: Force hard reset
2036 *
2037 * This routine places MPT adapter in diagnostic mode via the
2038 * WriteSequence register, and then performs a hard reset of adapter
2039 * via the Diagnostic register.
2040 *
2041 * Returns 0 for soft reset success, 1 for hard reset success,
2042 * else a negative value for failure.
2043 */
2044 static int
2045 KickStart(MPT_ADAPTER *ioc, int force)
2046 {
2047 int hard_reset_done = 0;
2048 u32 ioc_state;
2049 int cnt = 0;
2050
2051 dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
2052
2053 hard_reset_done = mpt_fc9x9_reset(ioc, force);
2054 #if 0
2055 if (ioc->chip_type == FC909 || ioc->chip-type == FC919) {
2056 hard_reset_done = mpt_fc9x9_reset(ioc, force);
2057 } else if (ioc->chip_type == FC929) {
2058 unsigned long delta;
2059
2060 delta = jiffies - ioc->last_kickstart;
2061 dprintk((KERN_INFO MYNAM ": %s: 929 KickStart, last=%ld, delta = %ld\n",
2062 ioc->name, ioc->last_kickstart, delta));
2063 if ((ioc->sod_reset == 0) || (delta >= 10*HZ))
2064 hard_reset_done = mpt_fc9x9_reset(ioc, ignore);
2065 else {
2066 dprintk((KERN_INFO MYNAM ": %s: Skipping KickStart (delta=%ld)!\n",
2067 ioc->name, delta));
2068 return 0;
2069 }
2070 /* TODO! Add C1030!
2071 } else if (ioc->chip_type == C1030) {
2072 */
2073 } else {
2074 printk(KERN_ERR MYNAM ": %s: ERROR - Bad chip_type (0x%x)\n",
2075 ioc->name, ioc->chip_type);
2076 return -5;
2077 }
2078 #endif
2079
2080 if (hard_reset_done < 0)
2081 return hard_reset_done;
2082
2083 dprintk((KERN_INFO MYNAM ": %s: Diagnostic reset successful\n",
2084 ioc->name));
2085
2086 for (cnt=0; cnt<HZ*20; cnt++) {
2087 if ((ioc_state = GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) {
2088 dprintk((KERN_INFO MYNAM ": %s: KickStart successful! (cnt=%d)\n",
2089 ioc->name, cnt));
2090 return hard_reset_done;
2091 }
2092 /* udelay(10000) ? */
2093 current->state = TASK_INTERRUPTIBLE;
2094 schedule_timeout(1);
2095 }
2096
2097 printk(KERN_ERR MYNAM ": %s: ERROR - Failed to come READY after reset!\n",
2098 ioc->name);
2099 return -1;
2100 }
2101
2102 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2103 /*
2104 * mpt_fc9x9_reset - Perform hard reset of FC9x9 adapter.
2105 * @ioc: Pointer to MPT_ADAPTER structure
2106 *
2107 * This routine places FC9x9 adapter in diagnostic mode via the
2108 * WriteSequence register, and then performs a hard reset of adapter
2109 * via the Diagnostic register.
2110 *
2111 * Returns 0 for success, non-zero for failure.
2112 */
2113 static int
2114 mpt_fc9x9_reset(MPT_ADAPTER *ioc, int ignore)
2115 {
2116 u32 diag0val;
2117 int hard_reset_done = 0;
2118
2119 /* Use "Diagnostic reset" method! (only thing available!) */
2120
2121 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2122 #ifdef MPT_DEBUG
2123 {
2124 u32 diag1val = 0;
2125 if (ioc->alt_ioc)
2126 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
2127 dprintk((KERN_INFO MYNAM ": %s: DBG1: diag0=%08x, diag1=%08x\n",
2128 ioc->name, diag0val, diag1val));
2129 }
2130 #endif
2131 if (diag0val & MPI_DIAG_DRWE) {
2132 dprintk((KERN_INFO MYNAM ": %s: DiagWriteEn bit already set\n",
2133 ioc->name));
2134 } else {
2135 /* Write magic sequence to WriteSequence register */
2136 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2137 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2138 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2139 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2140 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2141 dprintk((KERN_INFO MYNAM ": %s: Wrote magic DiagWriteEn sequence [spot#1]\n",
2142 ioc->name));
2143 }
2144
2145 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2146 #ifdef MPT_DEBUG
2147 {
2148 u32 diag1val = 0;
2149 if (ioc->alt_ioc)
2150 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
2151 dprintk((KERN_INFO MYNAM ": %s: DbG2: diag0=%08x, diag1=%08x\n",
2152 ioc->name, diag0val, diag1val));
2153 }
2154 #endif
2155 if (!ignore && (diag0val & MPI_DIAG_RESET_HISTORY)) {
2156 dprintk((KERN_INFO MYNAM ": %s: Skipping due to ResetHistory bit set!\n",
2157 ioc->name));
2158 } else {
2159 /*
2160 * Now hit the reset bit in the Diagnostic register
2161 * (THE BIG HAMMER!)
2162 */
2163 CHIPREG_WRITE32(&ioc->chip->Diagnostic, MPI_DIAG_RESET_ADAPTER);
2164 hard_reset_done = 1;
2165 dprintk((KERN_INFO MYNAM ": %s: Diagnostic reset performed\n",
2166 ioc->name));
2167
2168 /* want udelay(100) */
2169 current->state = TASK_INTERRUPTIBLE;
2170 schedule_timeout(1);
2171
2172 /* Write magic sequence to WriteSequence register */
2173 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2174 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2175 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2176 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2177 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2178 dprintk((KERN_INFO MYNAM ": %s: Wrote magic DiagWriteEn sequence [spot#2]\n",
2179 ioc->name));
2180 }
2181
2182 /* Clear RESET_HISTORY bit! */
2183 CHIPREG_WRITE32(&ioc->chip->Diagnostic, 0x0);
2184
2185 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2186 #ifdef MPT_DEBUG
2187 {
2188 u32 diag1val = 0;
2189 if (ioc->alt_ioc)
2190 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
2191 dprintk((KERN_INFO MYNAM ": %s: DbG3: diag0=%08x, diag1=%08x\n",
2192 ioc->name, diag0val, diag1val));
2193 }
2194 #endif
2195 if (diag0val & MPI_DIAG_RESET_HISTORY) {
2196 printk(KERN_WARNING MYNAM ": %s: WARNING - ResetHistory bit failed to clear!\n",
2197 ioc->name);
2198 }
2199
2200 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2201 #ifdef MPT_DEBUG
2202 {
2203 u32 diag1val = 0;
2204 if (ioc->alt_ioc)
2205 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
2206 dprintk((KERN_INFO MYNAM ": %s: DbG4: diag0=%08x, diag1=%08x\n",
2207 ioc->name, diag0val, diag1val));
2208 }
2209 #endif
2210 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
2211 printk(KERN_ERR MYNAM ": %s: ERROR - Diagnostic reset FAILED! (%02xh)\n",
2212 ioc->name, diag0val);
2213 return -3;
2214 }
2215
2216 /*
2217 * Reset flag that says we've enabled event notification
2218 */
2219 ioc->facts.EventState = 0;
2220
2221 /* NEW! 20010220 -sralston
2222 * Try to avoid redundant resets of the 929.
2223 */
2224 ioc->sod_reset++;
2225 ioc->last_kickstart = jiffies;
2226 if (ioc->alt_ioc) {
2227 ioc->alt_ioc->sod_reset = ioc->sod_reset;
2228 ioc->alt_ioc->last_kickstart = ioc->last_kickstart;
2229 }
2230
2231 return hard_reset_done;
2232 }
2233
2234 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2235 /*
2236 * SendIocReset - Send IOCReset request to MPT adapter.
2237 * @ioc: Pointer to MPT_ADAPTER structure
2238 * @reset_type: reset type, expected values are
2239 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
2240 *
2241 * Send IOCReset request to the MPT adapter.
2242 *
2243 * Returns 0 for success, non-zero for failure.
2244 */
2245 static int
2246 SendIocReset(MPT_ADAPTER *ioc, u8 reset_type)
2247 {
2248 int r;
2249
2250 dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
2251 ioc->name, reset_type));
2252 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
2253 if ((r = WaitForDoorbellAck(ioc, 2)) < 0)
2254 return r;
2255
2256 /* TODO!
2257 * Cleanup all event stuff for this IOC; re-issue EventNotification
2258 * request if needed.
2259 */
2260 if (ioc->facts.Function)
2261 ioc->facts.EventState = 0;
2262
2263 return 0;
2264 }
2265
2266 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2267 /*
2268 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
2269 * @ioc: Pointer to MPT_ADAPTER structure
2270 *
2271 * This routine allocates memory for the MPT reply and request frame
2272 * pools, and primes the IOC reply FIFO with reply frames.
2273 *
2274 * Returns 0 for success, non-zero for failure.
2275 */
2276 static int
2277 PrimeIocFifos(MPT_ADAPTER *ioc)
2278 {
2279 MPT_FRAME_HDR *mf;
2280 unsigned long b;
2281 dma_addr_t aligned_mem_dma;
2282 u8 *mem, *aligned_mem;
2283 int i, sz;
2284
2285 /* Prime reply FIFO... */
2286
2287 if (ioc->reply_frames == NULL) {
2288 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
2289 mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->reply_alloc_dma);
2290 if (mem == NULL)
2291 goto out_fail;
2292
2293 memset(mem, 0, sz);
2294 ioc->alloc_total += sz;
2295 ioc->reply_alloc = mem;
2296 dprintk((KERN_INFO MYNAM ": %s.reply_alloc @ %p[%08x], sz=%d bytes\n",
2297 ioc->name, mem, ioc->reply_alloc_dma, sz));
2298
2299 b = (unsigned long) mem;
2300 b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
2301 aligned_mem = (u8 *) b;
2302 ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem;
2303 ioc->reply_frames_dma =
2304 (ioc->reply_alloc_dma + (aligned_mem - mem));
2305 aligned_mem_dma = ioc->reply_frames_dma;
2306 dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%08x]\n",
2307 ioc->name, aligned_mem, aligned_mem_dma));
2308
2309 for (i = 0; i < ioc->reply_depth; i++) {
2310 /* Write each address to the IOC! */
2311 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma);
2312 aligned_mem_dma += ioc->reply_sz;
2313 }
2314 }
2315
2316
2317 /* Request FIFO - WE manage this! */
2318
2319 if (ioc->req_frames == NULL) {
2320 sz = (ioc->req_sz * ioc->req_depth) + 128;
2321 /*
2322 * Rounding UP to nearest 4-kB boundary here...
2323 */
2324 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
2325
2326 mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->req_alloc_dma);
2327 if (mem == NULL)
2328 goto out_fail;
2329
2330 memset(mem, 0, sz);
2331 ioc->alloc_total += sz;
2332 ioc->req_alloc = mem;
2333 dprintk((KERN_INFO MYNAM ": %s.req_alloc @ %p[%08x], sz=%d bytes\n",
2334 ioc->name, mem, ioc->req_alloc_dma, sz));
2335
2336 b = (unsigned long) mem;
2337 b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
2338 aligned_mem = (u8 *) b;
2339 ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem;
2340 ioc->req_frames_dma =
2341 (ioc->req_alloc_dma + (aligned_mem - mem));
2342 aligned_mem_dma = ioc->req_frames_dma;
2343
2344 dprintk((KERN_INFO MYNAM ": %s.req_frames @ %p[%08x]\n",
2345 ioc->name, aligned_mem, aligned_mem_dma));
2346
2347 for (i = 0; i < ioc->req_depth; i++) {
2348 mf = (MPT_FRAME_HDR *) aligned_mem;
2349
2350 /* Queue REQUESTs *internally*! */
2351 Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
2352 aligned_mem += ioc->req_sz;
2353 }
2354
2355 #if defined(CONFIG_MTRR) && 0
2356 /*
2357 * Enable Write Combining MTRR for IOC's memory region.
2358 * (at least as much as we can; "size and base must be
2359 * multiples of 4 kiB"
2360 */
2361 ioc->mtrr_reg = mtrr_add(ioc->req_alloc_dma,
2362 sz,
2363 MTRR_TYPE_WRCOMB, 1);
2364 dprintk((KERN_INFO MYNAM ": %s: MTRR region registered (base:size=%08x:%x)\n",
2365 ioc->name, ioc->req_alloc_dma,
2366 sz ));
2367 #endif
2368
2369 }
2370
2371 if (ioc->sense_buf_pool == NULL) {
2372 sz = (ioc->req_depth * 256);
2373 ioc->sense_buf_pool =
2374 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
2375 if (ioc->sense_buf_pool == NULL)
2376 goto out_fail;
2377
2378 ioc->alloc_total += sz;
2379 }
2380
2381 return 0;
2382
2383 out_fail:
2384 if (ioc->reply_alloc != NULL) {
2385 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
2386 pci_free_consistent(ioc->pcidev,
2387 sz,
2388 ioc->reply_alloc, ioc->reply_alloc_dma);
2389 ioc->reply_frames = NULL;
2390 ioc->reply_alloc = NULL;
2391 ioc->alloc_total -= sz;
2392 }
2393 if (ioc->req_alloc != NULL) {
2394 sz = (ioc->req_sz * ioc->req_depth) + 128;
2395 /*
2396 * Rounding UP to nearest 4-kB boundary here...
2397 */
2398 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
2399 pci_free_consistent(ioc->pcidev,
2400 sz,
2401 ioc->req_alloc, ioc->req_alloc_dma);
2402 #if defined(CONFIG_MTRR) && 0
2403 if (ioc->mtrr_reg > 0) {
2404 mtrr_del(ioc->mtrr_reg, 0, 0);
2405 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n",
2406 ioc->name));
2407 }
2408 #endif
2409 ioc->req_frames = NULL;
2410 ioc->req_alloc = NULL;
2411 ioc->alloc_total -= sz;
2412 }
2413 if (ioc->sense_buf_pool != NULL) {
2414 sz = (ioc->req_depth * 256);
2415 pci_free_consistent(ioc->pcidev,
2416 sz,
2417 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2418 ioc->sense_buf_pool = NULL;
2419 }
2420 return -1;
2421 }
2422
2423 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2424 /*
2425 * HandShakeReqAndReply - Send MPT request to and receive reply from
2426 * IOC via doorbell handshake method.
2427 * @ioc: Pointer to MPT_ADAPTER structure
2428 * @reqBytes: Size of the request in bytes
2429 * @req: Pointer to MPT request frame
2430 * @replyBytes: Expected size of the reply in bytes
2431 * @u16reply: Pointer to area where reply should be written
2432 * @maxwait: Max wait time for a reply (in seconds)
2433 *
2434 * NOTES: It is the callers responsibility to byte-swap fields in the
2435 * request which are greater than 1 byte in size. It is also the
2436 * callers responsibility to byte-swap response fields which are
2437 * greater than 1 byte in size.
2438 *
2439 * Returns 0 for success, non-zero for failure.
2440 */
2441 static int
2442 HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait)
2443 {
2444 MPIDefaultReply_t *mptReply;
2445 int failcnt = 0;
2446 int t;
2447
2448 /*
2449 * Get ready to cache a handshake reply
2450 */
2451 ioc->hs_reply_idx = 0;
2452 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
2453 mptReply->MsgLength = 0;
2454
2455 /*
2456 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
2457 * then tell IOC that we want to handshake a request of N words.
2458 * (WRITE u32val to Doorbell reg).
2459 */
2460 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2461 CHIPREG_WRITE32(&ioc->chip->Doorbell,
2462 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
2463 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
2464
2465 /*
2466 * Wait for IOC's doorbell handshake int
2467 */
2468 if ((t = WaitForDoorbellInt(ioc, 2)) < 0)
2469 failcnt++;
2470
2471 dhsprintk((KERN_INFO MYNAM ": %s: HandShake request start, WaitCnt=%d%s\n",
2472 ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
2473
2474 /*
2475 * Clear doorbell int (WRITE 0 to IntStatus reg),
2476 * then wait for IOC to ACKnowledge that it's ready for
2477 * our handshake request.
2478 */
2479 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2480 if (!failcnt && (t = WaitForDoorbellAck(ioc, 2)) < 0)
2481 failcnt++;
2482
2483 if (!failcnt) {
2484 int i;
2485 u8 *req_as_bytes = (u8 *) req;
2486
2487 /*
2488 * Stuff request words via doorbell handshake,
2489 * with ACK from IOC for each.
2490 */
2491 for (i = 0; !failcnt && i < reqBytes/4; i++) {
2492 u32 word = ((req_as_bytes[(i*4) + 0] << 0) |
2493 (req_as_bytes[(i*4) + 1] << 8) |
2494 (req_as_bytes[(i*4) + 2] << 16) |
2495 (req_as_bytes[(i*4) + 3] << 24));
2496
2497 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
2498 if ((t = WaitForDoorbellAck(ioc, 2)) < 0)
2499 failcnt++;
2500 }
2501
2502 dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
2503 DBG_DUMP_REQUEST_FRAME_HDR(req)
2504
2505 dhsprintk((KERN_INFO MYNAM ": %s: HandShake request post done, WaitCnt=%d%s\n",
2506 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
2507
2508 /*
2509 * Wait for completion of doorbell handshake reply from the IOC
2510 */
2511 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait)) < 0)
2512 failcnt++;
2513
2514 /*
2515 * Copy out the cached reply...
2516 */
2517 for(i=0; i < MIN(replyBytes/2,mptReply->MsgLength*2); i++)
2518 u16reply[i] = ioc->hs_reply[i];
2519 } else {
2520 return -99;
2521 }
2522
2523 return -failcnt;
2524 }
2525
2526 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2527 /*
2528 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
2529 * in it's IntStatus register.
2530 * @ioc: Pointer to MPT_ADAPTER structure
2531 * @howlong: How long to wait (in seconds)
2532 *
2533 * This routine waits (up to ~2 seconds max) for IOC doorbell
2534 * handshake ACKnowledge.
2535 *
2536 * Returns a negative value on failure, else wait loop count.
2537 */
2538 static int
2539 WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong)
2540 {
2541 int cntdn = HZ * howlong;
2542 int count = 0;
2543 u32 intstat;
2544
2545 while (--cntdn) {
2546 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
2547 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
2548 break;
2549 current->state = TASK_INTERRUPTIBLE;
2550 schedule_timeout(1);
2551 count++;
2552 }
2553
2554 if (cntdn) {
2555 dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell ACK (cnt=%d)\n",
2556 ioc->name, count));
2557 return count;
2558 }
2559
2560 printk(KERN_ERR MYNAM ": %s: ERROR - Doorbell ACK timeout(%d)!\n",
2561 ioc->name, (count+5)/HZ);
2562 return -1;
2563 }
2564
2565 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2566 /*
2567 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
2568 * in it's IntStatus register.
2569 * @ioc: Pointer to MPT_ADAPTER structure
2570 * @howlong: How long to wait (in seconds)
2571 *
2572 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
2573 *
2574 * Returns a negative value on failure, else wait loop count.
2575 */
2576 static int
2577 WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong)
2578 {
2579 int cntdn = HZ * howlong;
2580 int count = 0;
2581 u32 intstat;
2582
2583 while (--cntdn) {
2584 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
2585 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
2586 break;
2587 current->state = TASK_INTERRUPTIBLE;
2588 schedule_timeout(1);
2589 count++;
2590 }
2591
2592 if (cntdn) {
2593 dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell INT (cnt=%d)\n",
2594 ioc->name, count));
2595 return count;
2596 }
2597
2598 printk(KERN_ERR MYNAM ": %s: ERROR - Doorbell INT timeout(%d)!\n",
2599 ioc->name, (count+5)/HZ);
2600 return -1;
2601 }
2602
2603 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2604 /*
2605 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
2606 * @ioc: Pointer to MPT_ADAPTER structure
2607 * @howlong: How long to wait (in seconds)
2608 *
2609 * This routine polls the IOC for a handshake reply, 16 bits at a time.
2610 * Reply is cached to IOC private area large enough to hold a maximum
2611 * of 128 bytes of reply data.
2612 *
2613 * Returns a negative value on failure, else size of reply in WORDS.
2614 */
2615 static int
2616 WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong)
2617 {
2618 int u16cnt = 0;
2619 int failcnt = 0;
2620 int t;
2621 u16 *hs_reply = ioc->hs_reply;
2622 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
2623 u16 hword;
2624
2625 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
2626
2627 /*
2628 * Get first two u16's so we can look at IOC's intended reply MsgLength
2629 */
2630 u16cnt=0;
2631 if ((t = WaitForDoorbellInt(ioc, howlong)) < 0) {
2632 failcnt++;
2633 } else {
2634 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
2635 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2636 if ((t = WaitForDoorbellInt(ioc, 2)) < 0)
2637 failcnt++;
2638 else {
2639 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
2640 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2641 }
2642 }
2643
2644 dhsprintk((KERN_INFO MYNAM ": %s: First handshake reply word=%08x%s\n",
2645 ioc->name, le32_to_cpu(*(u32 *)hs_reply),
2646 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
2647
2648 /*
2649 * If no error (and IOC said MsgLength is > 0), piece together
2650 * reply 16 bits at a time.
2651 */
2652 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
2653 if ((t = WaitForDoorbellInt(ioc, 2)) < 0)
2654 failcnt++;
2655 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
2656 /* don't overflow our IOC hs_reply[] buffer! */
2657 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
2658 hs_reply[u16cnt] = hword;
2659 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2660 }
2661
2662 if (!failcnt && (t = WaitForDoorbellInt(ioc, 2)) < 0)
2663 failcnt++;
2664 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2665
2666 if (failcnt) {
2667 printk(KERN_ERR MYNAM ": %s: ERROR - Handshake reply failure!\n",
2668 ioc->name);
2669 return -failcnt;
2670 }
2671 #if 0
2672 else if (u16cnt != (2 * mptReply->MsgLength)) {
2673 return -101;
2674 }
2675 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
2676 return -102;
2677 }
2678 #endif
2679
2680 dmfprintk((KERN_INFO MYNAM ": %s: Got Handshake reply:\n", ioc->name));
2681 DBG_DUMP_REPLY_FRAME(mptReply)
2682
2683 dhsprintk((KERN_INFO MYNAM ": %s: WaitForDoorbell REPLY (sz=%d)\n",
2684 ioc->name, u16cnt/2));
2685 return u16cnt/2;
2686 }
2687
2688 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2689 /*
2690 * GetLanConfigPages - Fetch LANConfig pages.
2691 * @ioc: Pointer to MPT_ADAPTER structure
2692 *
2693 * Returns 0 for success, non-zero for failure.
2694 */
2695 static int
2696 GetLanConfigPages(MPT_ADAPTER *ioc)
2697 {
2698 Config_t config_req;
2699 ConfigReply_t config_reply;
2700 LANPage0_t *page0;
2701 dma_addr_t page0_dma;
2702 LANPage1_t *page1;
2703 dma_addr_t page1_dma;
2704 int i;
2705 int req_sz;
2706 int reply_sz;
2707 int data_sz;
2708
2709 /* LANPage0 */
2710 /* Immediate destination (reply area)... */
2711 reply_sz = sizeof(config_reply);
2712 memset(&config_reply, 0, reply_sz);
2713
2714 /* Ultimate destination... */
2715 page0 = &ioc->lan_cnfg_page0;
2716 data_sz = sizeof(*page0);
2717 memset(page0, 0, data_sz);
2718
2719 /* Request area (config_req on the stack right now!) */
2720 req_sz = sizeof(config_req);
2721 memset(&config_req, 0, req_sz);
2722 config_req.Function = MPI_FUNCTION_CONFIG;
2723 config_req.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2724 /* config_req.Header.PageVersion = 0; */
2725 /* config_req.Header.PageLength = 0; */
2726 config_req.Header.PageNumber = 0;
2727 config_req.Header.PageType = MPI_CONFIG_PAGETYPE_LAN;
2728 /* config_req.PageAddress = 0; */
2729 config_req.PageBufferSGE.u.Simple.FlagsLength = cpu_to_le32(
2730 ((MPI_SGE_FLAGS_LAST_ELEMENT |
2731 MPI_SGE_FLAGS_END_OF_BUFFER |
2732 MPI_SGE_FLAGS_END_OF_LIST |
2733 MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2734 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2735 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
2736 MPI_SGE_FLAGS_32_BIT_CONTEXT) << MPI_SGE_FLAGS_SHIFT) |
2737 (u32)data_sz
2738 );
2739 page0_dma = pci_map_single(ioc->pcidev, page0, data_sz, PCI_DMA_FROMDEVICE);
2740 config_req.PageBufferSGE.u.Simple.u.Address32 = cpu_to_le32(page0_dma);
2741
2742 dprintk((KERN_INFO MYNAM ": %s: Sending Config request LAN_PAGE_0\n",
2743 ioc->name));
2744
2745 i = HandShakeReqAndReply(ioc, req_sz, (u32*)&config_req,
2746 reply_sz, (u16*)&config_reply, 3);
2747 pci_unmap_single(ioc->pcidev, page0_dma, data_sz, PCI_DMA_FROMDEVICE);
2748 if (i != 0)
2749 return i;
2750
2751 /* Now byte swap the necessary LANPage0 fields */
2752
2753 /* LANPage1 */
2754 /* Immediate destination (reply area)... */
2755 reply_sz = sizeof(config_reply);
2756 memset(&config_reply, 0, reply_sz);
2757
2758 /* Ultimate destination... */
2759 page1 = &ioc->lan_cnfg_page1;
2760 data_sz = sizeof(*page1);
2761 memset(page1, 0, data_sz);
2762
2763 /* Request area (config_req on the stack right now!) */
2764 req_sz = sizeof(config_req);
2765 memset(&config_req, 0, req_sz);
2766 config_req.Function = MPI_FUNCTION_CONFIG;
2767 config_req.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2768 /* config_req.Header.PageVersion = 0; */
2769 /* config_req.Header.PageLength = 0; */
2770 config_req.Header.PageNumber = 1;
2771 config_req.Header.PageType = MPI_CONFIG_PAGETYPE_LAN;
2772 /* config_req.PageAddress = 0; */
2773 config_req.PageBufferSGE.u.Simple.FlagsLength = cpu_to_le32(
2774 ((MPI_SGE_FLAGS_LAST_ELEMENT |
2775 MPI_SGE_FLAGS_END_OF_BUFFER |
2776 MPI_SGE_FLAGS_END_OF_LIST |
2777 MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2778 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2779 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
2780 MPI_SGE_FLAGS_32_BIT_CONTEXT) << MPI_SGE_FLAGS_SHIFT) |
2781 (u32)data_sz
2782 );
2783 page1_dma = pci_map_single(ioc->pcidev, page1, data_sz, PCI_DMA_FROMDEVICE);
2784 config_req.PageBufferSGE.u.Simple.u.Address32 = cpu_to_le32(page1_dma);
2785
2786 dprintk((KERN_INFO MYNAM ": %s: Sending Config request LAN_PAGE_1\n",
2787 ioc->name));
2788
2789 i = HandShakeReqAndReply(ioc, req_sz, (u32*)&config_req,
2790 reply_sz, (u16*)&config_reply, 3);
2791 pci_unmap_single(ioc->pcidev, page1_dma, data_sz, PCI_DMA_FROMDEVICE);
2792 if (i != 0)
2793 return i;
2794
2795 /* Now byte swap the necessary LANPage1 fields */
2796
2797 return 0;
2798 }
2799
2800 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2801 /**
2802 * SendEventNotification - Send EventNotification (on or off) request
2803 * to MPT adapter.
2804 * @ioc: Pointer to MPT_ADAPTER structure
2805 * @EvSwitch: Event switch flags
2806 */
2807 static int
2808 SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
2809 {
2810 EventNotification_t *evnp;
2811
2812 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc->id);
2813 if (evnp == NULL) {
2814 dprintk((KERN_WARNING MYNAM ": %s: WARNING - Unable to allocate a event request frame!\n",
2815 ioc->name));
2816 return 0;
2817 }
2818 memset(evnp, 0, sizeof(*evnp));
2819
2820 dprintk((KERN_INFO MYNAM ": %s: Sending EventNotification(%d)\n", ioc->name, EvSwitch));
2821
2822 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
2823 evnp->ChainOffset = 0;
2824 evnp->MsgFlags = 0;
2825 evnp->Switch = EvSwitch;
2826
2827 mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)evnp);
2828
2829 return 0;
2830 }
2831
2832 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2833 /**
2834 * SendEventAck - Send EventAck request to MPT adapter.
2835 * @ioc: Pointer to MPT_ADAPTER structure
2836 * @evnp: Pointer to original EventNotification request
2837 */
2838 static int
2839 SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
2840 {
2841 EventAck_t *pAck;
2842
2843 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
2844 printk(KERN_WARNING MYNAM ": %s: WARNING - Unable to allocate event ACK request frame!\n",
2845 ioc->name);
2846 return -1;
2847 }
2848 memset(pAck, 0, sizeof(*pAck));
2849
2850 dprintk((KERN_INFO MYNAM ": %s: Sending EventAck\n", ioc->name));
2851
2852 pAck->Function = MPI_FUNCTION_EVENT_ACK;
2853 pAck->ChainOffset = 0;
2854 pAck->MsgFlags = 0;
2855 pAck->Event = evnp->Event;
2856 pAck->EventContext = evnp->EventContext;
2857
2858 mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)pAck);
2859
2860 return 0;
2861 }
2862
2863 #ifdef CONFIG_PROC_FS /* { */
2864 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2865 /*
2866 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
2867 */
2868
2869 #define PROC_MPT_READ_RETURN(page,start,off,count,eof,len) \
2870 { \
2871 len -= off; \
2872 if (len < count) { \
2873 *eof = 1; \
2874 if (len <= 0) \
2875 return 0; \
2876 } else \
2877 len = count; \
2878 *start = page + off; \
2879 return len; \
2880 }
2881
2882 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2883 /*
2884 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
2885 *
2886 * Returns 0 for success, non-zero for failure.
2887 */
2888 static int
2889 procmpt_create(void)
2890 {
2891 MPT_ADAPTER *ioc;
2892 struct proc_dir_entry *ent;
2893 int errcnt = 0;
2894
2895 /*
2896 * BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
2897 * (single level) to multi level (e.g. "driver/message/fusion")
2898 * something here needs to change. -sralston
2899 */
2900 procmpt_root_dir = CREATE_PROCDIR_ENTRY(MPT_PROCFS_MPTBASEDIR, NULL);
2901 if (procmpt_root_dir == NULL)
2902 return -ENOTDIR;
2903
2904 if ((ioc = mpt_adapter_find_first()) != NULL) {
2905 ent = create_proc_read_entry(MPT_PROCFS_SUMMARY_NODE, 0, NULL, procmpt_read_summary, NULL);
2906 if (ent == NULL) {
2907 printk(KERN_WARNING MYNAM ": WARNING - Could not create %s entry!\n",
2908 MPT_PROCFS_SUMMARY_PATHNAME);
2909 errcnt++;
2910 }
2911 }
2912
2913 while (ioc != NULL) {
2914 char pname[32];
2915 int namelen;
2916 /*
2917 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
2918 */
2919 namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
2920 if ((ent = CREATE_PROCDIR_ENTRY(pname, NULL)) != NULL) {
2921 /*
2922 * And populate it with: "summary" and "dbg" file entries.
2923 */
2924 (void) sprintf(pname+namelen, "/summary");
2925 ent = create_proc_read_entry(pname, 0, NULL, procmpt_read_summary, ioc);
2926 if (ent == NULL) {
2927 errcnt++;
2928 printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
2929 ioc->name, pname);
2930 }
2931 //#ifdef MPT_DEBUG
2932 /* DEBUG aid! */
2933 (void) sprintf(pname+namelen, "/dbg");
2934 ent = create_proc_read_entry(pname, 0, NULL, procmpt_read_dbg, ioc);
2935 if (ent == NULL) {
2936 errcnt++;
2937 printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
2938 ioc->name, pname);
2939 }
2940 //#endif
2941 } else {
2942 errcnt++;
2943 printk(KERN_WARNING MYNAM ": %s: WARNING - Could not create /proc/%s entry!\n",
2944 ioc->name, pname);
2945
2946 }
2947
2948 ioc = mpt_adapter_find_next(ioc);
2949 }
2950
2951 if (errcnt) {
2952 // remove_proc_entry("mpt", 0);
2953 return -ENOTDIR;
2954 }
2955
2956 return 0;
2957 }
2958
2959 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2960 /*
2961 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
2962 *
2963 * Returns 0 for success, non-zero for failure.
2964 */
2965 static int
2966 procmpt_destroy(void)
2967 {
2968 MPT_ADAPTER *ioc;
2969
2970 if (!procmpt_root_dir)
2971 return 0;
2972
2973 /*
2974 * BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt"
2975 * (single level) to multi level (e.g. "driver/message/fusion")
2976 * something here needs to change. -sralston
2977 */
2978
2979 ioc = mpt_adapter_find_first();
2980 if (ioc != NULL) {
2981 remove_proc_entry(MPT_PROCFS_SUMMARY_NODE, 0);
2982 }
2983
2984 while (ioc != NULL) {
2985 char pname[32];
2986 int namelen;
2987 /*
2988 * Tear down each "/proc/mpt/iocN" subdirectory.
2989 */
2990 namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
2991 (void) sprintf(pname+namelen, "/summary");
2992 remove_proc_entry(pname, 0);
2993 //#ifdef MPT_DEBUG
2994 (void) sprintf(pname+namelen, "/dbg");
2995 remove_proc_entry(pname, 0);
2996 //#endif
2997 (void) sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
2998 remove_proc_entry(pname, 0);
2999
3000 ioc = mpt_adapter_find_next(ioc);
3001 }
3002
3003 if (atomic_read((atomic_t *)&procmpt_root_dir->count) == 0) {
3004 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, 0);
3005 procmpt_root_dir = NULL;
3006 return 0;
3007 }
3008
3009 return -1;
3010 }
3011
3012 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3013 /**
3014 * procmpt_read_summary - Handle read request from /proc/mpt/summary
3015 * or from /proc/mpt/iocN/summary.
3016 * @page: Pointer to area to write information
3017 * @start: Pointer to start pointer
3018 * @off: Offset to start writing
3019 * @count:
3020 * @eof: Pointer to EOF integer
3021 * @data: Pointer
3022 *
3023 * Returns numbers of characters written to process performing the read.
3024 */
3025 static int
3026 procmpt_read_summary(char *page, char **start, off_t off, int count, int *eof, void *data)
3027 {
3028 MPT_ADAPTER *ioc;
3029 char *out = page;
3030 int len;
3031
3032 if (data == NULL)
3033 ioc = mpt_adapter_find_first();
3034 else
3035 ioc = data;
3036
3037 // Too verbose!
3038 // out += sprintf(out, "Attached Fusion MPT I/O Controllers:%s\n", ioc ? "" : " none");
3039
3040 while (ioc) {
3041 int more = 0;
3042
3043 // Too verbose!
3044 // mpt_print_ioc_facts(ioc, out, &more, 0);
3045 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
3046
3047 out += more;
3048 if ((out-page) >= count) {
3049 break;
3050 }
3051
3052 if (data == NULL)
3053 ioc = mpt_adapter_find_next(ioc);
3054 else
3055 ioc = NULL; /* force exit for iocN */
3056 }
3057 len = out - page;
3058
3059 PROC_MPT_READ_RETURN(page,start,off,count,eof,len);
3060 }
3061
3062 // debug aid!
3063 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3064 /**
3065 * procmpt_read_dbg - Handle read request from /proc/mpt/iocN/dbg.
3066 * @page: Pointer to area to write information
3067 * @start: Pointer to start pointer
3068 * @off: Offset to start writing
3069 * @count:
3070 * @eof: Pointer to EOF integer
3071 * @data: Pointer
3072 *
3073 * Returns numbers of characters written to process performing the read.
3074 */
3075 static int
3076 procmpt_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data)
3077 {
3078 MPT_ADAPTER *ioc;
3079 char *out = page;
3080 int len;
3081
3082 ioc = data;
3083
3084 while (ioc) {
3085 int more = 0;
3086
3087 mpt_print_ioc_facts(ioc, out, &more, 0);
3088
3089 out += more;
3090 if ((out-page) >= count) {
3091 break;
3092 }
3093 ioc = NULL;
3094 }
3095 len = out - page;
3096
3097 PROC_MPT_READ_RETURN(page,start,off,count,eof,len);
3098 }
3099 #endif /* CONFIG_PROC_FS } */
3100
3101 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3102 static void
3103 mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
3104 {
3105 if ((ioc->facts.FWVersion & 0xF000) == 0xE000)
3106 sprintf(buf, " (Exp %02d%02d)",
3107 (ioc->facts.FWVersion & 0x0F00) >> 8, /* Month */
3108 ioc->facts.FWVersion & 0x001F); /* Day */
3109 else
3110 buf[0] ='\0';
3111
3112 /* insider hack! */
3113 if (ioc->facts.FWVersion & 0x0080) {
3114 strcat(buf, " [MDBG]");
3115 }
3116 }
3117
3118 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3119 /**
3120 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
3121 * @ioc: Pointer to MPT_ADAPTER structure
3122 * @buffer: Pointer to buffer where IOC summary info should be written
3123 * @size: Pointer to number of bytes we wrote (set by this routine)
3124 * @len: Offset at which to start writing in buffer
3125 * @showlan: Display LAN stuff?
3126 *
3127 * This routine writes (english readable) ASCII text, which represents
3128 * a summary of IOC information, to a buffer.
3129 */
3130 void
3131 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
3132 {
3133 char expVer[32];
3134 int y;
3135
3136 mpt_get_fw_exp_ver(expVer, ioc);
3137
3138 /*
3139 * Shorter summary of attached ioc's...
3140 */
3141 y = sprintf(buffer+len, "%s: %s, %s%04xh%s, Ports=%d, MaxQ=%d",
3142 ioc->name,
3143 ioc->prod_name,
3144 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
3145 ioc->facts.FWVersion,
3146 expVer,
3147 ioc->facts.NumberOfPorts,
3148 ioc->req_depth);
3149
3150 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
3151 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
3152 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
3153 a[5], a[4], a[3], a[2], a[1], a[0]);
3154 }
3155
3156 if (ioc->pci_irq < 100)
3157 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
3158
3159 if (!ioc->active)
3160 y += sprintf(buffer+len+y, " (disabled)");
3161
3162 y += sprintf(buffer+len+y, "\n");
3163
3164 *size = y;
3165 }
3166
3167 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3168 /**
3169 * mpt_print_ioc_facts - Write ASCII summary of IOC facts to a buffer.
3170 * @ioc: Pointer to MPT_ADAPTER structure
3171 * @buffer: Pointer to buffer where IOC facts should be written
3172 * @size: Pointer to number of bytes we wrote (set by this routine)
3173 * @len: Offset at which to start writing in buffer
3174 *
3175 * This routine writes (english readable) ASCII text, which represents
3176 * a summary of the IOC facts, to a buffer.
3177 */
3178 void
3179 mpt_print_ioc_facts(MPT_ADAPTER *ioc, char *buffer, int *size, int len)
3180 {
3181 char expVer[32];
3182 char iocName[16];
3183 int sz;
3184 int y;
3185 int p;
3186
3187 mpt_get_fw_exp_ver(expVer, ioc);
3188
3189 strcpy(iocName, ioc->name);
3190 y = sprintf(buffer+len, "%s:\n", iocName);
3191
3192 y += sprintf(buffer+len+y, " ProductID = 0x%04x\n", ioc->facts.ProductID);
3193 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
3194 y += sprintf(buffer+len+y, " PortNumber = %d (of %d)\n",
3195 p+1,
3196 ioc->facts.NumberOfPorts);
3197 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
3198 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
3199 y += sprintf(buffer+len+y, " LanAddr = 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
3200 a[5], a[4], a[3], a[2], a[1], a[0]);
3201 }
3202 }
3203 y += sprintf(buffer+len+y, " FWVersion = 0x%04x%s\n", ioc->facts.FWVersion, expVer);
3204 y += sprintf(buffer+len+y, " MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
3205 y += sprintf(buffer+len+y, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
3206 y += sprintf(buffer+len+y, " EventState = 0x%02x\n", ioc->facts.EventState);
3207 y += sprintf(buffer+len+y, " CurrentHostMfaHighAddr = 0x%08x\n",
3208 ioc->facts.CurrentHostMfaHighAddr);
3209 y += sprintf(buffer+len+y, " CurrentSenseBufferHighAddr = 0x%08x\n",
3210 ioc->facts.CurrentSenseBufferHighAddr);
3211 y += sprintf(buffer+len+y, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
3212 y += sprintf(buffer+len+y, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
3213
3214 y += sprintf(buffer+len+y, " RequestFrames @ 0x%p (Dma @ 0x%08x)\n",
3215 ioc->req_alloc, ioc->req_alloc_dma);
3216 /*
3217 * Rounding UP to nearest 4-kB boundary here...
3218 */
3219 sz = (ioc->req_sz * ioc->req_depth) + 128;
3220 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
3221 y += sprintf(buffer+len+y, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
3222 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
3223 y += sprintf(buffer+len+y, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
3224 4*ioc->facts.RequestFrameSize,
3225 ioc->facts.GlobalCredits);
3226
3227 y += sprintf(buffer+len+y, " ReplyFrames @ 0x%p (Dma @ 0x%08x)\n",
3228 ioc->reply_alloc, ioc->reply_alloc_dma);
3229 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
3230 y += sprintf(buffer+len+y, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
3231 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
3232 y += sprintf(buffer+len+y, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
3233 ioc->facts.CurReplyFrameSize,
3234 ioc->facts.ReplyQueueDepth);
3235
3236 *size = y;
3237 }
3238
3239 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3240 static char *
3241 EventDescriptionStr(u8 event, u32 evData0)
3242 {
3243 char *ds = NULL;
3244
3245 switch(event) {
3246 case MPI_EVENT_NONE:
3247 ds = "None";
3248 break;
3249 case MPI_EVENT_LOG_DATA:
3250 ds = "Log Data";
3251 break;
3252 case MPI_EVENT_STATE_CHANGE:
3253 ds = "State Change";
3254 break;
3255 case MPI_EVENT_UNIT_ATTENTION:
3256 ds = "Unit Attention";
3257 break;
3258 case MPI_EVENT_IOC_BUS_RESET:
3259 ds = "IOC Bus Reset";
3260 break;
3261 case MPI_EVENT_EXT_BUS_RESET:
3262 ds = "External Bus Reset";
3263 break;
3264 case MPI_EVENT_RESCAN:
3265 ds = "Bus Rescan Event";
3266 /* Ok, do we need to do anything here? As far as
3267 I can tell, this is when a new device gets added
3268 to the loop. */
3269 break;
3270 case MPI_EVENT_LINK_STATUS_CHANGE:
3271 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
3272 ds = "Link Status(FAILURE) Change";
3273 else
3274 ds = "Link Status(ACTIVE) Change";
3275 break;
3276 case MPI_EVENT_LOOP_STATE_CHANGE:
3277 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
3278 ds = "Loop State(LIP) Change";
3279 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
3280 ds = "Loop State(LPE) Change"; /* ??? */
3281 else
3282 ds = "Loop State(LPB) Change"; /* ??? */
3283 break;
3284 case MPI_EVENT_LOGOUT:
3285 ds = "Logout";
3286 break;
3287 case MPI_EVENT_EVENT_CHANGE:
3288 if (evData0)
3289 ds = "Events(ON) Change";
3290 else
3291 ds = "Events(OFF) Change";
3292 break;
3293 /*
3294 * MPT base "custom" events may be added here...
3295 */
3296 default:
3297 ds = "Unknown";
3298 break;
3299 }
3300 return ds;
3301 }
3302
3303 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3304 /**
3305 * ProcessEventNotification - Route a received EventNotificationReply to
3306 * all currently regeistered event handlers.
3307 * @ioc: Pointer to MPT_ADAPTER structure
3308 * @pEventReply: Pointer to EventNotification reply frame
3309 * @evHandlers: Pointer to integer, number of event handlers
3310 *
3311 * Returns sum of event handlers return values.
3312 */
3313 static int
3314 ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
3315 {
3316 u16 evDataLen;
3317 u32 evData0 = 0;
3318 // u32 evCtx;
3319 int i;
3320 int r = 0;
3321 int handlers = 0;
3322 char *evStr;
3323 u8 event;
3324
3325 /*
3326 * Do platform normalization of values
3327 */
3328 event = le32_to_cpu(pEventReply->Event) & 0xFF;
3329 // evCtx = le32_to_cpu(pEventReply->EventContext);
3330 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
3331 if (evDataLen) {
3332 evData0 = le32_to_cpu(pEventReply->Data[0]);
3333 }
3334
3335 evStr = EventDescriptionStr(event, evData0);
3336 dprintk((KERN_INFO MYNAM ": %s: MPT event (%s=%02Xh) detected!\n",
3337 ioc->name,
3338 evStr,
3339 event));
3340
3341 #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
3342 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
3343 for (i = 0; i < evDataLen; i++)
3344 printk(" %08x", le32_to_cpu(pEventReply->Data[i]));
3345 printk("\n");
3346 #endif
3347
3348 /*
3349 * Do general / base driver event processing
3350 */
3351 switch(event) {
3352 case MPI_EVENT_NONE: /* 00 */
3353 case MPI_EVENT_LOG_DATA: /* 01 */
3354 case MPI_EVENT_STATE_CHANGE: /* 02 */
3355 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
3356 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
3357 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
3358 case MPI_EVENT_RESCAN: /* 06 */
3359 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
3360 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
3361 case MPI_EVENT_LOGOUT: /* 09 */
3362 default:
3363 break;
3364 case MPI_EVENT_EVENT_CHANGE: /* 0A */
3365 if (evDataLen) {
3366 u8 evState = evData0 & 0xFF;
3367
3368 /* CHECKME! What if evState unexpectedly says OFF (0)? */
3369
3370 /* Update EventState field in cached IocFacts */
3371 if (ioc->facts.Function) {
3372 ioc->facts.EventState = evState;
3373 }
3374 }
3375 break;
3376 }
3377
3378 /*
3379 * Call each currently registered protocol event handler.
3380 */
3381 for (i=MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
3382 if (MptEvHandlers[i]) {
3383 dprintk((KERN_INFO MYNAM ": %s: Routing Event to event handler #%d\n",
3384 ioc->name, i));
3385 r += (*(MptEvHandlers[i]))(ioc, pEventReply);
3386 handlers++;
3387 }
3388 }
3389 /* FIXME? Examine results here? */
3390
3391 /*
3392 * If needed, send (a single) EventAck.
3393 */
3394 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
3395 if ((i = SendEventAck(ioc, pEventReply)) != 0) {
3396 }
3397 }
3398
3399 *evHandlers = handlers;
3400 return r;
3401 }
3402
3403 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3404 /*
3405 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
3406 * @ioc: Pointer to MPT_ADAPTER structure
3407 * @log_info: U32 LogInfo reply word from the IOC
3408 *
3409 * Refer to lsi/fc_log.h.
3410 */
3411 static void
3412 mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
3413 {
3414 static char *subcl_str[8] = {
3415 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
3416 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
3417 };
3418 char *desc = "unknown";
3419 u8 subcl = (log_info >> 24) & 0x7;
3420 u32 SubCl = log_info & 0x27000000;
3421
3422 switch(log_info) {
3423 /* FCP Initiator */
3424 case MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME:
3425 desc = "Received an out of order frame - unsupported";
3426 break;
3427 case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME:
3428 desc = "Bad start of frame primative";
3429 break;
3430 case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME:
3431 desc = "Bad end of frame primative";
3432 break;
3433 case MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN:
3434 desc = "Receiver hardware detected overrun";
3435 break;
3436 case MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER:
3437 desc = "Other errors caught by IOC which require retries";
3438 break;
3439 case MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD:
3440 desc = "Main processor could not initialize sub-processor";
3441 break;
3442 /* FC Target */
3443 case MPI_IOCLOGINFO_FC_TARGET_NO_PDISC:
3444 desc = "Not sent because we are waiting for a PDISC from the initiator";
3445 break;
3446 case MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN:
3447 desc = "Not sent because we are not logged in to the remote node";
3448 break;
3449 case MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP:
3450 desc = "Data Out, Auto Response, not sent due to a LIP";
3451 break;
3452 case MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP:
3453 desc = "Data In, Auto Response, not sent due to a LIP";
3454 break;
3455 case MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA:
3456 desc = "Data In, Auto Response, missing data frames";
3457 break;
3458 case MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP:
3459 desc = "Data Out, No Response, not sent due to a LIP";
3460 break;
3461 case MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP:
3462 desc = "Auto-response after a write not sent due to a LIP";
3463 break;
3464 case MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP:
3465 desc = "Data In, No Response, not completed due to a LIP";
3466 break;
3467 case MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA:
3468 desc = "Data In, No Response, missing data frames";
3469 break;
3470 case MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP:
3471 desc = "Manual Response not sent due to a LIP";
3472 break;
3473 case MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3:
3474 desc = "Not sent because remote node does not support Class 3";
3475 break;
3476 case MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID:
3477 desc = "Not sent because login to remote node not validated";
3478 break;
3479 case MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND:
3480 desc = "Cleared from the outbound after a logout";
3481 break;
3482 case MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN:
3483 desc = "Cleared waiting for data after a logout";
3484 break;
3485 /* LAN */
3486 case MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING:
3487 desc = "Transaction Context Sgl Missing";
3488 break;
3489 case MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE:
3490 desc = "Transaction Context found before an EOB";
3491 break;
3492 case MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET:
3493 desc = "Transaction Context value has reserved bits set";
3494 break;
3495 case MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG:
3496 desc = "Invalid SGL Flags";
3497 break;
3498 /* FC Link */
3499 case MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT:
3500 desc = "Loop initialization timed out";
3501 break;
3502 case MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED:
3503 desc = "Another system controller already initialized the loop";
3504 break;
3505 case MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED:
3506 desc = "Not synchronized to signal or still negotiating (possible cable problem)";
3507 break;
3508 case MPI_IOCLOGINFO_FC_LINK_CRC_ERROR:
3509 desc = "CRC check detected error on received frame";
3510 break;
3511 }
3512
3513 printk(KERN_INFO MYNAM ": %s: LogInfo(0x%08x): SubCl={%s}",
3514 ioc->name, log_info, subcl_str[subcl]);
3515 if (SubCl == MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET)
3516 printk(", byte_offset=%d\n", log_info & MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET);
3517 else if (SubCl == MPI_IOCLOGINFO_FC_STATE_CHANGE)
3518 printk("\n"); /* StateChg in LogInfo & 0x00FFFFFF, above */
3519 else
3520 printk("\n" KERN_INFO " %s\n", desc);
3521 }
3522
3523 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3524 /*
3525 * mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
3526 * @ioc: Pointer to MPT_ADAPTER structure
3527 * @mr: Pointer to MPT reply frame
3528 * @log_info: U32 LogInfo word from the IOC
3529 *
3530 * Refer to lsi/sp_log.h.
3531 */
3532 static void
3533 mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
3534 {
3535 /* FIXME! */
3536 printk(KERN_INFO MYNAM ": %s: LogInfo(0x%08x)\n", ioc->name, log_info);
3537 }
3538
3539 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3540 /**
3541 * mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI
3542 * OpCode strings from the (optional) isense module.
3543 * @ascqTable: Pointer to ASCQ_Table_t structure
3544 * @ascqtbl_sz: Number of entries in ASCQ_Table
3545 * @opsTable: Pointer to array of SCSI OpCode strings (char pointers)
3546 *
3547 * Specialized driver registration routine for the isense driver.
3548 */
3549 int
3550 mpt_register_ascqops_strings(/*ASCQ_Table_t*/void *ascqTable, int ascqtbl_sz, const char **opsTable)
3551 {
3552 int r = 0;
3553
3554 if (ascqTable && ascqtbl_sz && opsTable) {
3555 mpt_v_ASCQ_TablePtr = ascqTable;
3556 mpt_ASCQ_TableSz = ascqtbl_sz;
3557 mpt_ScsiOpcodesPtr = opsTable;
3558 printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n");
3559 r = 1;
3560 }
3561 MOD_INC_USE_COUNT;
3562 return r;
3563 }
3564
3565 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3566 /**
3567 * mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI
3568 * OpCode strings from the isense driver.
3569 *
3570 * Specialized driver deregistration routine for the isense driver.
3571 */
3572 void
3573 mpt_deregister_ascqops_strings(void)
3574 {
3575 mpt_v_ASCQ_TablePtr = NULL;
3576 mpt_ASCQ_TableSz = 0;
3577 mpt_ScsiOpcodesPtr = NULL;
3578 printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
3579 MOD_DEC_USE_COUNT;
3580 }
3581
3582 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3583
3584 EXPORT_SYMBOL(mpt_register);
3585 EXPORT_SYMBOL(mpt_deregister);
3586 EXPORT_SYMBOL(mpt_event_register);
3587 EXPORT_SYMBOL(mpt_event_deregister);
3588 EXPORT_SYMBOL(mpt_reset_register);
3589 EXPORT_SYMBOL(mpt_reset_deregister);
3590 EXPORT_SYMBOL(mpt_get_msg_frame);
3591 EXPORT_SYMBOL(mpt_put_msg_frame);
3592 EXPORT_SYMBOL(mpt_free_msg_frame);
3593 EXPORT_SYMBOL(mpt_send_handshake_request);
3594 EXPORT_SYMBOL(mpt_adapter_find_first);
3595 EXPORT_SYMBOL(mpt_adapter_find_next);
3596 EXPORT_SYMBOL(mpt_verify_adapter);
3597 EXPORT_SYMBOL(mpt_print_ioc_summary);
3598 EXPORT_SYMBOL(mpt_lan_index);
3599 EXPORT_SYMBOL(mpt_stm_index);
3600
3601 EXPORT_SYMBOL(mpt_register_ascqops_strings);
3602 EXPORT_SYMBOL(mpt_deregister_ascqops_strings);
3603 EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr);
3604 EXPORT_SYMBOL(mpt_ASCQ_TableSz);
3605 EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
3606
3607 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3608 /**
3609 * fusion_init - Fusion MPT base driver initialization routine.
3610 *
3611 * Returns 0 for success, non-zero for failure.
3612 */
3613 int __init fusion_init(void)
3614 {
3615 int i;
3616
3617 if (FusionInitCalled++) {
3618 dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n"));
3619 return 0;
3620 }
3621
3622 show_mptmod_ver(my_NAME, my_VERSION);
3623 printk(KERN_INFO COPYRIGHT "\n");
3624
3625 Q_INIT(&MptAdapters, MPT_ADAPTER); /* set to empty */
3626 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
3627 MptCallbacks[i] = NULL;
3628 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
3629 MptEvHandlers[i] = NULL;
3630 MptResetHandlers[i] = NULL;
3631 }
3632
3633 /* NEW! 20010120 -sralston
3634 * Register ourselves (mptbase) in order to facilitate
3635 * EventNotification handling.
3636 */
3637 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
3638
3639 if ((i = mpt_pci_scan()) < 0)
3640 return i;
3641
3642 return 0;
3643 }
3644
3645 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3646 /**
3647 * fusion_exit - Perform driver unload cleanup.
3648 *
3649 * This routine frees all resources associated with each MPT adapter
3650 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
3651 */
3652 static void fusion_exit(void)
3653 {
3654 MPT_ADAPTER *this;
3655
3656 dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
3657
3658 /* Whups? 20010120 -sralston
3659 * Moved this *above* removal of all MptAdapters!
3660 */
3661 #ifdef CONFIG_PROC_FS
3662 procmpt_destroy();
3663 #endif
3664
3665 while (! Q_IS_EMPTY(&MptAdapters)) {
3666 this = MptAdapters.head;
3667 Q_DEL_ITEM(this);
3668 mpt_adapter_dispose(this);
3669 }
3670 }
3671
3672 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3673
3674 module_init(fusion_init);
3675 module_exit(fusion_exit);
3676