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.21 2019/09/23 16:19:33 skrll 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  * Copyright (c) 2002, 2006 by Matthew Jacob
   32  * All rights reserved.
   33  *
   34  * Redistribution and use in source and binary forms, with or without
   35  * modification, are permitted provided that the following conditions are
   36  * met:
   37  * 1. Redistributions of source code must retain the above copyright
   38  *    notice, this list of conditions and the following disclaimer.
   39  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   40  *    substantially similar to the "NO WARRANTY" disclaimer below
   41  *    ("Disclaimer") and any redistribution must be conditioned upon including
   42  *    a substantially similar Disclaimer requirement for further binary
   43  *    redistribution.
   44  * 3. Neither the names of the above listed copyright holders nor the names
   45  *    of any contributors may be used to endorse or promote products derived
   46  *    from this software without specific prior written permission.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   49  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   52  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   53  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   54  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   55  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   56  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   57  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
   58  * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   59  *
   60  * Support from Chris Ellsworth in order to make SAS adapters work
   61  * is gratefully acknowledged.
   62  *
   63  *
   64  * Support from LSI-Logic has also gone a great deal toward making this a
   65  * workable subsystem and is gratefully acknowledged.
   66  */
   67 /*-
   68  * Copyright (c) 2004, Avid Technology, Inc. and its contributors.
   69  * Copyright (c) 2005, WHEEL Sp. z o.o.
   70  * Copyright (c) 2004, 2005 Justin T. Gibbs
   71  * All rights reserved.
   72  *
   73  * Redistribution and use in source and binary forms, with or without
   74  * modification, are permitted provided that the following conditions are
   75  * met:
   76  * 1. Redistributions of source code must retain the above copyright
   77  *    notice, this list of conditions and the following disclaimer.
   78  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   79  *    substantially similar to the "NO WARRANTY" disclaimer below
   80  *    ("Disclaimer") and any redistribution must be conditioned upon including
   81  *    a substantially similar Disclaimer requirement for further binary
   82  *    redistribution.
   83  * 3. Neither the names of the above listed copyright holders nor the names
   84  *    of any contributors may be used to endorse or promote products derived
   85  *    from this software without specific prior written permission.
   86  *
   87  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   88  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   89  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   90  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   91  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   92  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   93  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   94  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   95  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   96  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
   97  * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   98  */
   99 
  100 
  101 /*
  102  * mpt.c:
  103  *
  104  * Generic routines for LSI Fusion adapters.
  105  *
  106  * Adapted from the FreeBSD "mpt" driver by Jason R. Thorpe for
  107  * Wasabi Systems, Inc.
  108  *
  109  * Additional contributions by Garrett D'Amore on behalf of TELES AG.
  110  */
  111 
  112 #include <sys/cdefs.h>
  113 __KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.21 2019/09/23 16:19:33 skrll Exp $");
  114 
  115 #include <dev/ic/mpt.h>
  116 
  117 #define MPT_MAX_TRYS 3
  118 #define MPT_MAX_WAIT 300000
  119 
  120 static int maxwait_ack = 0;
  121 static int maxwait_int = 0;
  122 static int maxwait_state = 0;
  123 
  124 static inline u_int32_t
  125 mpt_rd_db(mpt_softc_t *mpt)
  126 {
  127         return mpt_read(mpt, MPT_OFFSET_DOORBELL);
  128 }
  129 
  130 static inline u_int32_t
  131 mpt_rd_intr(mpt_softc_t *mpt)
  132 {
  133         return mpt_read(mpt, MPT_OFFSET_INTR_STATUS);
  134 }
  135 
  136 /* Busy wait for a door bell to be read by IOC */
  137 static int
  138 mpt_wait_db_ack(mpt_softc_t *mpt)
  139 {
  140         int i;
  141         for (i=0; i < MPT_MAX_WAIT; i++) {
  142                 if (!MPT_DB_IS_BUSY(mpt_rd_intr(mpt))) {
  143                         maxwait_ack = i > maxwait_ack ? i : maxwait_ack;
  144                         return MPT_OK;
  145                 }
  146 
  147                 DELAY(100);
  148         }
  149         return MPT_FAIL;
  150 }
  151 
  152 /* Busy wait for a door bell interrupt */
  153 static int
  154 mpt_wait_db_int(mpt_softc_t *mpt)
  155 {
  156         int i;
  157         for (i=0; i < MPT_MAX_WAIT; i++) {
  158                 if (MPT_DB_INTR(mpt_rd_intr(mpt))) {
  159                         maxwait_int = i > maxwait_int ? i : maxwait_int;
  160                         return MPT_OK;
  161                 }
  162                 DELAY(100);
  163         }
  164         return MPT_FAIL;
  165 }
  166 
  167 /* Wait for IOC to transition to a give state */
  168 void
  169 mpt_check_doorbell(mpt_softc_t *mpt)
  170 {
  171         u_int32_t db = mpt_rd_db(mpt);
  172         if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) {
  173                 mpt_prt(mpt, "Device not running");
  174                 mpt_print_db(db);
  175         }
  176 }
  177 
  178 /* Wait for IOC to transition to a give state */
  179 static int
  180 mpt_wait_state(mpt_softc_t *mpt, enum DB_STATE_BITS state)
  181 {
  182         int i;
  183 
  184         for (i = 0; i < MPT_MAX_WAIT; i++) {
  185                 u_int32_t db = mpt_rd_db(mpt);
  186                 if (MPT_STATE(db) == state) {
  187                         maxwait_state = i > maxwait_state ? i : maxwait_state;
  188                         return (MPT_OK);
  189                 }
  190                 DELAY(100);
  191         }
  192         return (MPT_FAIL);
  193 }
  194 
  195 
  196 /* Issue the reset COMMAND to the IOC */
  197 int
  198 mpt_soft_reset(mpt_softc_t *mpt)
  199 {
  200         if (mpt->verbose) {
  201                 mpt_prt(mpt, "soft reset");
  202         }
  203 
  204         /* Have to use hard reset if we are not in Running state */
  205         if (MPT_STATE(mpt_rd_db(mpt)) != MPT_DB_STATE_RUNNING) {
  206                 mpt_prt(mpt, "soft reset failed: device not running");
  207                 return MPT_FAIL;
  208         }
  209 
  210         /* If door bell is in use we don't have a chance of getting
  211          * a word in since the IOC probably crashed in message
  212          * processing. So don't waste our time.
  213          */
  214         if (MPT_DB_IS_IN_USE(mpt_rd_db(mpt))) {
  215                 mpt_prt(mpt, "soft reset failed: doorbell wedged");
  216                 return MPT_FAIL;
  217         }
  218 
  219         /* Send the reset request to the IOC */
  220         mpt_write(mpt, MPT_OFFSET_DOORBELL,
  221             MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET << MPI_DOORBELL_FUNCTION_SHIFT);
  222         if (mpt_wait_db_ack(mpt) != MPT_OK) {
  223                 mpt_prt(mpt, "soft reset failed: ack timeout");
  224                 return MPT_FAIL;
  225         }
  226 
  227         /* Wait for the IOC to reload and come out of reset state */
  228         if (mpt_wait_state(mpt, MPT_DB_STATE_READY) != MPT_OK) {
  229                 mpt_prt(mpt, "soft reset failed: device did not start running");
  230                 return MPT_FAIL;
  231         }
  232 
  233         return MPT_OK;
  234 }
  235 
  236 /* This is a magic diagnostic reset that resets all the ARM
  237  * processors in the chip.
  238  */
  239 void
  240 mpt_hard_reset(mpt_softc_t *mpt)
  241 {
  242         if (mpt->verbose) {
  243                 mpt_prt(mpt, "hard reset");
  244         }
  245         mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xff);
  246 
  247         /* Enable diagnostic registers */
  248         mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_1);
  249         mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_2);
  250         mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_3);
  251         mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_4);
  252         mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_5);
  253 
  254         /* Diag. port is now active so we can now hit the reset bit */
  255         mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, MPT_DIAG_RESET_IOC);
  256 
  257         DELAY(10000);
  258 
  259         /* Disable Diagnostic Register */
  260         mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF);
  261 }
  262 
  263 /*
  264  * Reset the IOC when needed. Try software command first then if needed
  265  * poke at the magic diagnostic reset. Note that a hard reset resets
  266  * *both* IOCs on dual function chips (FC929 && LSI1030) as well as
  267  * fouls up the PCI configuration registers.
  268  */
  269 int
  270 mpt_reset(mpt_softc_t *mpt)
  271 {
  272         int ret;
  273 
  274         /* Try a soft reset */
  275         if ((ret = mpt_soft_reset(mpt)) != MPT_OK) {
  276                 /* Failed; do a hard reset */
  277                 mpt_hard_reset(mpt);
  278 
  279                 /* Wait for the IOC to reload and come out of reset state */
  280                 ret = mpt_wait_state(mpt, MPT_DB_STATE_READY);
  281                 if (ret != MPT_OK) {
  282                         mpt_prt(mpt, "failed to reset device");
  283                 }
  284         }
  285 
  286         return ret;
  287 }
  288 
  289 /* Return a command buffer to the free queue */
  290 void
  291 mpt_free_request(mpt_softc_t *mpt, request_t *req)
  292 {
  293         if (req == NULL || req != &mpt->request_pool[req->index]) {
  294                 panic("mpt_free_request bad req ptr\n");
  295                 return;
  296         }
  297         req->sequence = 0;
  298         req->xfer = NULL;
  299         req->debug = REQ_FREE;
  300         SLIST_INSERT_HEAD(&mpt->request_free_list, req, link);
  301 }
  302 
  303 /* Get a command buffer from the free queue */
  304 request_t *
  305 mpt_get_request(mpt_softc_t *mpt)
  306 {
  307         request_t *req;
  308         req = SLIST_FIRST(&mpt->request_free_list);
  309         if (req != NULL) {
  310                 if (req != &mpt->request_pool[req->index]) {
  311                         panic("mpt_get_request: corrupted request free list\n");
  312                 }
  313                 if (req->xfer != NULL) {
  314                         panic("mpt_get_request: corrupted request free list (xfer)\n");
  315                 }
  316                 SLIST_REMOVE_HEAD(&mpt->request_free_list, link);
  317                 req->debug = REQ_IN_PROGRESS;
  318         }
  319         return req;
  320 }
  321 
  322 /* Pass the command to the IOC */
  323 void
  324 mpt_send_cmd(mpt_softc_t *mpt, request_t *req)
  325 {
  326         req->sequence = mpt->sequence++;
  327         if (mpt->verbose > 1) {
  328                 u_int32_t *pReq;
  329                 pReq = req->req_vbuf;
  330                 mpt_prt(mpt, "Send Request %d (%#" PRIxBUSADDR "):",
  331                     req->index, req->req_pbuf);
  332                 mpt_prt(mpt, "%08x %08x %08x %08x",
  333                     pReq[0], pReq[1], pReq[2], pReq[3]);
  334                 mpt_prt(mpt, "%08x %08x %08x %08x",
  335                     pReq[4], pReq[5], pReq[6], pReq[7]);
  336                 mpt_prt(mpt, "%08x %08x %08x %08x",
  337                     pReq[8], pReq[9], pReq[10], pReq[11]);
  338                 mpt_prt(mpt, "%08x %08x %08x %08x",
  339                     pReq[12], pReq[13], pReq[14], pReq[15]);
  340         }
  341         MPT_SYNC_REQ(mpt, req, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  342         req->debug = REQ_ON_CHIP;
  343         mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (u_int32_t) req->req_pbuf);
  344 }
  345 
  346 /*
  347  * Give the reply buffer back to the IOC after we have
  348  * finished processing it.
  349  */
  350 void
  351 mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr)
  352 {
  353      mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr);
  354 }
  355 
  356 /* Get a reply from the IOC */
  357 u_int32_t
  358 mpt_pop_reply_queue(mpt_softc_t *mpt)
  359 {
  360      return mpt_read(mpt, MPT_OFFSET_REPLY_Q);
  361 }
  362 
  363 /*
  364  * Send a command to the IOC via the handshake register.
  365  *
  366  * Only done at initialization time and for certain unusual
  367  * commands such as device/bus reset as specified by LSI.
  368  */
  369 int
  370 mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd)
  371 {
  372         int i;
  373         u_int32_t data, *data32;
  374 
  375         /* Check condition of the IOC */
  376         data = mpt_rd_db(mpt);
  377         if (((MPT_STATE(data) != MPT_DB_STATE_READY)    &&
  378              (MPT_STATE(data) != MPT_DB_STATE_RUNNING)  &&
  379              (MPT_STATE(data) != MPT_DB_STATE_FAULT))   ||
  380             (  MPT_DB_IS_IN_USE(data) )) {
  381                 mpt_prt(mpt, "handshake aborted due to invalid doorbell state");
  382                 mpt_print_db(data);
  383                 return(EBUSY);
  384         }
  385 
  386         /* We move things in 32 bit chunks */
  387         len = (len + 3) >> 2;
  388         data32 = cmd;
  389 
  390         /* Clear any left over pending doorbell interrupts */
  391         if (MPT_DB_INTR(mpt_rd_intr(mpt)))
  392                 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  393 
  394         /*
  395          * Tell the handshake reg. we are going to send a command
  396          * and how long it is going to be.
  397          */
  398         data = (MPI_FUNCTION_HANDSHAKE << MPI_DOORBELL_FUNCTION_SHIFT) |
  399             (len << MPI_DOORBELL_ADD_DWORDS_SHIFT);
  400         mpt_write(mpt, MPT_OFFSET_DOORBELL, data);
  401 
  402         /* Wait for the chip to notice */
  403         if (mpt_wait_db_int(mpt) != MPT_OK) {
  404                 mpt_prt(mpt, "mpt_send_handshake_cmd timeout1");
  405                 return ETIMEDOUT;
  406         }
  407 
  408         /* Clear the interrupt */
  409         mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  410 
  411         if (mpt_wait_db_ack(mpt) != MPT_OK) {
  412                 mpt_prt(mpt, "mpt_send_handshake_cmd timeout2");
  413                 return ETIMEDOUT;
  414         }
  415 
  416         /* Send the command */
  417         for (i = 0; i < len; i++) {
  418                 mpt_write(mpt, MPT_OFFSET_DOORBELL, htole32(*data32++));
  419                 if (mpt_wait_db_ack(mpt) != MPT_OK) {
  420                         mpt_prt(mpt,
  421                             "mpt_send_handshake_cmd timeout! index = %d", i);
  422                         return ETIMEDOUT;
  423                 }
  424         }
  425         return MPT_OK;
  426 }
  427 
  428 /* Get the response from the handshake register */
  429 int
  430 mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply)
  431 {
  432         int left, reply_left;
  433         u_int16_t *data16;
  434         MSG_DEFAULT_REPLY *hdr;
  435 
  436         /* We move things out in 16 bit chunks */
  437         reply_len >>= 1;
  438         data16 = (u_int16_t *)reply;
  439 
  440         hdr = (MSG_DEFAULT_REPLY *)reply;
  441 
  442         /* Get first word */
  443         if (mpt_wait_db_int(mpt) != MPT_OK) {
  444                 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout1");
  445                 return ETIMEDOUT;
  446         }
  447         *data16++ = le16toh(mpt_read(mpt, MPT_OFFSET_DOORBELL) &
  448                             MPT_DB_DATA_MASK);
  449         mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  450 
  451         /* Get Second Word */
  452         if (mpt_wait_db_int(mpt) != MPT_OK) {
  453                 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2");
  454                 return ETIMEDOUT;
  455         }
  456         *data16++ = le16toh(mpt_read(mpt, MPT_OFFSET_DOORBELL) &
  457                             MPT_DB_DATA_MASK);
  458         mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  459 
  460         /* With the second word, we can now look at the length */
  461         if (mpt->verbose > 1 && ((reply_len >> 1) != hdr->MsgLength)) {
  462                 mpt_prt(mpt, "reply length does not match message length: "
  463                         "got 0x%02x, expected %#02zx",
  464                         hdr->MsgLength << 2, reply_len << 1);
  465         }
  466 
  467         /* Get rest of the reply; but don't overflow the provided buffer */
  468         left = (hdr->MsgLength << 1) - 2;
  469         reply_left =  reply_len - 2;
  470         while (left--) {
  471                 u_int16_t datum;
  472 
  473                 if (mpt_wait_db_int(mpt) != MPT_OK) {
  474                         mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3");
  475                         return ETIMEDOUT;
  476                 }
  477                 datum = mpt_read(mpt, MPT_OFFSET_DOORBELL);
  478 
  479                 if (reply_left-- > 0)
  480                         *data16++ = le16toh(datum & MPT_DB_DATA_MASK);
  481 
  482                 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  483         }
  484 
  485         /* One more wait & clear at the end */
  486         if (mpt_wait_db_int(mpt) != MPT_OK) {
  487                 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout4");
  488                 return ETIMEDOUT;
  489         }
  490         mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
  491 
  492         if ((hdr->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
  493                 if (mpt->verbose > 1)
  494                         mpt_print_reply(hdr);
  495                 return (MPT_FAIL | hdr->IOCStatus);
  496         }
  497 
  498         return (0);
  499 }
  500 
  501 static int
  502 mpt_get_iocfacts(mpt_softc_t *mpt, MSG_IOC_FACTS_REPLY *freplp)
  503 {
  504         MSG_IOC_FACTS f_req;
  505         int error;
  506 
  507         memset(&f_req, 0, sizeof f_req);
  508         f_req.Function = MPI_FUNCTION_IOC_FACTS;
  509         f_req.MsgContext = htole32(0x12071942);
  510         error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
  511         if (error)
  512                 return(error);
  513         error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
  514         return (error);
  515 }
  516 
  517 static int
  518 mpt_get_portfacts(mpt_softc_t *mpt, MSG_PORT_FACTS_REPLY *freplp)
  519 {
  520         MSG_PORT_FACTS f_req;
  521         int error;
  522 
  523         /* XXX: Only getting PORT FACTS for Port 0 */
  524         memset(&f_req, 0, sizeof f_req);
  525         f_req.Function = MPI_FUNCTION_PORT_FACTS;
  526         f_req.MsgContext =  htole32(0x12071943);
  527         error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
  528         if (error)
  529                 return(error);
  530         error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
  531         return (error);
  532 }
  533 
  534 /*
  535  * Send the initialization request. This is where we specify how many
  536  * SCSI busses and how many devices per bus we wish to emulate.
  537  * This is also the command that specifies the max size of the reply
  538  * frames from the IOC that we will be allocating.
  539  */
  540 static int
  541 mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who)
  542 {
  543         int error = 0;
  544         MSG_IOC_INIT init;
  545         MSG_IOC_INIT_REPLY reply;
  546 
  547         memset(&init, 0, sizeof init);
  548         init.WhoInit = who;
  549         init.Function = MPI_FUNCTION_IOC_INIT;
  550         init.MaxDevices = mpt->mpt_max_devices;
  551         init.MaxBuses = 1;
  552         init.ReplyFrameSize = htole16(MPT_REPLY_SIZE);
  553         init.MsgContext = htole32(0x12071941);
  554 
  555         if ((error = mpt_send_handshake_cmd(mpt, sizeof init, &init)) != 0) {
  556                 return(error);
  557         }
  558 
  559         error = mpt_recv_handshake_reply(mpt, sizeof reply, &reply);
  560         return (error);
  561 }
  562 
  563 
  564 /*
  565  * Utiltity routine to read configuration headers and pages
  566  */
  567 
  568 int
  569 mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber,
  570     int PageAddress, fCONFIG_PAGE_HEADER *rslt)
  571 {
  572         int count;
  573         request_t *req;
  574         MSG_CONFIG *cfgp;
  575         MSG_CONFIG_REPLY *reply;
  576 
  577         req = mpt_get_request(mpt);
  578 
  579         cfgp = req->req_vbuf;
  580         memset(cfgp, 0, sizeof *cfgp);
  581 
  582         cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER;
  583         cfgp->Function = MPI_FUNCTION_CONFIG;
  584         cfgp->Header.PageNumber = (U8) PageNumber;
  585         cfgp->Header.PageType = (U8) PageType;
  586         cfgp->PageAddress = htole32(PageAddress);
  587         MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE),
  588             (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
  589             MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
  590         cfgp->MsgContext = htole32(req->index | 0x80000000);
  591 
  592         mpt_check_doorbell(mpt);
  593         mpt_send_cmd(mpt, req);
  594         count = 0;
  595         do {
  596                 DELAY(500);
  597                 mpt_intr(mpt);
  598                 if (++count == 1000) {
  599                         mpt_prt(mpt, "read_cfg_header timed out");
  600                         return (-1);
  601                 }
  602         } while (req->debug == REQ_ON_CHIP);
  603 
  604         reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
  605         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
  606                 mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x",
  607                     reply->IOCStatus);
  608                 mpt_free_reply(mpt, (req->sequence << 1));
  609                 return (-1);
  610         }
  611         memcpy(rslt, &reply->Header, sizeof (fCONFIG_PAGE_HEADER));
  612         mpt_free_reply(mpt, (req->sequence << 1));
  613         mpt_free_request(mpt, req);
  614         return (0);
  615 }
  616 
  617 #define CFG_DATA_OFF    128
  618 
  619 int
  620 mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
  621 {
  622         int count;
  623         request_t *req;
  624         SGE_SIMPLE32 *se;
  625         MSG_CONFIG *cfgp;
  626         size_t amt;
  627         MSG_CONFIG_REPLY *reply;
  628 
  629         req = mpt_get_request(mpt);
  630 
  631         cfgp = req->req_vbuf;
  632         memset(cfgp, 0, MPT_REQUEST_AREA);
  633         cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
  634         cfgp->Function = MPI_FUNCTION_CONFIG;
  635         cfgp->Header = *hdr;
  636         amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
  637         cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK;
  638         cfgp->PageAddress = htole32(PageAddress);
  639         se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
  640         se->Address = htole32(req->req_pbuf + CFG_DATA_OFF);
  641         MPI_pSGE_SET_LENGTH(se, amt);
  642         MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
  643             MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
  644             MPI_SGE_FLAGS_END_OF_LIST));
  645         se->FlagsLength = htole32(se->FlagsLength);
  646 
  647         cfgp->MsgContext = htole32(req->index | 0x80000000);
  648 
  649         mpt_check_doorbell(mpt);
  650         mpt_send_cmd(mpt, req);
  651         count = 0;
  652         do {
  653                 DELAY(500);
  654                 mpt_intr(mpt);
  655                 if (++count == 1000) {
  656                         mpt_prt(mpt, "read_cfg_page timed out");
  657                         return (-1);
  658                 }
  659         } while (req->debug == REQ_ON_CHIP);
  660 
  661         reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
  662         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
  663                 mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x",
  664                     reply->IOCStatus);
  665                 mpt_free_reply(mpt, (req->sequence << 1));
  666                 return (-1);
  667         }
  668         mpt_free_reply(mpt, (req->sequence << 1));
  669 #if 0 /* XXXJRT */
  670         bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
  671             BUS_DMASYNC_POSTREAD);
  672 #endif
  673         if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  674             cfgp->Header.PageNumber == 0) {
  675                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
  676         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  677             cfgp->Header.PageNumber == 1) {
  678                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
  679         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  680             cfgp->Header.PageNumber == 2) {
  681                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
  682         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
  683             cfgp->Header.PageNumber == 0) {
  684                 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
  685         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
  686             cfgp->Header.PageNumber == 1) {
  687                 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
  688         }
  689         memcpy(hdr, (char *)req->req_vbuf + CFG_DATA_OFF, amt);
  690         mpt_free_request(mpt, req);
  691         return (0);
  692 }
  693 
  694 int
  695 mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
  696 {
  697         int count, hdr_attr;
  698         request_t *req;
  699         SGE_SIMPLE32 *se;
  700         MSG_CONFIG *cfgp;
  701         size_t amt;
  702         MSG_CONFIG_REPLY *reply;
  703 
  704         req = mpt_get_request(mpt);
  705 
  706         cfgp = req->req_vbuf;
  707         memset(cfgp, 0, sizeof *cfgp);
  708 
  709         hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
  710         if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
  711             hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
  712                 mpt_prt(mpt, "page type 0x%x not changeable",
  713                     hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
  714                 return (-1);
  715         }
  716         hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK;
  717 
  718         cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
  719         cfgp->Function = MPI_FUNCTION_CONFIG;
  720         cfgp->Header = *hdr;
  721         amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
  722         cfgp->PageAddress = htole32(PageAddress);
  723 
  724         se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
  725         se->Address = htole32(req->req_pbuf + CFG_DATA_OFF);
  726         MPI_pSGE_SET_LENGTH(se, amt);
  727         MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
  728             MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
  729             MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC));
  730         se->FlagsLength = htole32(se->FlagsLength);
  731 
  732         cfgp->MsgContext = htole32(req->index | 0x80000000);
  733 
  734         if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  735             cfgp->Header.PageNumber == 0) {
  736                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
  737         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  738             cfgp->Header.PageNumber == 1) {
  739                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
  740         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
  741             cfgp->Header.PageNumber == 2) {
  742                 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
  743         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
  744             cfgp->Header.PageNumber == 0) {
  745                 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
  746         } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
  747             cfgp->Header.PageNumber == 1) {
  748                 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
  749         }
  750         memcpy((char *)req->req_vbuf + CFG_DATA_OFF, hdr, amt);
  751         /* Restore stripped out attributes */
  752         hdr->PageType |= hdr_attr;
  753 
  754         mpt_check_doorbell(mpt);
  755         mpt_send_cmd(mpt, req);
  756         count = 0;
  757         do {
  758                 DELAY(500);
  759                 mpt_intr(mpt);
  760                 if (++count == 1000) {
  761                         hdr->PageType |= hdr_attr;
  762                         mpt_prt(mpt, "mpt_write_cfg_page timed out");
  763                         return (-1);
  764                 }
  765         } while (req->debug == REQ_ON_CHIP);
  766 
  767         reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
  768         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
  769                 mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x",
  770                     le16toh(reply->IOCStatus));
  771                 mpt_free_reply(mpt, (req->sequence << 1));
  772                 return (-1);
  773         }
  774         mpt_free_reply(mpt, (req->sequence << 1));
  775 
  776         mpt_free_request(mpt, req);
  777         return (0);
  778 }
  779 
  780 /*
  781  * Read SCSI configuration information
  782  */
  783 static int
  784 mpt_read_config_info_spi(mpt_softc_t *mpt)
  785 {
  786         int rv, i;
  787 
  788         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0,
  789             0, &mpt->mpt_port_page0.Header);
  790         if (rv) {
  791                 return (-1);
  792         }
  793         if (mpt->verbose > 1) {
  794                 mpt_prt(mpt, "SPI Port Page 0 Header: %x %x %x %x",
  795                     mpt->mpt_port_page0.Header.PageVersion,
  796                     mpt->mpt_port_page0.Header.PageLength,
  797                     mpt->mpt_port_page0.Header.PageNumber,
  798                     mpt->mpt_port_page0.Header.PageType);
  799         }
  800 
  801         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1,
  802             0, &mpt->mpt_port_page1.Header);
  803         if (rv) {
  804                 return (-1);
  805         }
  806         if (mpt->verbose > 1) {
  807                 mpt_prt(mpt, "SPI Port Page 1 Header: %x %x %x %x",
  808                     mpt->mpt_port_page1.Header.PageVersion,
  809                     mpt->mpt_port_page1.Header.PageLength,
  810                     mpt->mpt_port_page1.Header.PageNumber,
  811                     mpt->mpt_port_page1.Header.PageType);
  812         }
  813 
  814         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2,
  815             0, &mpt->mpt_port_page2.Header);
  816         if (rv) {
  817                 return (-1);
  818         }
  819 
  820         if (mpt->verbose > 1) {
  821                 mpt_prt(mpt, "SPI Port Page 2 Header: %x %x %x %x",
  822                     mpt->mpt_port_page1.Header.PageVersion,
  823                     mpt->mpt_port_page1.Header.PageLength,
  824                     mpt->mpt_port_page1.Header.PageNumber,
  825                     mpt->mpt_port_page1.Header.PageType);
  826         }
  827 
  828         for (i = 0; i < 16; i++) {
  829                 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
  830                     0, i, &mpt->mpt_dev_page0[i].Header);
  831                 if (rv) {
  832                         return (-1);
  833                 }
  834                 if (mpt->verbose > 1) {
  835                         mpt_prt(mpt,
  836                             "SPI Target %d Device Page 0 Header: %x %x %x %x",
  837                             i, mpt->mpt_dev_page0[i].Header.PageVersion,
  838                             mpt->mpt_dev_page0[i].Header.PageLength,
  839                             mpt->mpt_dev_page0[i].Header.PageNumber,
  840                             mpt->mpt_dev_page0[i].Header.PageType);
  841                 }
  842 
  843                 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
  844                     1, i, &mpt->mpt_dev_page1[i].Header);
  845                 if (rv) {
  846                         return (-1);
  847                 }
  848                 if (mpt->verbose > 1) {
  849                         mpt_prt(mpt,
  850                             "SPI Target %d Device Page 1 Header: %x %x %x %x",
  851                             i, mpt->mpt_dev_page1[i].Header.PageVersion,
  852                             mpt->mpt_dev_page1[i].Header.PageLength,
  853                             mpt->mpt_dev_page1[i].Header.PageNumber,
  854                             mpt->mpt_dev_page1[i].Header.PageType);
  855                 }
  856         }
  857 
  858         /*
  859          * At this point, we don't *have* to fail. As long as we have
  860          * valid config header information, we can (barely) lurch
  861          * along.
  862          */
  863 
  864         rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header);
  865         mpt2host_config_page_scsi_port_0(&mpt->mpt_port_page0);
  866         if (rv) {
  867                 mpt_prt(mpt, "failed to read SPI Port Page 0");
  868         } else if (mpt->verbose > 1) {
  869                 mpt_prt(mpt,
  870                     "SPI Port Page 0: Capabilities %x PhysicalInterface %x",
  871                     mpt->mpt_port_page0.Capabilities,
  872                     mpt->mpt_port_page0.PhysicalInterface);
  873         }
  874 
  875         rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header);
  876         mpt2host_config_page_scsi_port_1(&mpt->mpt_port_page1);
  877         if (rv) {
  878                 mpt_prt(mpt, "failed to read SPI Port Page 1");
  879         } else if (mpt->verbose > 1) {
  880                 mpt_prt(mpt,
  881                     "SPI Port Page 1: Configuration %x OnBusTimerValue %x",
  882                     mpt->mpt_port_page1.Configuration,
  883                     mpt->mpt_port_page1.OnBusTimerValue);
  884         }
  885 
  886         rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header);
  887         mpt2host_config_page_scsi_port_2(&mpt->mpt_port_page2);
  888         if (rv) {
  889                 mpt_prt(mpt, "failed to read SPI Port Page 2");
  890         } else if (mpt->verbose > 1) {
  891                 mpt_prt(mpt,
  892                     "SPI Port Page 2: Flags %x Settings %x",
  893                     mpt->mpt_port_page2.PortFlags,
  894                     mpt->mpt_port_page2.PortSettings);
  895                 for (i = 0; i < 1; i++) {
  896                         mpt_prt(mpt,
  897                             "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x",
  898                             i, mpt->mpt_port_page2.DeviceSettings[i].Timeout,
  899                             mpt->mpt_port_page2.DeviceSettings[i].SyncFactor,
  900                             mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags);
  901                 }
  902         }
  903 
  904         for (i = 0; i < 16; i++) {
  905                 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header);
  906                 mpt2host_config_page_scsi_device_0(&mpt->mpt_dev_page0[i]);
  907                 if (rv) {
  908                         mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 0", i);
  909                         continue;
  910                 }
  911                 if (mpt->verbose > 1) {
  912                         mpt_prt(mpt,
  913                             "SPI Tgt %d Page 0: NParms %x Information %x",
  914                             i, mpt->mpt_dev_page0[i].NegotiatedParameters,
  915                             mpt->mpt_dev_page0[i].Information);
  916                 }
  917                 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header);
  918                 mpt2host_config_page_scsi_device_1(&mpt->mpt_dev_page1[i]);
  919                 if (rv) {
  920                         mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 1", i);
  921                         continue;
  922                 }
  923                 if (mpt->verbose > 1) {
  924                         mpt_prt(mpt,
  925                             "SPI Tgt %d Page 1: RParms %x Configuration %x",
  926                             i, mpt->mpt_dev_page1[i].RequestedParameters,
  927                             mpt->mpt_dev_page1[i].Configuration);
  928                 }
  929         }
  930         return (0);
  931 }
  932 
  933 /*
  934  * Validate SPI configuration information.
  935  *
  936  * In particular, validate SPI Port Page 1.
  937  */
  938 static int
  939 mpt_set_initial_config_spi(mpt_softc_t *mpt)
  940 {
  941         int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id;
  942 
  943         mpt->mpt_disc_enable = 0xffff;
  944         mpt->mpt_tag_enable = 0;
  945 
  946         if (mpt->mpt_port_page1.Configuration != pp1val) {
  947                 fCONFIG_PAGE_SCSI_PORT_1 tmp;
  948 
  949                 mpt_prt(mpt,
  950                     "SPI Port Page 1 Config value bad (%x)- should be %x",
  951                     mpt->mpt_port_page1.Configuration, pp1val);
  952                 tmp = mpt->mpt_port_page1;
  953                 tmp.Configuration = pp1val;
  954                 host2mpt_config_page_scsi_port_1(&tmp);
  955                 if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) {
  956                         return (-1);
  957                 }
  958                 if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) {
  959                         return (-1);
  960                 }
  961                 mpt2host_config_page_scsi_port_1(&tmp);
  962                 if (tmp.Configuration != pp1val) {
  963                         mpt_prt(mpt,
  964                             "failed to reset SPI Port Page 1 Config value");
  965                         return (-1);
  966                 }
  967                 mpt->mpt_port_page1 = tmp;
  968         }
  969 
  970         i = 0;
  971         for (i = 0; i < 16; i++) {
  972                 fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
  973 
  974                 tmp = mpt->mpt_dev_page1[i];
  975                 tmp.RequestedParameters = 0;
  976                 tmp.Configuration = 0;
  977                 if (mpt->verbose > 1) {
  978                         mpt_prt(mpt,
  979                             "Set Tgt %d SPI DevicePage 1 values to %x 0 %x",
  980                             i, tmp.RequestedParameters, tmp.Configuration);
  981                 }
  982                 host2mpt_config_page_scsi_device_1(&tmp);
  983                 if (mpt_write_cfg_page(mpt, i, &tmp.Header)) {
  984                         return (-1);
  985                 }
  986                 if (mpt_read_cfg_page(mpt, i, &tmp.Header)) {
  987                         return (-1);
  988                 }
  989                 mpt2host_config_page_scsi_device_1(&tmp);
  990                 mpt->mpt_dev_page1[i] = tmp;
  991                 if (mpt->verbose > 1) {
  992                         mpt_prt(mpt,
  993                             "SPI Tgt %d Page 1: RParm %x Configuration %x", i,
  994                             mpt->mpt_dev_page1[i].RequestedParameters,
  995                             mpt->mpt_dev_page1[i].Configuration);
  996                 }
  997         }
  998         return (0);
  999 }
 1000 
 1001 /*
 1002  * Enable IOC port
 1003  */
 1004 static int
 1005 mpt_send_port_enable(mpt_softc_t *mpt, int port)
 1006 {
 1007         int count;
 1008         request_t *req;
 1009         MSG_PORT_ENABLE *enable_req;
 1010 
 1011         req = mpt_get_request(mpt);
 1012 
 1013         enable_req = req->req_vbuf;
 1014         memset(enable_req, 0, sizeof *enable_req);
 1015 
 1016         enable_req->Function   = MPI_FUNCTION_PORT_ENABLE;
 1017         enable_req->MsgContext = htole32(req->index | 0x80000000);
 1018         enable_req->PortNumber = port;
 1019 
 1020         mpt_check_doorbell(mpt);
 1021         if (mpt->verbose > 1) {
 1022                 mpt_prt(mpt, "enabling port %d", port);
 1023         }
 1024         mpt_send_cmd(mpt, req);
 1025 
 1026         count = 0;
 1027         do {
 1028                 DELAY(500);
 1029                 mpt_intr(mpt);
 1030                 if (++count == 100000) {
 1031                         mpt_prt(mpt, "port enable timed out");
 1032                         return (-1);
 1033                 }
 1034         } while (req->debug == REQ_ON_CHIP);
 1035         mpt_free_request(mpt, req);
 1036         return (0);
 1037 }
 1038 
 1039 /*
 1040  * Enable/Disable asynchronous event reporting.
 1041  *
 1042  * NB: this is the first command we send via shared memory
 1043  * instead of the handshake register.
 1044  */
 1045 static int
 1046 mpt_send_event_request(mpt_softc_t *mpt, int onoff)
 1047 {
 1048         request_t *req;
 1049         MSG_EVENT_NOTIFY *enable_req;
 1050 
 1051         req = mpt_get_request(mpt);
 1052 
 1053         enable_req = req->req_vbuf;
 1054         memset(enable_req, 0, sizeof *enable_req);
 1055 
 1056         enable_req->Function   = MPI_FUNCTION_EVENT_NOTIFICATION;
 1057         enable_req->MsgContext = htole32(req->index | 0x80000000);
 1058         enable_req->Switch     = onoff;
 1059 
 1060         mpt_check_doorbell(mpt);
 1061         if (mpt->verbose > 1) {
 1062                 mpt_prt(mpt, "%sabling async events", onoff? "en" : "dis");
 1063         }
 1064         mpt_send_cmd(mpt, req);
 1065 
 1066         return (0);
 1067 }
 1068 
 1069 /*
 1070  * Un-mask the interrupts on the chip.
 1071  */
 1072 void
 1073 mpt_enable_ints(mpt_softc_t *mpt)
 1074 {
 1075         /* Unmask every thing except door bell int */
 1076         mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK);
 1077 }
 1078 
 1079 /*
 1080  * Mask the interrupts on the chip.
 1081  */
 1082 void
 1083 mpt_disable_ints(mpt_softc_t *mpt)
 1084 {
 1085         /* Mask all interrupts */
 1086         mpt_write(mpt, MPT_OFFSET_INTR_MASK,
 1087             MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK);
 1088 }
 1089 
 1090 /* (Re)Initialize the chip for use */
 1091 int
 1092 mpt_hw_init(mpt_softc_t *mpt)
 1093 {
 1094         u_int32_t       db;
 1095         int             try;
 1096 
 1097         /*
 1098          * Start by making sure we're not at FAULT or RESET state
 1099          */
 1100         for (try = 0; try < MPT_MAX_TRYS; try++) {
 1101 
 1102                 db = mpt_rd_db(mpt);
 1103 
 1104                 switch (MPT_STATE(db)) {
 1105                 case MPT_DB_STATE_READY:
 1106                         return (0);
 1107 
 1108                 default:
 1109                         /* if peer has already reset us, don't do it again! */
 1110                         if (MPT_WHO(db) == MPT_DB_INIT_PCIPEER)
 1111                                 return (0);
 1112                         /*FALLTHRU*/
 1113                 case MPT_DB_STATE_RESET:
 1114                 case MPT_DB_STATE_FAULT:
 1115                         if (mpt_reset(mpt) != MPT_OK) {
 1116                                 DELAY(10000);
 1117                                 continue;
 1118                         }
 1119                         break;
 1120                 }
 1121         }
 1122         return (EIO);
 1123 }
 1124 
 1125 int
 1126 mpt_init(mpt_softc_t *mpt, u_int32_t who)
 1127 {
 1128         int try;
 1129         MSG_IOC_FACTS_REPLY facts;
 1130         MSG_PORT_FACTS_REPLY pfp;
 1131         prop_dictionary_t dict;
 1132         uint32_t ini_id;
 1133         uint32_t pptr;
 1134         int val;
 1135 
 1136         /* Put all request buffers (back) on the free list */
 1137         SLIST_INIT(&mpt->request_free_list);
 1138         for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
 1139                 mpt_free_request(mpt, &mpt->request_pool[val]);
 1140         }
 1141 
 1142         if (mpt->verbose > 1) {
 1143                 mpt_prt(mpt, "doorbell req = %s",
 1144                     mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL)));
 1145         }
 1146 
 1147         /*
 1148          * Start by making sure we're not at FAULT or RESET state
 1149          */
 1150         if (mpt_hw_init(mpt) != 0)
 1151                 return (EIO);
 1152 
 1153         dict = device_properties(mpt->sc_dev);
 1154 
 1155         for (try = 0; try < MPT_MAX_TRYS; try++) {
 1156                 /*
 1157                  * No need to reset if the IOC is already in the READY state.
 1158                  */
 1159 
 1160                 if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
 1161                         mpt_prt(mpt, "mpt_get_iocfacts failed");
 1162                         continue;
 1163                 }
 1164                 mpt2host_iocfacts_reply(&facts);
 1165 
 1166                 if (mpt->verbose > 1) {
 1167                         mpt_prt(mpt,
 1168                             "IOCFACTS: GlobalCredits=%d BlockSize=%u "
 1169                             "Request Frame Size %u", facts.GlobalCredits,
 1170                             facts.BlockSize, facts.RequestFrameSize);
 1171                 }
 1172                 mpt->mpt_max_devices = facts.MaxDevices;
 1173                 mpt->mpt_global_credits = facts.GlobalCredits;
 1174                 mpt->request_frame_size = facts.RequestFrameSize;
 1175 
 1176                 if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
 1177                         mpt_prt(mpt, "mpt_get_portfacts failed");
 1178                         continue;
 1179                 }
 1180                 mpt2host_portfacts_reply(&pfp);
 1181 
 1182                 if (mpt->verbose > 1) {
 1183                         mpt_prt(mpt,
 1184                             "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d",
 1185                             pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID,
 1186                             pfp.MaxDevices);
 1187                 }
 1188 
 1189                 if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
 1190                         mpt_prt(mpt, "initiator role unsupported");
 1191                         return (ENXIO);
 1192                 }
 1193 
 1194                 switch (pfp.PortType) {
 1195                 case MPI_PORTFACTS_PORTTYPE_FC:
 1196                         mpt->is_fc = 1;
 1197                         mpt->mpt_max_devices = 255;
 1198                         break;
 1199                 case MPI_PORTFACTS_PORTTYPE_SCSI:
 1200                         mpt->is_scsi = 1;
 1201                         /* some SPI controllers (VMWare, Sun) lie */
 1202                         mpt->mpt_max_devices = 16;
 1203                         break;
 1204                 case MPI_PORTFACTS_PORTTYPE_SAS:
 1205                         mpt->is_sas = 1;
 1206                         break;
 1207                 default:
 1208                         mpt_prt(mpt, "Unsupported Port Type (%x)",
 1209                             pfp.PortType);
 1210                         return (ENXIO);
 1211                 }
 1212 
 1213                 if (!mpt->is_sas && !mpt->is_fc &&
 1214                     prop_dictionary_get_uint32(dict, "scsi-initiator-id", &ini_id))
 1215                         mpt->mpt_ini_id = ini_id;
 1216                 else
 1217                         mpt->mpt_ini_id = pfp.PortSCSIID;
 1218 
 1219                 if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
 1220                         mpt_prt(mpt, "mpt_send_ioc_init failed");
 1221                         continue;
 1222                 }
 1223 
 1224                 if (mpt->verbose > 1) {
 1225                         mpt_prt(mpt, "mpt_send_ioc_init ok");
 1226                 }
 1227 
 1228                 if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) {
 1229                         mpt_prt(mpt, "IOC failed to go to run state");
 1230                         continue;
 1231                 }
 1232                 if (mpt->verbose > 1) {
 1233                         mpt_prt(mpt, "IOC now at RUNSTATE");
 1234                 }
 1235 
 1236                 /*
 1237                  * Give it reply buffers
 1238                  *
 1239                  * Do *not* except global credits.
 1240                  */
 1241                 for (val = 0, pptr = mpt->reply_phys;
 1242                     (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE);
 1243                      pptr += MPT_REPLY_SIZE) {
 1244                         mpt_free_reply(mpt, pptr);
 1245                         if (++val == mpt->mpt_global_credits - 1)
 1246                                 break;
 1247                 }
 1248 
 1249                 /*
 1250                  * Enable asynchronous event reporting
 1251                  */
 1252                 mpt_send_event_request(mpt, 1);
 1253 
 1254 
 1255                 /*
 1256                  * Read set up initial configuration information
 1257                  * (SPI only for now)
 1258                  */
 1259 
 1260                 if (mpt->is_scsi) {
 1261                         if (mpt_read_config_info_spi(mpt)) {
 1262                                 return (EIO);
 1263                         }
 1264                         if (mpt_set_initial_config_spi(mpt)) {
 1265                                 return (EIO);
 1266                         }
 1267                 }
 1268 
 1269                 /*
 1270                  * Now enable the port
 1271                  */
 1272                 if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
 1273                         mpt_prt(mpt, "failed to enable port 0");
 1274                         continue;
 1275                 }
 1276 
 1277                 if (mpt->verbose > 1) {
 1278                         mpt_prt(mpt, "enabled port 0");
 1279                 }
 1280 
 1281                 /* Everything worked */
 1282                 break;
 1283         }
 1284 
 1285         if (try >= MPT_MAX_TRYS) {
 1286                 mpt_prt(mpt, "failed to initialize IOC");
 1287                 return (EIO);
 1288         }
 1289 
 1290         if (mpt->verbose > 1) {
 1291                 mpt_prt(mpt, "enabling interrupts");
 1292         }
 1293 
 1294         mpt_enable_ints(mpt);
 1295         return (0);
 1296 }
 1297 
 1298 /*
 1299  * Endian Conversion Functions- only used on Big Endian machines
 1300  */
 1301 #if     _BYTE_ORDER == _BIG_ENDIAN
 1302 void
 1303 mpt2host_sge_simple_union(SGE_SIMPLE_UNION *sge)
 1304 {
 1305 
 1306         MPT_2_HOST32(sge, FlagsLength);
 1307         MPT_2_HOST32(sge, _u.Address64.Low);
 1308         MPT_2_HOST32(sge, _u.Address64.High);
 1309 }
 1310 
 1311 void
 1312 mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY *rp)
 1313 {
 1314 
 1315         MPT_2_HOST16(rp, MsgVersion);
 1316 #if 0
 1317         MPT_2_HOST16(rp, HeaderVersion);
 1318 #endif
 1319         MPT_2_HOST32(rp, MsgContext);
 1320         MPT_2_HOST16(rp, IOCExceptions);
 1321         MPT_2_HOST16(rp, IOCStatus);
 1322         MPT_2_HOST32(rp, IOCLogInfo);
 1323         MPT_2_HOST16(rp, ReplyQueueDepth);
 1324         MPT_2_HOST16(rp, RequestFrameSize);
 1325         MPT_2_HOST16(rp, Reserved_0101_FWVersion);
 1326         MPT_2_HOST16(rp, ProductID);
 1327         MPT_2_HOST32(rp, CurrentHostMfaHighAddr);
 1328         MPT_2_HOST16(rp, GlobalCredits);
 1329         MPT_2_HOST32(rp, CurrentSenseBufferHighAddr);
 1330         MPT_2_HOST16(rp, CurReplyFrameSize);
 1331         MPT_2_HOST32(rp, FWImageSize);
 1332 #if 0
 1333         MPT_2_HOST32(rp, IOCCapabilities);
 1334 #endif
 1335         MPT_2_HOST32(rp, FWVersion.Word);
 1336 #if 0
 1337         MPT_2_HOST16(rp, HighPriorityQueueDepth);
 1338         MPT_2_HOST16(rp, Reserved2);
 1339         mpt2host_sge_simple_union(&rp->HostPageBufferSGE);
 1340         MPT_2_HOST32(rp, ReplyFifoHostSignalingAddr);
 1341 #endif
 1342 }
 1343 
 1344 void
 1345 mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY *pfp)
 1346 {
 1347 
 1348         MPT_2_HOST16(pfp, Reserved);
 1349         MPT_2_HOST16(pfp, Reserved1);
 1350         MPT_2_HOST32(pfp, MsgContext);
 1351         MPT_2_HOST16(pfp, Reserved2);
 1352         MPT_2_HOST16(pfp, IOCStatus);
 1353         MPT_2_HOST32(pfp, IOCLogInfo);
 1354         MPT_2_HOST16(pfp, MaxDevices);
 1355         MPT_2_HOST16(pfp, PortSCSIID);
 1356         MPT_2_HOST16(pfp, ProtocolFlags);
 1357         MPT_2_HOST16(pfp, MaxPostedCmdBuffers);
 1358         MPT_2_HOST16(pfp, MaxPersistentIDs);
 1359         MPT_2_HOST16(pfp, MaxLanBuckets);
 1360         MPT_2_HOST16(pfp, Reserved4);
 1361         MPT_2_HOST32(pfp, Reserved5);
 1362 }
 1363 
 1364 void
 1365 mpt2host_config_page_scsi_port_0(fCONFIG_PAGE_SCSI_PORT_0 *sp0)
 1366 {
 1367 
 1368         MPT_2_HOST32(sp0, Capabilities);
 1369         MPT_2_HOST32(sp0, PhysicalInterface);
 1370 }
 1371 
 1372 void
 1373 mpt2host_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
 1374 {
 1375 
 1376         MPT_2_HOST32(sp1, Configuration);
 1377         MPT_2_HOST32(sp1, OnBusTimerValue);
 1378 #if 0
 1379         MPT_2_HOST16(sp1, IDConfig);
 1380 #endif
 1381 }
 1382 
 1383 void
 1384 host2mpt_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
 1385 {
 1386 
 1387         HOST_2_MPT32(sp1, Configuration);
 1388         HOST_2_MPT32(sp1, OnBusTimerValue);
 1389 #if 0
 1390         HOST_2_MPT16(sp1, IDConfig);
 1391 #endif
 1392 }
 1393 
 1394 void
 1395 mpt2host_config_page_scsi_port_2(fCONFIG_PAGE_SCSI_PORT_2 *sp2)
 1396 {
 1397         int i;
 1398 
 1399         MPT_2_HOST32(sp2, PortFlags);
 1400         MPT_2_HOST32(sp2, PortSettings);
 1401         for (i = 0; i < sizeof(sp2->DeviceSettings) /
 1402             sizeof(*sp2->DeviceSettings); i++) {
 1403                 MPT_2_HOST16(sp2, DeviceSettings[i].DeviceFlags);
 1404         }
 1405 }
 1406 
 1407 void
 1408 mpt2host_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
 1409 {
 1410 
 1411         MPT_2_HOST32(sd0, NegotiatedParameters);
 1412         MPT_2_HOST32(sd0, Information);
 1413 }
 1414 
 1415 void
 1416 host2mpt_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
 1417 {
 1418 
 1419         HOST_2_MPT32(sd0, NegotiatedParameters);
 1420         HOST_2_MPT32(sd0, Information);
 1421 }
 1422 
 1423 void
 1424 mpt2host_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
 1425 {
 1426 
 1427         MPT_2_HOST32(sd1, RequestedParameters);
 1428         MPT_2_HOST32(sd1, Reserved);
 1429         MPT_2_HOST32(sd1, Configuration);
 1430 }
 1431 
 1432 void
 1433 host2mpt_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
 1434 {
 1435 
 1436         HOST_2_MPT32(sd1, RequestedParameters);
 1437         HOST_2_MPT32(sd1, Reserved);
 1438         HOST_2_MPT32(sd1, Configuration);
 1439 }
 1440 
 1441 void
 1442 mpt2host_config_page_fc_port_0(fCONFIG_PAGE_FC_PORT_0 *fp0)
 1443 {
 1444 
 1445         MPT_2_HOST32(fp0, Flags);
 1446         MPT_2_HOST32(fp0, PortIdentifier);
 1447         MPT_2_HOST32(fp0, WWNN.Low);
 1448         MPT_2_HOST32(fp0, WWNN.High);
 1449         MPT_2_HOST32(fp0, WWPN.Low);
 1450         MPT_2_HOST32(fp0, WWPN.High);
 1451         MPT_2_HOST32(fp0, SupportedServiceClass);
 1452         MPT_2_HOST32(fp0, SupportedSpeeds);
 1453         MPT_2_HOST32(fp0, CurrentSpeed);
 1454         MPT_2_HOST32(fp0, MaxFrameSize);
 1455         MPT_2_HOST32(fp0, FabricWWNN.Low);
 1456         MPT_2_HOST32(fp0, FabricWWNN.High);
 1457         MPT_2_HOST32(fp0, FabricWWPN.Low);
 1458         MPT_2_HOST32(fp0, FabricWWPN.High);
 1459         MPT_2_HOST32(fp0, DiscoveredPortsCount);
 1460         MPT_2_HOST32(fp0, MaxInitiators);
 1461 }
 1462 
 1463 void
 1464 mpt2host_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
 1465 {
 1466 
 1467         MPT_2_HOST32(fp1, Flags);
 1468         MPT_2_HOST32(fp1, NoSEEPROMWWNN.Low);
 1469         MPT_2_HOST32(fp1, NoSEEPROMWWNN.High);
 1470         MPT_2_HOST32(fp1, NoSEEPROMWWPN.Low);
 1471         MPT_2_HOST32(fp1, NoSEEPROMWWPN.High);
 1472 }
 1473 
 1474 void
 1475 host2mpt_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
 1476 {
 1477 
 1478         HOST_2_MPT32(fp1, Flags);
 1479         HOST_2_MPT32(fp1, NoSEEPROMWWNN.Low);
 1480         HOST_2_MPT32(fp1, NoSEEPROMWWNN.High);
 1481         HOST_2_MPT32(fp1, NoSEEPROMWWPN.Low);
 1482         HOST_2_MPT32(fp1, NoSEEPROMWWPN.High);
 1483 }
 1484 
 1485 void
 1486 mpt2host_config_page_raid_vol_0(fCONFIG_PAGE_RAID_VOL_0 *volp)
 1487 {
 1488         int i;
 1489 
 1490         MPT_2_HOST16(volp, VolumeStatus.Reserved);
 1491         MPT_2_HOST16(volp, VolumeSettings.Settings);
 1492         MPT_2_HOST32(volp, MaxLBA);
 1493 #if 0
 1494         MPT_2_HOST32(volp, MaxLBAHigh);
 1495 #endif
 1496         MPT_2_HOST32(volp, StripeSize);
 1497         MPT_2_HOST32(volp, Reserved2);
 1498         MPT_2_HOST32(volp, Reserved3);
 1499         for (i = 0; i < MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX; i++) {
 1500                 MPT_2_HOST16(volp, PhysDisk[i].Reserved);
 1501         }
 1502 }
 1503 
 1504 void
 1505 mpt2host_config_page_raid_phys_disk_0(fCONFIG_PAGE_RAID_PHYS_DISK_0 *rpd0)
 1506 {
 1507 
 1508         MPT_2_HOST32(rpd0, Reserved1);
 1509         MPT_2_HOST16(rpd0, PhysDiskStatus.Reserved);
 1510         MPT_2_HOST32(rpd0, MaxLBA);
 1511         MPT_2_HOST16(rpd0, ErrorData.Reserved);
 1512         MPT_2_HOST16(rpd0, ErrorData.ErrorCount);
 1513         MPT_2_HOST16(rpd0, ErrorData.SmartCount);
 1514 }
 1515 
 1516 void
 1517 mpt2host_config_page_ioc_2(fCONFIG_PAGE_IOC_2 *ioc2)
 1518 {
 1519         MPT_2_HOST32(ioc2, CapabilitiesFlags);
 1520 }
 1521 
 1522 #endif

Cache object: a7de2977d78f00150c094f57a027d9e9


[ 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.