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

Cache object: c2a30243386325750e473c4b86c11576


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