mptbase.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:105k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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