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

Cache object: ee2a4a929b2928a684e9fc49d8570609


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