OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [message/] [fusion/] [mptbase.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.