The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/mpt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: mpt.c,v 1.4 2003/11/02 11:07:45 wiz Exp $      */
    2 
    3 /*
    4  * Copyright (c) 2000, 2001 by Greg Ansley
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice immediately at the beginning of the file, without modification,
   11  *    this list of conditions, and the following disclaimer.
   12  * 2. The name of the author may not be used to endorse or promote products
   13  *    derived from this software without specific prior written permission.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 /*
   28  * Additional Copyright (c) 2002 by Matthew Jacob under same license.
   29  */
   30 
   31 /*
   32  * mpt.c:
   33  *
   34  * Generic routines for LSI Fusion adapters.
   35  *
   36  * Adapted from the FreeBSD "mpt" driver by Jason R. Thorpe for
   37  * Wasabi Systems, Inc.
   38  */
   39 
   40 #include <sys/cdefs.h>
   41 __KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.4 2003/11/02 11:07:45 wiz Exp $");
   42 
   43 #include <dev/ic/mpt.h>
   44 
   45 #define MPT_MAX_TRYS 3
   46 #define MPT_MAX_WAIT 300000
   47 
   48 static int maxwait_ack = 0;
   49 static int maxwait_int = 0;
   50 static int maxwait_state = 0;
   51 
   52 static __inline u_int32_t
   53 mpt_rd_db(mpt_softc_t *mpt)
   54 {
   55         return mpt_read(mpt, MPT_OFFSET_DOORBELL);
   56 }
   57 
   58 static __inline u_int32_t
   59 mpt_rd_intr(mpt_softc_t *mpt)
   60 {
   61         return mpt_read(mpt, MPT_OFFSET_INTR_STATUS);
   62 }
   63 
   64 /* Busy wait for a door bell to be read by IOC */
   65 static int
   66 mpt_wait_db_ack(mpt_softc_t *mpt)
   67 {
   68         int i;
   69         for (i=0; i < MPT_MAX_WAIT; i++) {
   70                 if (!MPT_DB_IS_BUSY(mpt_rd_intr(mpt))) {
   71                         maxwait_ack = i > maxwait_ack ? i : maxwait_ack;
   72                         return MPT_OK;
   73                 }
   74 
   75                 DELAY(100);
   76         }
   77         return MPT_FAIL;
   78 }
   79 
   80 /* Busy wait for a door bell interrupt */
   81 static int
   82 mpt_wait_db_int(mpt_softc_t *mpt)
   83 {
   84         int i;
   85         for (i=0; i < MPT_MAX_WAIT; i++) {
   86                 if (MPT_DB_INTR(mpt_rd_intr(mpt))) {
   87                         maxwait_int = i > maxwait_int ? i : maxwait_int;
   88                         return MPT_OK;
   89                 }
   90                 DELAY(100);
   91         }
   92         return MPT_FAIL;
   93 }
   94 
   95 /* Wait for IOC to transition to a give state */
   96 void
   97 mpt_check_doorbell(mpt_softc_t *mpt)
   98 {
   99         u_int32_t db = mpt_rd_db(mpt);
  100         if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) {
  101                 mpt_prt(mpt, "Device not running");
  102                 mpt_print_db(db);
  103         }
  104 }
  105 
  106 /* Wait for IOC to transition to a give state */
  107 static int
  108 mpt_wait_state(mpt_softc_t *mpt, enum DB_STATE_BITS state)
  109 {
  110         int i;
  111 
  112         for (i = 0; i < MPT_MAX_WAIT; i++) {
  113                 u_int32_t db = mpt_rd_db(mpt);
  114                 if (MPT_STATE(db) == state) {
  115                         maxwait_state = i > maxwait_state ? i : maxwait_state;
  116                         return (MPT_OK);
  117                 }
  118                 DELAY(100);
  119         }
  120         return (MPT_FAIL);
  121 }
  122 
  123 
  124 /* Issue the reset COMMAND to the IOC */
  125 int
  126 mpt_soft_reset(mpt_softc_t *mpt)
  127 {
  128         if (mpt->verbose) {
  129                 mpt_prt(mpt, "soft reset");
  130         }
  131 
  132         /* Have to use hard reset if we are not in Running state */
  133         if (MPT_STATE(mpt_rd_db(mpt)) != MPT_DB_STATE_RUNNING) {
  134                 mpt_prt(mpt, "soft reset failed: device not running");
  135                 return MPT_FAIL;
  136         }
  137 
  138         /* If door bell is in use we don't have a chance of getting
  139          * a word in since the IOC probably crashed in message
  140          * processing. So don't waste our time.
  141          */
  142         if (MPT_DB_IS_IN_USE(mpt_rd_db(mpt))) {
  143                 mpt_prt(mpt, "soft reset failed: doorbell wedged");
  144                 return MPT_FAIL;
  145         }
  146 
  147         /* Send the reset request to the IOC */
  148         mpt_write(mpt, MPT_OFFSET_DOORBELL,
  149             MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET << MPI_DOORBELL_FUNCTION_SHIFT);
  150         if (mpt_wait_db_ack(mpt) != MPT_OK) {
  151                 mpt_prt(mpt, "soft reset failed: ack timeout");
  152                 return MPT_FAIL;
  153         }
  154 
  155         /* Wait for the IOC to reload and come out of reset state */
  156         if (mpt_wait_state(mpt, MPT_DB_STATE_READY) != MPT_OK) {
  157                 mpt_prt(mpt, "soft reset failed: device did not start running");
  158                 return MPT_FAIL;
  159         }
  160 
  161         return MPT_OK;
  162 }
  163 
  164 /* This is a magic diagnostic reset that resets all the ARM
  165  * processors in the chip. 
  166  */
  167 void
  168 mpt_hard_reset(mpt_softc_t *mpt)
  169 {
  170         /* This extra read comes for the Linux source
  171          * released by LSI. It's function is undocumented!
  172          */
  173         if (mpt->verbose) {
  174                 mpt_prt(mpt, "hard reset");
  175         }
  176         mpt_read(mpt, MPT_OFFSET_FUBAR);
  177 
  178         /* Enable diagnostic registers */
  179         mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_1);
  180         mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_2);
  181         mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_3);
  182         mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_4);
  183         mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_5);
  184 
  185         /* Diag. port is now active so we can now hit the reset bit */
  186         mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, MPT_DIAG_RESET_IOC);
  187 
  188         DELAY(10000);
  189 
  190         /* Disable Diagnostic Register */
  191         mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF);
  192 
  193         /* Restore the config register values */
  194         /*   Hard resets are known to screw up the BAR for diagnostic
  195              memory accesses (Mem1). */
  196         mpt_set_config_regs(mpt);
  197         if (mpt->mpt2 != NULL) {
  198                 mpt_set_config_regs(mpt->mpt2);
  199         }
  200 
  201         /* Note that if there is no valid firmware to run, the doorbell will
  202            remain in the reset state (0x00000000) */
  203 }
  204 
  205 /*
  206  * Reset the IOC when needed. Try software command first then if needed
  207  * poke at the magic diagnostic reset. Note that a hard reset resets
  208  * *both* IOCs on dual function chips (FC929 && LSI1030) as well as
  209  * fouls up the PCI configuration registers.
  210  */
  211 int
  212 mpt_reset(mpt_softc_t *mpt)
  213 {
  214         int ret;
  215 
  216         /* Try a soft reset */
  217         if ((ret = mpt_soft_reset(mpt)) != MPT_OK) {
  218                 /* Failed; do a hard reset */
  219                 mpt_hard_reset(mpt);
  220 
  221                 /* Wait for the IOC to reload and come out of reset state */
  222                 ret = mpt_wait_state(mpt, MPT_DB_STATE_READY);
  223                 if (ret != MPT_OK) {
  224                         mpt_prt(mpt, "failed to reset device");
  225                 }
  226         }
  227 
  228         return ret;
  229 }
  230 
  231 /* Return a command buffer to the free queue */
  232 void
  233 mpt_free_request(mpt_softc_t *mpt, request_t *req)
  234 {
  235         if (req == NULL || req != &mpt->request_pool[req->index]) {
  236                 panic("mpt_free_request bad req ptr\n");
  237                 return;
  238         }
  239         req->sequence = 0;
  240         req->xfer = NULL;
  241         req->debug = REQ_FREE;
  242         SLIST_INSERT_HEAD(&mpt->request_free_list, req, link);
  243 }
  244 
  245 /* Get a command buffer from the free queue */
  246 request_t *
  247 mpt_get_request(mpt_softc_t *mpt)
  248 {
  249         request_t *req;
  250         req = SLIST_FIRST(&mpt->request_free_list);
  251         if (req != NULL) {
  252                 if (req != &mpt->request_pool[req->index]) {
  253                         panic("mpt_get_request: corrupted request free list\n");
  254                 }
  255                 if (req->xfer != NULL) {
  256                         panic("mpt_get_request: corrupted request free list (xfer)\n");
  257                 }
  258                 SLIST_REMOVE_HEAD(&mpt->request_free_list, link);
  259                 req->debug = REQ_IN_PROGRESS;
  260         }
  261         return req;
  262 }
  263 
  264 /* Pass the command to the IOC */
  265 void
  266 mpt_send_cmd(mpt_softc_t *mpt, request_t *req)
  267 {
  268         req->sequence = mpt->sequence++;
  269         if (mpt->verbose > 1) {
  270                 u_int32_t *pReq;
  271                 pReq = req->req_vbuf;
  272                 mpt_prt(mpt, "Send Request %d (0x%x):",
  273                     req->index, req->req_pbuf);
  274                 mpt_prt(mpt, "%08x %08x %08x %08x",
  275                     pReq[0], pReq[1], pReq[2], pReq[3]);
  276                 mpt_prt(mpt, "%08x %08x %08x %08x",
  277                     pReq[4], pReq[5], pReq[6], pReq[7]);
  278                 mpt_prt(mpt, "%08x %08x %08x %08x",
  279                     pReq[8], pReq[9], pReq[10], pReq[11]);
  280                 mpt_prt(mpt, "%08x %08x %08x %08x",
  281                     pReq[12], pReq[13], pReq[14], pReq[15]);
  282         }
  283         MPT_SYNC_REQ(mpt, req, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  284         req->debug = REQ_ON_CHIP;
  285         mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (u_int32_t) req->req_pbuf);
  286 }
  287 
  288 /*
  289  * Give the reply buffer back to the IOC after we have
  290  * finished processing it.
  291  */
  292 void
  293 mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr)
  294 {
  295      mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr);
  296 }
  297 
  298 /* Get a reply from the IOC */
  299 u_int32_t
  300 mpt_pop_reply_queue(mpt_softc_t *mpt)
  301 {
  302      return mpt_read(mpt, MPT_OFFSET_REPLY_Q);
  303 }
  304 
  305 /*
  306  * Send a command to the IOC via the handshake register.
  307  *
  308  * Only done at initialization time and for certain unusual
  309  * commands such as device/bus reset as specified by LSI.
  310  */
  311 int
  312 mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd)
  313 {
  314         int i;
  315         u_int32_t data, *data32;
  316 
  317         /* Check condition of the IOC */
  318         data = mpt_rd_db(mpt);
  319         if (((MPT_STATE(data) != MPT_DB_STATE_READY)    &&
  320              (MPT_STATE(data) != MPT_DB_STATE_RUNNING)  &&
  321              (MPT_STATE(data) != MPT_DB_STATE_FAULT))   ||
  322             (  MPT_DB_IS_IN_USE(data) )) {
  323                 mpt_prt(mpt, "handshake aborted due to invalid doorbell state");
  324                 mpt_print_db(data);
  325                 return(EBUSY);
  326         }
  327 
  328         /* We move things in 32 bit chunks */
  329         len = (len + 3) >> 2;
  330         data32 = cmd;
  331 
  332         /* Clear any left over pending doorbell interrupts */
  333         if (MPT_DB_INTR(mpt_rd_intr(mpt)))
  334                 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  335 
  336         /*
  337          * Tell the handshake reg. we are going to send a command
  338          * and how long it is going to be.
  339          */
  340         data = (MPI_FUNCTION_HANDSHAKE << MPI_DOORBELL_FUNCTION_SHIFT) |
  341             (len << MPI_DOORBELL_ADD_DWORDS_SHIFT);
  342         mpt_write(mpt, MPT_OFFSET_DOORBELL, data);
  343 
  344         /* Wait for the chip to notice */
  345         if (mpt_wait_db_int(mpt) != MPT_OK) {
  346                 mpt_prt(mpt, "mpt_send_handshake_cmd timeout1");
  347                 return ETIMEDOUT;
  348         }
  349 
  350         /* Clear the interrupt */
  351         mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  352 
  353         if (mpt_wait_db_ack(mpt) != MPT_OK) {
  354                 mpt_prt(mpt, "mpt_send_handshake_cmd timeout2");
  355                 return ETIMEDOUT;
  356         }
  357 
  358         /* Send the command */
  359         for (i = 0; i < len; i++) {
  360                 mpt_write(mpt, MPT_OFFSET_DOORBELL, *data32++);
  361                 if (mpt_wait_db_ack(mpt) != MPT_OK) {
  362                         mpt_prt(mpt,
  363                             "mpt_send_handshake_cmd timeout! index = %d", i);
  364                         return ETIMEDOUT;
  365                 }
  366         }
  367         return MPT_OK;
  368 }
  369 
  370 /* Get the response from the handshake register */
  371 int
  372 mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply)
  373 {
  374         int left, reply_left;
  375         u_int16_t *data16;
  376         MSG_DEFAULT_REPLY *hdr;
  377 
  378         /* We move things out in 16 bit chunks */
  379         reply_len >>= 1;
  380         data16 = (u_int16_t *)reply;
  381 
  382         hdr = (MSG_DEFAULT_REPLY *)reply;
  383 
  384         /* Get first word */
  385         if (mpt_wait_db_int(mpt) != MPT_OK) {
  386                 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout1");
  387                 return ETIMEDOUT;
  388         }
  389         *data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK;
  390         mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  391 
  392         /* Get Second Word */
  393         if (mpt_wait_db_int(mpt) != MPT_OK) {
  394                 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2");
  395                 return ETIMEDOUT;
  396         }
  397         *data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK;
  398         mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  399 
  400         /* With the second word, we can now look at the length */
  401         if (mpt->verbose > 1 && ((reply_len >> 1) != hdr->MsgLength)) {
  402                 mpt_prt(mpt, "reply length does not match message length: "
  403                         "got 0x%02x, expected 0x%02x",
  404                         hdr->MsgLength << 2, reply_len << 1);
  405         }
  406 
  407         /* Get rest of the reply; but don't overflow the provided buffer */
  408         left = (hdr->MsgLength << 1) - 2;
  409         reply_left =  reply_len - 2;
  410         while (left--) {
  411                 u_int16_t datum;
  412 
  413                 if (mpt_wait_db_int(mpt) != MPT_OK) {
  414                         mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3");
  415                         return ETIMEDOUT;
  416                 }
  417                 datum = mpt_read(mpt, MPT_OFFSET_DOORBELL);
  418 
  419                 if (reply_left-- > 0)
  420                         *data16++ = datum & MPT_DB_DATA_MASK;
  421 
  422                 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  423         }
  424 
  425         /* One more wait & clear at the end */
  426         if (mpt_wait_db_int(mpt) != MPT_OK) {
  427                 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout4");
  428                 return ETIMEDOUT;
  429         }
  430         mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  431 
  432         if ((hdr->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
  433                 if (mpt->verbose > 1)
  434                         mpt_print_reply(hdr);
  435                 return (MPT_FAIL | hdr->IOCStatus);
  436         }
  437 
  438         return (0);
  439 }
  440 
  441 static int
  442 mpt_get_iocfacts(mpt_softc_t *mpt, MSG_IOC_FACTS_REPLY *freplp)
  443 {
  444         MSG_IOC_FACTS f_req;
  445         int error;
  446         
  447         bzero(&f_req, sizeof f_req);
  448         f_req.Function = MPI_FUNCTION_IOC_FACTS;
  449         f_req.MsgContext =  0x12071942;
  450         error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
  451         if (error)
  452                 return(error);
  453         error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
  454         return (error);
  455 }
  456 
  457 static int
  458 mpt_get_portfacts(mpt_softc_t *mpt, MSG_PORT_FACTS_REPLY *freplp)
  459 {
  460         MSG_PORT_FACTS f_req;
  461         int error;
  462         
  463         /* XXX: Only getting PORT FACTS for Port 0 */
  464         bzero(&f_req, sizeof f_req);
  465         f_req.Function = MPI_FUNCTION_PORT_FACTS;
  466         f_req.MsgContext =  0x12071943;
  467         error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
  468         if (error)
  469                 return(error);
  470         error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
  471         return (error);
  472 }
  473 
  474 /*
  475  * Send the initialization request. This is where we specify how many
  476  * SCSI busses and how many devices per bus we wish to emulate.
  477  * This is also the command that specifies the max size of the reply
  478  * frames from the IOC that we will be allocating.
  479  */
  480 static int
  481 mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who)
  482 {
  483         int error = 0;
  484         MSG_IOC_INIT init;
  485         MSG_IOC_INIT_REPLY reply;
  486 
  487         bzero(&init, sizeof init);
  488         init.WhoInit = who;
  489         init.Function = MPI_FUNCTION_IOC_INIT;
  490         if (mpt->is_fc) {
  491                 init.MaxDevices = 255;
  492         } else {
  493                 init.MaxDevices = 16;
  494         }
  495         init.MaxBuses = 1;
  496         init.ReplyFrameSize = MPT_REPLY_SIZE;
  497         init.MsgContext = 0x12071941;
  498 
  499         if ((error = mpt_send_handshake_cmd(mpt, sizeof init, &init)) != 0) {
  500                 return(error);
  501         }
  502 
  503         error = mpt_recv_handshake_reply(mpt, sizeof reply, &reply);
  504         return (error);
  505 }
  506 
  507 
  508 /*
  509  * Utiltity routine to read configuration headers and pages
  510  */
  511 
  512 static int
  513 mpt_read_cfg_header(mpt_softc_t *, int, int, int, fCONFIG_PAGE_HEADER *);
  514 
  515 static int
  516 mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber,
  517     int PageAddress, fCONFIG_PAGE_HEADER *rslt)
  518 {
  519         int count;
  520         request_t *req;
  521         MSG_CONFIG *cfgp;
  522         MSG_CONFIG_REPLY *reply;
  523 
  524         req = mpt_get_request(mpt);
  525 
  526         cfgp = req->req_vbuf;
  527         bzero(cfgp, sizeof *cfgp);
  528 
  529         cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER;
  530         cfgp->Function = MPI_FUNCTION_CONFIG;
  531         cfgp->Header.PageNumber = (U8) PageNumber;
  532         cfgp->Header.PageType = (U8) PageType;
  533         cfgp->PageAddress = PageAddress;
  534         MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE),
  535             (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
  536             MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
  537         cfgp->MsgContext = req->index | 0x80000000;
  538 
  539         mpt_check_doorbell(mpt);
  540         mpt_send_cmd(mpt, req);
  541         count = 0;
  542         do {
  543                 DELAY(500);
  544                 mpt_intr(mpt);
  545                 if (++count == 1000) {
  546                         mpt_prt(mpt, "read_cfg_header timed out");
  547                         return (-1);
  548                 }
  549         } while (req->debug == REQ_ON_CHIP);
  550 
  551         reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
  552         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
  553                 mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x",
  554                     reply->IOCStatus);
  555                 mpt_free_reply(mpt, (req->sequence << 1));
  556                 return (-1);
  557         }
  558         bcopy(&reply->Header, rslt, sizeof (fCONFIG_PAGE_HEADER));
  559         mpt_free_reply(mpt, (req->sequence << 1));
  560         mpt_free_request(mpt, req);
  561         return (0);
  562 }
  563 
  564 #define CFG_DATA_OFF    128
  565 
  566 int
  567 mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
  568 {
  569         int count;
  570         request_t *req;
  571         SGE_SIMPLE32 *se;
  572         MSG_CONFIG *cfgp;
  573         size_t amt;
  574         MSG_CONFIG_REPLY *reply;
  575 
  576         req = mpt_get_request(mpt);
  577 
  578         cfgp = req->req_vbuf;
  579         bzero(cfgp, MPT_REQUEST_AREA);
  580         cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
  581         cfgp->Function = MPI_FUNCTION_CONFIG;
  582         cfgp->Header = *hdr;
  583         amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
  584         cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK;
  585         cfgp->PageAddress = PageAddress;
  586         se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
  587         se->Address = req->req_pbuf + CFG_DATA_OFF;
  588         MPI_pSGE_SET_LENGTH(se, amt);
  589         MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
  590             MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
  591             MPI_SGE_FLAGS_END_OF_LIST));
  592 
  593         cfgp->MsgContext = req->index | 0x80000000;
  594 
  595         mpt_check_doorbell(mpt);
  596         mpt_send_cmd(mpt, req);
  597         count = 0;
  598         do {
  599                 DELAY(500);
  600                 mpt_intr(mpt);
  601                 if (++count == 1000) {
  602                         mpt_prt(mpt, "read_cfg_page timed out");
  603                         return (-1);
  604                 }
  605         } while (req->debug == REQ_ON_CHIP);
  606 
  607         reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
  608         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
  609                 mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x",
  610                     reply->IOCStatus);
  611                 mpt_free_reply(mpt, (req->sequence << 1));
  612                 return (-1);
  613         }
  614         mpt_free_reply(mpt, (req->sequence << 1));
  615 #if 0 /* XXXJRT */
  616         bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
  617             BUS_DMASYNC_POSTREAD);
  618 #endif
  619         if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  620             cfgp->Header.PageNumber == 0) {
  621                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
  622         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  623             cfgp->Header.PageNumber == 1) {
  624                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
  625         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  626             cfgp->Header.PageNumber == 2) {
  627                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
  628         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
  629             cfgp->Header.PageNumber == 0) {
  630                 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
  631         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
  632             cfgp->Header.PageNumber == 1) {
  633                 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
  634         }
  635         bcopy(((caddr_t)req->req_vbuf)+CFG_DATA_OFF, hdr, amt);
  636         mpt_free_request(mpt, req);
  637         return (0);
  638 }
  639 
  640 int
  641 mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
  642 {
  643         int count, hdr_attr;
  644         request_t *req;
  645         SGE_SIMPLE32 *se;
  646         MSG_CONFIG *cfgp;
  647         size_t amt;
  648         MSG_CONFIG_REPLY *reply;
  649 
  650         req = mpt_get_request(mpt);
  651 
  652         cfgp = req->req_vbuf;
  653         bzero(cfgp, sizeof *cfgp);
  654 
  655         hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
  656         if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
  657             hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
  658                 mpt_prt(mpt, "page type 0x%x not changeable",
  659                     hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
  660                 return (-1);
  661         }
  662         hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK;
  663 
  664         cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
  665         cfgp->Function = MPI_FUNCTION_CONFIG;
  666         cfgp->Header = *hdr;
  667         amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
  668         cfgp->PageAddress = PageAddress;
  669 
  670         se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
  671         se->Address = req->req_pbuf + CFG_DATA_OFF;
  672         MPI_pSGE_SET_LENGTH(se, amt);
  673         MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
  674             MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
  675             MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC));
  676 
  677         cfgp->MsgContext = req->index | 0x80000000;
  678 
  679         if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  680             cfgp->Header.PageNumber == 0) {
  681                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
  682         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  683             cfgp->Header.PageNumber == 1) {
  684                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
  685         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  686             cfgp->Header.PageNumber == 2) {
  687                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
  688         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
  689             cfgp->Header.PageNumber == 0) {
  690                 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
  691         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
  692             cfgp->Header.PageNumber == 1) {
  693                 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
  694         }
  695         bcopy(hdr, ((caddr_t)req->req_vbuf)+CFG_DATA_OFF, amt);
  696         /* Restore stripped out attributes */
  697         hdr->PageType |= hdr_attr;
  698 
  699         mpt_check_doorbell(mpt);
  700         mpt_send_cmd(mpt, req);
  701         count = 0;
  702         do {
  703                 DELAY(500);
  704                 mpt_intr(mpt);
  705                 if (++count == 1000) {
  706                         hdr->PageType |= hdr_attr;
  707                         mpt_prt(mpt, "mpt_write_cfg_page timed out");
  708                         return (-1);
  709                 }
  710         } while (req->debug == REQ_ON_CHIP);
  711 
  712         reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
  713         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
  714                 mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x",
  715                     reply->IOCStatus);
  716                 mpt_free_reply(mpt, (req->sequence << 1));
  717                 return (-1);
  718         }
  719         mpt_free_reply(mpt, (req->sequence << 1));
  720 
  721         mpt_free_request(mpt, req);
  722         return (0);
  723 }
  724 
  725 /*
  726  * Read SCSI configuration information
  727  */
  728 static int
  729 mpt_read_config_info_spi(mpt_softc_t *mpt)
  730 {
  731         int rv, i;
  732 
  733         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0,
  734             0, &mpt->mpt_port_page0.Header);
  735         if (rv) {
  736                 return (-1);
  737         }
  738         if (mpt->verbose > 1) {
  739                 mpt_prt(mpt, "SPI Port Page 0 Header: %x %x %x %x",
  740                     mpt->mpt_port_page0.Header.PageVersion,
  741                     mpt->mpt_port_page0.Header.PageLength,
  742                     mpt->mpt_port_page0.Header.PageNumber,
  743                     mpt->mpt_port_page0.Header.PageType);
  744         }
  745 
  746         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1,
  747             0, &mpt->mpt_port_page1.Header);
  748         if (rv) {
  749                 return (-1);
  750         }
  751         if (mpt->verbose > 1) {
  752                 mpt_prt(mpt, "SPI Port Page 1 Header: %x %x %x %x",
  753                     mpt->mpt_port_page1.Header.PageVersion,
  754                     mpt->mpt_port_page1.Header.PageLength,
  755                     mpt->mpt_port_page1.Header.PageNumber,
  756                     mpt->mpt_port_page1.Header.PageType);
  757         }
  758 
  759         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2,
  760             0, &mpt->mpt_port_page2.Header);
  761         if (rv) {
  762                 return (-1);
  763         }
  764 
  765         if (mpt->verbose > 1) {
  766                 mpt_prt(mpt, "SPI Port Page 2 Header: %x %x %x %x",
  767                     mpt->mpt_port_page1.Header.PageVersion,
  768                     mpt->mpt_port_page1.Header.PageLength,
  769                     mpt->mpt_port_page1.Header.PageNumber,
  770                     mpt->mpt_port_page1.Header.PageType);
  771         }
  772 
  773         for (i = 0; i < 16; i++) {
  774                 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
  775                     0, i, &mpt->mpt_dev_page0[i].Header);
  776                 if (rv) {
  777                         return (-1);
  778                 }
  779                 if (mpt->verbose > 1) {
  780                         mpt_prt(mpt,
  781                             "SPI Target %d Device Page 0 Header: %x %x %x %x",
  782                             i, mpt->mpt_dev_page0[i].Header.PageVersion,
  783                             mpt->mpt_dev_page0[i].Header.PageLength,
  784                             mpt->mpt_dev_page0[i].Header.PageNumber,
  785                             mpt->mpt_dev_page0[i].Header.PageType);
  786                 }
  787                 
  788                 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
  789                     1, i, &mpt->mpt_dev_page1[i].Header);
  790                 if (rv) {
  791                         return (-1);
  792                 }
  793                 if (mpt->verbose > 1) {
  794                         mpt_prt(mpt,
  795                             "SPI Target %d Device Page 1 Header: %x %x %x %x",
  796                             i, mpt->mpt_dev_page1[i].Header.PageVersion,
  797                             mpt->mpt_dev_page1[i].Header.PageLength,
  798                             mpt->mpt_dev_page1[i].Header.PageNumber,
  799                             mpt->mpt_dev_page1[i].Header.PageType);
  800                 }
  801         }
  802 
  803         /*
  804          * At this point, we don't *have* to fail. As long as we have
  805          * valid config header information, we can (barely) lurch
  806          * along.
  807          */
  808 
  809         rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header);
  810         if (rv) {
  811                 mpt_prt(mpt, "failed to read SPI Port Page 0");
  812         } else if (mpt->verbose > 1) {
  813                 mpt_prt(mpt,
  814                     "SPI Port Page 0: Capabilities %x PhysicalInterface %x",
  815                     mpt->mpt_port_page0.Capabilities,
  816                     mpt->mpt_port_page0.PhysicalInterface);
  817         }
  818 
  819         rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header);
  820         if (rv) {
  821                 mpt_prt(mpt, "failed to read SPI Port Page 1");
  822         } else if (mpt->verbose > 1) {
  823                 mpt_prt(mpt,
  824                     "SPI Port Page 1: Configuration %x OnBusTimerValue %x",
  825                     mpt->mpt_port_page1.Configuration,
  826                     mpt->mpt_port_page1.OnBusTimerValue);
  827         }
  828 
  829         rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header);
  830         if (rv) {
  831                 mpt_prt(mpt, "failed to read SPI Port Page 2");
  832         } else if (mpt->verbose > 1) {
  833                 mpt_prt(mpt,
  834                     "SPI Port Page 2: Flags %x Settings %x",
  835                     mpt->mpt_port_page2.PortFlags,
  836                     mpt->mpt_port_page2.PortSettings);
  837                 for (i = 0; i < 16; i++) {
  838                         mpt_prt(mpt,
  839                             "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x",
  840                             i, mpt->mpt_port_page2.DeviceSettings[i].Timeout,
  841                             mpt->mpt_port_page2.DeviceSettings[i].SyncFactor,
  842                             mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags);
  843                 }
  844         }
  845 
  846         for (i = 0; i < 16; i++) {
  847                 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header);
  848                 if (rv) {
  849                         mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 0", i);
  850                         continue;
  851                 }
  852                 if (mpt->verbose > 1) {
  853                         mpt_prt(mpt,
  854                             "SPI Tgt %d Page 0: NParms %x Information %x",
  855                             i, mpt->mpt_dev_page0[i].NegotiatedParameters,
  856                             mpt->mpt_dev_page0[i].Information);
  857                 }
  858                 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header);
  859                 if (rv) {
  860                         mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 1", i);
  861                         continue;
  862                 }
  863                 if (mpt->verbose > 1) {
  864                         mpt_prt(mpt,
  865                             "SPI Tgt %d Page 1: RParms %x Configuration %x",
  866                             i, mpt->mpt_dev_page1[i].RequestedParameters,
  867                             mpt->mpt_dev_page1[i].Configuration);
  868                 }
  869         }
  870         return (0);
  871 }
  872 
  873 /*
  874  * Validate SPI configuration information.
  875  *
  876  * In particular, validate SPI Port Page 1.
  877  */
  878 static int
  879 mpt_set_initial_config_spi(mpt_softc_t *mpt)
  880 {
  881         int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id;
  882 
  883         mpt->mpt_disc_enable = 0xff;
  884         mpt->mpt_tag_enable = 0;
  885 
  886         if (mpt->mpt_port_page1.Configuration != pp1val) {
  887                 fCONFIG_PAGE_SCSI_PORT_1 tmp;
  888                 mpt_prt(mpt,
  889                     "SPI Port Page 1 Config value bad (%x)- should be %x",
  890                     mpt->mpt_port_page1.Configuration, pp1val);
  891                 tmp = mpt->mpt_port_page1;
  892                 tmp.Configuration = pp1val;
  893                 if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) {
  894                         return (-1);
  895                 }
  896                 if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) {
  897                         return (-1);
  898                 }
  899                 if (tmp.Configuration != pp1val) {
  900                         mpt_prt(mpt,
  901                             "failed to reset SPI Port Page 1 Config value");
  902                         return (-1);
  903                 }
  904                 mpt->mpt_port_page1 = tmp;
  905         }
  906 
  907         for (i = 0; i < 16; i++) {
  908                 fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
  909                 tmp = mpt->mpt_dev_page1[i];
  910                 tmp.RequestedParameters = 0;
  911                 tmp.Configuration = 0;
  912                 if (mpt->verbose > 1) {
  913                         mpt_prt(mpt,
  914                             "Set Tgt %d SPI DevicePage 1 values to %x 0 %x",
  915                             i, tmp.RequestedParameters, tmp.Configuration);
  916                 }
  917                 if (mpt_write_cfg_page(mpt, i, &tmp.Header)) {
  918                         return (-1);
  919                 }
  920                 if (mpt_read_cfg_page(mpt, i, &tmp.Header)) {
  921                         return (-1);
  922                 }
  923                 mpt->mpt_dev_page1[i] = tmp;
  924                 if (mpt->verbose > 1) {
  925                         mpt_prt(mpt,
  926                             "SPI Tgt %d Page 1: RParm %x Configuration %x", i,
  927                             mpt->mpt_dev_page1[i].RequestedParameters,
  928                             mpt->mpt_dev_page1[i].Configuration);
  929                 }
  930         }
  931         return (0);
  932 }
  933 
  934 /*
  935  * Enable IOC port
  936  */
  937 static int
  938 mpt_send_port_enable(mpt_softc_t *mpt, int port)
  939 {
  940         int count;
  941         request_t *req;
  942         MSG_PORT_ENABLE *enable_req;
  943 
  944         req = mpt_get_request(mpt);
  945 
  946         enable_req = req->req_vbuf;
  947         bzero(enable_req, sizeof *enable_req);
  948 
  949         enable_req->Function   = MPI_FUNCTION_PORT_ENABLE;
  950         enable_req->MsgContext = req->index | 0x80000000;
  951         enable_req->PortNumber = port;
  952 
  953         mpt_check_doorbell(mpt);
  954         if (mpt->verbose > 1) {
  955                 mpt_prt(mpt, "enabling port %d", port);
  956         }
  957         mpt_send_cmd(mpt, req);
  958 
  959         count = 0;
  960         do {
  961                 DELAY(500);
  962                 mpt_intr(mpt);
  963                 if (++count == 100000) {
  964                         mpt_prt(mpt, "port enable timed out");
  965                         return (-1);
  966                 }
  967         } while (req->debug == REQ_ON_CHIP);
  968         mpt_free_request(mpt, req);
  969         return (0);
  970 }
  971 
  972 /*
  973  * Enable/Disable asynchronous event reporting.
  974  *
  975  * NB: this is the first command we send via shared memory
  976  * instead of the handshake register.
  977  */
  978 static int
  979 mpt_send_event_request(mpt_softc_t *mpt, int onoff)
  980 {
  981         request_t *req;
  982         MSG_EVENT_NOTIFY *enable_req;
  983 
  984         req = mpt_get_request(mpt);
  985 
  986         enable_req = req->req_vbuf;
  987         bzero(enable_req, sizeof *enable_req);
  988 
  989         enable_req->Function   = MPI_FUNCTION_EVENT_NOTIFICATION;
  990         enable_req->MsgContext = req->index | 0x80000000;
  991         enable_req->Switch     = onoff;
  992 
  993         mpt_check_doorbell(mpt);
  994         if (mpt->verbose > 1) {
  995                 mpt_prt(mpt, "%sabling async events", onoff? "en" : "dis");
  996         }
  997         mpt_send_cmd(mpt, req);
  998 
  999         return (0);
 1000 }
 1001 
 1002 /*
 1003  * Un-mask the interrupts on the chip.
 1004  */
 1005 void
 1006 mpt_enable_ints(mpt_softc_t *mpt)
 1007 {
 1008         /* Unmask every thing except door bell int */
 1009         mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK);
 1010 }
 1011 
 1012 /*
 1013  * Mask the interrupts on the chip.
 1014  */
 1015 void
 1016 mpt_disable_ints(mpt_softc_t *mpt)
 1017 {
 1018         /* Mask all interrupts */
 1019         mpt_write(mpt, MPT_OFFSET_INTR_MASK, 
 1020             MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK);
 1021 }
 1022 
 1023 /* (Re)Initialize the chip for use */
 1024 int
 1025 mpt_init(mpt_softc_t *mpt, u_int32_t who)
 1026 {
 1027         int try;
 1028         MSG_IOC_FACTS_REPLY facts;
 1029         MSG_PORT_FACTS_REPLY pfp;
 1030         u_int32_t pptr;
 1031         int val;
 1032 
 1033         /* Put all request buffers (back) on the free list */
 1034         SLIST_INIT(&mpt->request_free_list);
 1035         for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
 1036                 mpt_free_request(mpt, &mpt->request_pool[val]);
 1037         }
 1038 
 1039         if (mpt->verbose > 1) {
 1040                 mpt_prt(mpt, "doorbell req = %s",
 1041                     mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL)));
 1042         }
 1043 
 1044         /*
 1045          * Start by making sure we're not at FAULT or RESET state
 1046          */
 1047         switch (mpt_rd_db(mpt) & MPT_DB_STATE_MASK) {
 1048         case MPT_DB_STATE_RESET:
 1049         case MPT_DB_STATE_FAULT:
 1050                 if (mpt_reset(mpt) != MPT_OK) {
 1051                         return (EIO);
 1052                 }
 1053         default:
 1054                 break;
 1055         }
 1056         
 1057         for (try = 0; try < MPT_MAX_TRYS; try++) {
 1058                 /*
 1059                  * No need to reset if the IOC is already in the READY state.
 1060                  *
 1061                  * Force reset if initialization failed previously.
 1062                  * Note that a hard_reset of the second channel of a '929
 1063                  * will stop operation of the first channel.  Hopefully, if the
 1064                  * first channel is ok, the second will not require a hard 
 1065                  * reset.
 1066                  */
 1067                 if ((mpt_rd_db(mpt) & MPT_DB_STATE_MASK) !=
 1068                     MPT_DB_STATE_READY) {
 1069                         if (mpt_reset(mpt) != MPT_OK) {
 1070                                 DELAY(10000);
 1071                                 continue;
 1072                         }
 1073                 }
 1074 
 1075                 if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
 1076                         mpt_prt(mpt, "mpt_get_iocfacts failed");
 1077                         continue;
 1078                 }
 1079 
 1080                 if (mpt->verbose > 1) {
 1081                         mpt_prt(mpt,
 1082                             "IOCFACTS: GlobalCredits=%d BlockSize=%u "
 1083                             "Request Frame Size %u\n", facts.GlobalCredits,
 1084                             facts.BlockSize, facts.RequestFrameSize);
 1085                 }
 1086                 mpt->mpt_global_credits = facts.GlobalCredits;
 1087                 mpt->request_frame_size = facts.RequestFrameSize;
 1088 
 1089                 if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
 1090                         mpt_prt(mpt, "mpt_get_portfacts failed");
 1091                         continue;
 1092                 }
 1093 
 1094                 if (mpt->verbose > 1) {
 1095                         mpt_prt(mpt,
 1096                             "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d\n",
 1097                             pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID,
 1098                             pfp.MaxDevices);
 1099                 }
 1100 
 1101                 if (pfp.PortType != MPI_PORTFACTS_PORTTYPE_SCSI &&
 1102                     pfp.PortType != MPI_PORTFACTS_PORTTYPE_FC) {
 1103                         mpt_prt(mpt, "Unsupported Port Type (%x)",
 1104                             pfp.PortType);
 1105                         return (ENXIO);
 1106                 }
 1107                 if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
 1108                         mpt_prt(mpt, "initiator role unsupported");
 1109                         return (ENXIO);
 1110                 }
 1111                 if (pfp.PortType == MPI_PORTFACTS_PORTTYPE_FC) {
 1112                         mpt->is_fc = 1;
 1113                 } else {
 1114                         mpt->is_fc = 0;
 1115                 }
 1116                 mpt->mpt_ini_id = pfp.PortSCSIID;
 1117 
 1118                 if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
 1119                         mpt_prt(mpt, "mpt_send_ioc_init failed");
 1120                         continue;
 1121                 }
 1122 
 1123                 if (mpt->verbose > 1) {
 1124                         mpt_prt(mpt, "mpt_send_ioc_init ok");
 1125                 }
 1126 
 1127                 if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) {
 1128                         mpt_prt(mpt, "IOC failed to go to run state");
 1129                         continue;
 1130                 }
 1131                 if (mpt->verbose > 1) {
 1132                         mpt_prt(mpt, "IOC now at RUNSTATE");
 1133                 }
 1134 
 1135                 /*
 1136                  * Give it reply buffers
 1137                  *
 1138                  * Do *not* except global credits.
 1139                  */
 1140                 for (val = 0, pptr = mpt->reply_phys; 
 1141                     (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE); 
 1142                      pptr += MPT_REPLY_SIZE) {
 1143                         mpt_free_reply(mpt, pptr);
 1144                         if (++val == mpt->mpt_global_credits - 1)
 1145                                 break;
 1146                 }
 1147 
 1148                 /*
 1149                  * Enable asynchronous event reporting
 1150                  */
 1151                 mpt_send_event_request(mpt, 1);
 1152 
 1153 
 1154                 /*
 1155                  * Read set up initial configuration information
 1156                  * (SPI only for now)
 1157                  */
 1158 
 1159                 if (mpt->is_fc == 0) {
 1160                         if (mpt_read_config_info_spi(mpt)) {
 1161                                 return (EIO);
 1162                         }
 1163                         if (mpt_set_initial_config_spi(mpt)) {
 1164                                 return (EIO);
 1165                         }
 1166                 }
 1167 
 1168                 /*
 1169                  * Now enable the port
 1170                  */
 1171                 if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
 1172                         mpt_prt(mpt, "failed to enable port 0");
 1173                         continue;
 1174                 }
 1175 
 1176                 if (mpt->verbose > 1) {
 1177                         mpt_prt(mpt, "enabled port 0");
 1178                 }
 1179 
 1180                 /* Everything worked */
 1181                 break;
 1182         }
 1183 
 1184         if (try >= MPT_MAX_TRYS) {
 1185                 mpt_prt(mpt, "failed to initialize IOC");
 1186                 return (EIO);
 1187         }
 1188 
 1189         if (mpt->verbose > 1) {
 1190                 mpt_prt(mpt, "enabling interrupts");
 1191         }
 1192 
 1193         mpt_enable_ints(mpt);
 1194         return (0);
 1195 }

Cache object: 67335b599f4b04f74508dd3414684146


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.