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/twa/twa.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 /*-
    2  * Copyright (c) 2003-04 3ware, Inc.
    3  * Copyright (c) 2000 Michael Smith
    4  * Copyright (c) 2000 BSDi
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  *      $FreeBSD: releng/5.3/sys/dev/twa/twa.c 127746 2004-04-02 15:09:57Z des $
   29  */
   30 
   31 /*
   32  * 3ware driver for 9000 series storage controllers.
   33  *
   34  * Author: Vinod Kashyap
   35  */
   36 
   37 
   38 #include <dev/twa/twa_includes.h>
   39 
   40 #ifdef TWA_FLASH_FIRMWARE
   41 static int      twa_flash_firmware(struct twa_softc *sc);
   42 static int      twa_hard_reset(struct twa_softc *sc);
   43 #endif /* TWA_FLASH_FIRMWARE */
   44 
   45 static int      twa_init_ctlr(struct twa_softc *sc);
   46 static void     *twa_get_param(struct twa_softc *sc, int table_id,
   47                                         int parameter_id, size_t size,
   48                                         void (* callback)(struct twa_request *tr));
   49 static int      twa_set_param(struct twa_softc *sc, int table_id, int param_id,
   50                                         int param_size, void *data,
   51                                         void (* callback)(struct twa_request *tr));
   52 static int      twa_init_connection(struct twa_softc *sc, u_int16_t message_credits,
   53                                 u_int32_t set_features, u_int16_t current_fw_srl,
   54                                 u_int16_t current_fw_arch_id, u_int16_t current_fw_branch,
   55                                 u_int16_t current_fw_build, u_int16_t *fw_on_ctlr_srl,
   56                                 u_int16_t *fw_on_ctlr_arch_id, u_int16_t *fw_on_ctlr_branch,
   57                                 u_int16_t *fw_on_ctlr_build, u_int32_t *init_connect_result);
   58 
   59 static int      twa_wait_request(struct twa_request *req, u_int32_t timeout);
   60 static int      twa_immediate_request(struct twa_request *req, u_int32_t timeout);
   61 
   62 static int      twa_done(struct twa_softc *sc);
   63 static int      twa_drain_pending_queue(struct twa_softc *sc);
   64 static void     twa_drain_complete_queue(struct twa_softc *sc);
   65 static int      twa_wait_status(struct twa_softc *sc, u_int32_t status, u_int32_t timeout);
   66 static int      twa_drain_response_queue(struct twa_softc *sc);
   67 static int      twa_check_ctlr_state(struct twa_softc *sc, u_int32_t status_reg);
   68 static int      twa_soft_reset(struct twa_softc *sc);
   69 
   70 static void     twa_host_intr(struct twa_softc *sc);
   71 static void     twa_attention_intr(struct twa_softc *sc);
   72 static void     twa_command_intr(struct twa_softc *sc);
   73 
   74 static int      twa_fetch_aen(struct twa_softc *sc);
   75 static void     twa_aen_callback(struct twa_request *tr);
   76 static void     twa_enqueue_aen(struct twa_softc *sc, struct twa_command_header *cmd_hdr);
   77 static int      twa_drain_aen_queue(struct twa_softc *sc);
   78 static int      twa_find_aen(struct twa_softc *sc, u_int16_t aen_code);
   79 
   80 static void     twa_panic(struct twa_softc *sc, int8_t *reason);
   81 
   82 /*
   83  * Function name:       twa_setup
   84  * Description:         Initializes driver data structures for the controller.
   85  *
   86  * Input:               sc      -- ptr to per ctlr structure
   87  * Output:              None
   88  * Return value:        0       -- success
   89  *                      non-zero-- failure
   90  */
   91 int
   92 twa_setup(struct twa_softc *sc)
   93 {
   94         struct twa_event_packet *aen_queue;
   95         int                     error = 0;
   96         int                     i;
   97 
   98         twa_dbg_dprint_enter(3, sc);
   99 
  100         /* Initialize request queues. */
  101         twa_initq_free(sc);
  102         twa_initq_busy(sc);
  103         twa_initq_pending(sc);
  104         twa_initq_complete(sc);
  105 
  106         if (twa_alloc_req_pkts(sc, TWA_Q_LENGTH)) {
  107                 twa_printf(sc, "Failed to allocate request packets.\n");
  108                 return(ENOMEM);
  109         }
  110 
  111         /* Allocate memory for the AEN queue. */
  112         if ((aen_queue = malloc(sizeof(struct twa_event_packet) * TWA_Q_LENGTH,
  113                                         M_DEVBUF, M_WAITOK)) == NULL) {
  114                 /* 
  115                  * This should not cause us to return error.  We will only be
  116                  * unable to support AEN's.  But then, we will have to check
  117                  * time and again to see if we can support AEN's, if we
  118                  * continue.  So, we will just return error.
  119                  */
  120                 twa_printf(sc, "Could not allocate memory for AEN queue.\n");
  121                 return(ENOMEM); /* any unfreed memory will be freed by twa_free */
  122         }
  123         /* Initialize the aen queue. */
  124         bzero(aen_queue, sizeof(struct twa_event_packet) * TWA_Q_LENGTH);
  125         for (i = 0; i < TWA_Q_LENGTH; i++)
  126                 sc->twa_aen_queue[i] = &(aen_queue[i]);
  127 
  128         /*
  129          * Disable interrupts from the card.
  130          * Interrupts will be enabled back in twa_intrhook.
  131          */
  132         twa_disable_interrupts(sc);
  133 
  134         /* Initialize the controller. */
  135         if ((error = twa_init_ctlr(sc))) {
  136                 /* Soft reset the controller, and try one more time. */
  137                 twa_printf(sc, "Controller initialization failed. Retrying...\n");
  138                 if ((error = twa_soft_reset(sc)))
  139                         twa_printf(sc, "Controller soft reset failed.\n");
  140                 else
  141                         error = twa_init_ctlr(sc);
  142         }
  143         return(error);
  144 }
  145 
  146 #ifdef TWA_FLASH_FIRMWARE
  147 /*
  148  * Function name:       twa_flash_firmware
  149  * Description:         Flashes bundled firmware image onto controller.
  150  *
  151  * Input:               sc      -- ptr to per ctlr structure
  152  * Output:              None
  153  * Return value:        0       -- success
  154  *                      non-zero-- failure
  155  */
  156 static int
  157 twa_flash_firmware(struct twa_softc *sc)
  158 {
  159         struct twa_request                      *tr;
  160         struct twa_command_download_firmware    *cmd;
  161         u_int32_t                               fw_img_chunk_size;
  162         u_int32_t                               this_chunk_size = 0;
  163         u_int32_t                               remaining_img_size = 0;
  164         int                                     error;
  165         int                                     i;
  166 
  167         if ((tr = twa_get_request(sc)) == NULL) {
  168                 /* No free request packets available.  Can't proceed. */
  169                 error = EIO;
  170                 goto out;
  171         }
  172         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
  173         /* Allocate sufficient memory to hold a chunk of the firmware image. */
  174         fw_img_chunk_size = ((twa_fw_img_size/NUM_FW_IMAGE_CHUNKS) + 511) & ~511;
  175         if ((tr->tr_data = malloc(fw_img_chunk_size, M_DEVBUF, M_WAITOK)) == NULL) {
  176                 twa_printf (sc, "Could not allocate memory for firmware image.\n"); 
  177                 error = ENOMEM;
  178                 goto out;
  179         }
  180         remaining_img_size = twa_fw_img_size;
  181         cmd = &(tr->tr_command->command.cmd_pkt_7k.download_fw);
  182 
  183         for (i = 0; i < NUM_FW_IMAGE_CHUNKS; i++) {
  184                 /* Build a cmd pkt for downloading firmware. */
  185                 bzero(tr->tr_command, sizeof(struct twa_command_packet));
  186 
  187                 tr->tr_command->cmd_hdr.header_desc.size_header = 128;
  188         
  189                 cmd->opcode = TWA_OP_DOWNLOAD_FIRMWARE;
  190                 cmd->sgl_offset = 2;/* offset in dwords, to the beginning of sg list */
  191                 cmd->size = 2;  /* this field will be updated at data map time */
  192                 cmd->request_id = tr->tr_request_id;
  193                 cmd->unit = 0;
  194                 cmd->status = 0;
  195                 cmd->flags = 0;
  196                 cmd->param = 8; /* prom image */
  197 
  198                 if (i != (NUM_FW_IMAGE_CHUNKS - 1))
  199                         this_chunk_size = fw_img_chunk_size;
  200                 else     /* last chunk */
  201                         this_chunk_size = remaining_img_size;
  202         
  203                 remaining_img_size -= this_chunk_size;
  204                 bcopy(twa_fw_img + (i * fw_img_chunk_size),
  205                                         tr->tr_data, this_chunk_size);
  206 
  207                 /*
  208                  * The next line will effect only the last chunk.
  209                  */
  210                 tr->tr_length = (this_chunk_size + 511) & ~511;
  211 
  212                 tr->tr_flags |= TWA_CMD_DATA_OUT;
  213 
  214                 error = twa_immediate_request(tr, TWA_REQUEST_TIMEOUT_PERIOD);
  215                 if (error) {
  216                         twa_printf(sc, "Firmware flash request could not be posted. error = 0x%x\n",
  217                                                                         error);
  218                         if (error == ETIMEDOUT)
  219                                 return(error); /* clean-up done by twa_immediate_request */
  220                         break;
  221                 }
  222                 error = cmd->status;
  223                 if (i != (NUM_FW_IMAGE_CHUNKS - 1)) {
  224                         if ((error = tr->tr_command->cmd_hdr.status_block.error) != TWA_ERROR_MORE_DATA) {
  225                                 twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
  226                                         cmd->opcode,
  227                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
  228                                         error,
  229                                         twa_find_msg_string(twa_error_table, error),
  230                                         tr->tr_command->cmd_hdr.err_specific_desc);
  231                                 twa_printf(sc, "Firmware flash request failed. Intermediate error = 0x%x, i = %x\n",
  232                                                         cmd->status, i);
  233                                 /* Hard reset the controller, so that it doesn't wait for the remaining chunks. */
  234                                 twa_hard_reset(sc);
  235                                 break;
  236                         }
  237                 } else   /* last chunk */
  238                         if (error) {
  239                                 twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
  240                                         cmd->opcode,
  241                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
  242                                         tr->tr_command->cmd_hdr.status_block.error,
  243                                         twa_find_msg_string(twa_error_table,
  244                                                 tr->tr_command->cmd_hdr.status_block.error),
  245                                         tr->tr_command->cmd_hdr.err_specific_desc);
  246                                 twa_printf(sc, "Firmware flash request failed. error = 0x%x\n", error);
  247                                 /* Hard reset the controller, so that it doesn't wait for more chunks. */
  248                                 twa_hard_reset(sc);
  249                         }
  250         } /* for */
  251 
  252         if (tr->tr_data)
  253                 free(tr->tr_data, M_DEVBUF);
  254 out:
  255         if (tr)
  256                 twa_release_request(tr);
  257         return(error);
  258 }
  259 
  260 
  261 /*
  262  * Function name:       twa_hard_reset
  263  * Description:         Hard reset the controller.
  264  *
  265  * Input:               sc      -- ptr to per ctlr structure
  266  * Output:              None
  267  * Return value:        0       -- success
  268  *                      non-zero-- failure
  269  */
  270 static int
  271 twa_hard_reset(struct twa_softc *sc)
  272 {
  273         struct twa_request                      *tr;
  274         struct twa_command_reset_firmware       *cmd;
  275         int                                     error;
  276 
  277         if ((tr = twa_get_request(sc)) == NULL)
  278                 return(EIO);
  279         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
  280         /* Build a cmd pkt for sending down the hard reset command. */
  281         tr->tr_command->cmd_hdr.header_desc.size_header = 128;
  282         
  283         cmd = &(tr->tr_command->command.cmd_pkt_7k.reset_fw);
  284         cmd->opcode = TWA_OP_RESET_FIRMWARE;
  285         cmd->size = 2;  /* this field will be updated at data map time */
  286         cmd->request_id = tr->tr_request_id;
  287         cmd->unit = 0;
  288         cmd->status = 0;
  289         cmd->flags = 0;
  290         cmd->param = 0; /* don't reload FPGA logic */
  291 
  292         tr->tr_data = NULL;
  293         tr->tr_length = 0;
  294 
  295         error = twa_immediate_request(tr, TWA_REQUEST_TIMEOUT_PERIOD);
  296         if (error) {
  297                 twa_printf(sc, "Hard reset request could not be posted. error = 0x%x\n",
  298                                                                 error);
  299                 if (error == ETIMEDOUT)
  300                         return(error); /* clean-up done by twa_immediate_request */
  301                 goto out;
  302         }
  303         if ((error = cmd->status)) {
  304                 twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
  305                                         cmd->opcode,
  306                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
  307                                         tr->tr_command->cmd_hdr.status_block.error,
  308                                         twa_find_msg_string(twa_error_table,
  309                                                 tr->tr_command->cmd_hdr.status_block.error),
  310                                         tr->tr_command->cmd_hdr.err_specific_desc);
  311                 twa_printf(sc, "Hard reset request failed. error = 0x%x\n", error);
  312         }
  313 
  314 out:
  315         if (tr)
  316                 twa_release_request(tr);
  317         return(error);
  318 }
  319 
  320 #endif /* TWA_FLASH_FIRMWARE */
  321 
  322 /*
  323  * Function name:       twa_init_ctlr
  324  * Description:         Establishes a logical connection with the controller.
  325  *                      If bundled with firmware, determines whether or not
  326  *                      to flash firmware, based on arch_id, fw SRL (Spec.
  327  *                      Revision Level), branch & build #'s.  Also determines
  328  *                      whether or not the driver is compatible with the
  329  *                      firmware on the controller, before proceeding to work
  330  *                      with it.
  331  *
  332  * Input:               sc      -- ptr to per ctlr structure
  333  * Output:              None
  334  * Return value:        0       -- success
  335  *                      non-zero-- failure
  336  */
  337 static int
  338 twa_init_ctlr(struct twa_softc *sc)
  339 {
  340         u_int16_t       fw_on_ctlr_srl = 0;
  341         u_int16_t       fw_on_ctlr_arch_id = 0;
  342         u_int16_t       fw_on_ctlr_branch = 0;
  343         u_int16_t       fw_on_ctlr_build = 0;
  344         u_int32_t       init_connect_result = 0;
  345         int             error = 0;
  346 #ifdef TWA_FLASH_FIRMWARE
  347         int8_t          fw_flashed = FALSE;
  348         int8_t          fw_flash_failed = FALSE;
  349 #endif /* TWA_FLASH_FIRMWARE */
  350 
  351         twa_dbg_dprint_enter(3, sc);
  352 
  353         /* Wait for the controller to become ready. */
  354         if (twa_wait_status(sc, TWA_STATUS_MICROCONTROLLER_READY,
  355                                         TWA_REQUEST_TIMEOUT_PERIOD)) {
  356                 twa_printf(sc, "Microcontroller not ready.\n");
  357                 return(ENXIO);
  358         }
  359         /* Drain the response queue. */
  360         if (twa_drain_response_queue(sc)) {
  361                 twa_printf(sc, "Can't drain response queue.\n");
  362                 return(1);
  363         }
  364         /* Establish a logical connection with the controller. */
  365         if ((error = twa_init_connection(sc, TWA_INIT_MESSAGE_CREDITS,
  366                         TWA_EXTENDED_INIT_CONNECT, TWA_CURRENT_FW_SRL,
  367                         TWA_9000_ARCH_ID, TWA_CURRENT_FW_BRANCH,
  368                         TWA_CURRENT_FW_BUILD, &fw_on_ctlr_srl,
  369                         &fw_on_ctlr_arch_id, &fw_on_ctlr_branch,
  370                         &fw_on_ctlr_build, &init_connect_result))) {
  371                 twa_printf(sc, "Can't initialize connection in current mode.\n");
  372                 return(error);
  373         }
  374 
  375 #ifdef TWA_FLASH_FIRMWARE
  376 
  377         if ((init_connect_result & TWA_BUNDLED_FW_SAFE_TO_FLASH) &&
  378                 (init_connect_result & TWA_CTLR_FW_RECOMMENDS_FLASH)) {
  379                 /*
  380                  * The bundled firmware is safe to flash, and the firmware
  381                  * on the controller recommends a flash.  So, flash!
  382                  */
  383                 twa_printf(sc, "Flashing bundled firmware...\n");
  384                 if ((error = twa_flash_firmware(sc))) {
  385                         fw_flash_failed = TRUE;
  386                         twa_printf(sc, "Unable to flash bundled firmware.\n");
  387                         twa_printf(sc, "Will see if possible to work with firmware on controller...\n");
  388                 } else {
  389                         twa_printf(sc, "Successfully flashed bundled firmware.\n");
  390                         fw_flashed = TRUE;
  391                 }
  392         }
  393 
  394         if (fw_flashed) {
  395                 /* The firmware was flashed.  Have the new image loaded */
  396                 error = twa_hard_reset(sc);
  397                 if (error)
  398                         twa_printf(sc, "Could not reset controller after flash!\n");
  399                 else    /* Go through initialization again. */
  400                         error = twa_init_ctlr(sc);
  401                 /*
  402                  * If hard reset of controller failed, we need to return.
  403                  * Otherwise, the above recursive call to twa_init_ctlr will
  404                  * have completed the rest of the initialization (starting
  405                  * from twa_drain_aen_queue below).  Don't do it again.
  406                  * Just return.
  407                  */
  408                 return(error);
  409         } else
  410 #endif /* TWA_FLASH_FIRMWARE */
  411         {
  412                 /*
  413                  * Either we are not bundled with a firmware image, or
  414                  * the bundled firmware is not safe to flash,
  415                  * or flash failed for some reason.  See if we can at
  416                  * least work with the firmware on the controller in the
  417                  * current mode.
  418                  */
  419                 if (init_connect_result & TWA_CTLR_FW_COMPATIBLE) {
  420                         /* Yes, we can.  Make note of the operating mode. */
  421                         sc->working_srl = TWA_CURRENT_FW_SRL;
  422                         sc->working_branch = TWA_CURRENT_FW_BRANCH;
  423                         sc->working_build = TWA_CURRENT_FW_BUILD;
  424                 } else {
  425                         /*
  426                          * No, we can't.  See if we can at least work with
  427                          * it in the base mode.  We should never come here
  428                          * if firmware has just been flashed.
  429                          */
  430                         twa_printf(sc, "Driver/Firmware mismatch.  Negotiating for base level...\n");
  431                         if ((error = twa_init_connection(sc, TWA_INIT_MESSAGE_CREDITS,
  432                                         TWA_EXTENDED_INIT_CONNECT, TWA_BASE_FW_SRL,
  433                                         TWA_9000_ARCH_ID, TWA_BASE_FW_BRANCH,
  434                                         TWA_BASE_FW_BUILD, &fw_on_ctlr_srl,
  435                                         &fw_on_ctlr_arch_id, &fw_on_ctlr_branch,
  436                                         &fw_on_ctlr_build, &init_connect_result))) {
  437                                 twa_printf(sc, "Can't initialize connection in base mode.\n");
  438                                 return(error);
  439                         }
  440                         if (!(init_connect_result & TWA_CTLR_FW_COMPATIBLE)) {
  441                                 /*
  442                                  * The firmware on the controller is not even
  443                                  * compatible with our base mode.  We cannot
  444                                  * work with it.  Bail...
  445                                  */
  446                                 twa_printf(sc, "Incompatible firmware on controller\n");
  447 #ifdef TWA_FLASH_FIRMWARE
  448                                 if (fw_flash_failed)
  449                                         twa_printf(sc, "...and could not flash bundled firmware.\n");
  450                                 else
  451                                         twa_printf(sc, "...and bundled firmware not safe to flash.\n");
  452 #endif /* TWA_FLASH_FIRMWARE */
  453                                 return(1);
  454                         }
  455                         /* We can work with this firmware, but only in base mode. */
  456                         sc->working_srl = TWA_BASE_FW_SRL;
  457                         sc->working_branch = TWA_BASE_FW_BRANCH;
  458                         sc->working_build = TWA_BASE_FW_BUILD;
  459                         sc->twa_operating_mode = TWA_BASE_MODE;
  460                 }
  461         }
  462 
  463         /* Drain the AEN queue */
  464         if (twa_drain_aen_queue(sc)) {
  465                 /* 
  466                  * We will just print that we couldn't drain the AEN queue.
  467                  * There's no need to bail out.
  468                  */
  469                 twa_printf(sc, "Can't drain AEN queue.\n");
  470         }
  471 
  472         /* Set controller state to initialized. */
  473         sc->twa_state &= ~TWA_STATE_SHUTDOWN;
  474 
  475         twa_dbg_dprint_exit(3, sc);
  476         return(0);
  477 }
  478 
  479 
  480 /*
  481  * Function name:       twa_deinit_ctlr
  482  * Description:         Close logical connection with the controller.
  483  *
  484  * Input:               sc      -- ptr to per ctlr structure
  485  * Output:              None
  486  * Return value:        0       -- success
  487  *                      non-zero-- failure
  488  */
  489 int
  490 twa_deinit_ctlr(struct twa_softc *sc)
  491 {
  492         /*
  493          * Mark the controller as shutting down,
  494          * and disable any further interrupts.
  495          */
  496         sc->twa_state |= TWA_STATE_SHUTDOWN;
  497         twa_disable_interrupts(sc);
  498 
  499         /* Let the controller know that we are going down. */
  500         return(twa_init_connection(sc, TWA_SHUTDOWN_MESSAGE_CREDITS,
  501                                         0, 0, 0, 0, 0,
  502                                         NULL, NULL, NULL, NULL, NULL));
  503 }
  504 
  505 
  506 /*
  507  * Function name:       twa_interrupt
  508  * Description:         Interrupt handler.  Determines the kind of interrupt,
  509  *                      and calls the appropriate handler.
  510  *
  511  * Input:               sc      -- ptr to per ctlr structure
  512  * Output:              None
  513  * Return value:        None
  514  */
  515 void
  516 twa_interrupt(struct twa_softc *sc)
  517 {
  518         u_int32_t       status_reg;
  519 
  520         twa_dbg_dprint_enter(5, sc);
  521 
  522         /* Collect current interrupt status. */
  523         status_reg = TWA_READ_STATUS_REGISTER(sc);
  524         if (twa_check_ctlr_state(sc, status_reg))
  525                 return;
  526 
  527         /* Dispatch based on the kind of interrupt. */
  528         if (status_reg & TWA_STATUS_HOST_INTERRUPT)
  529                 twa_host_intr(sc);
  530         if (status_reg & TWA_STATUS_ATTENTION_INTERRUPT)
  531                 twa_attention_intr(sc);
  532         if (status_reg & TWA_STATUS_COMMAND_INTERRUPT)
  533                 twa_command_intr(sc);
  534         if (status_reg & TWA_STATUS_RESPONSE_INTERRUPT)
  535                 twa_done(sc);
  536 }
  537 
  538 
  539 /*
  540  * Function name:       twa_ioctl
  541  * Description:         ioctl handler.
  542  *
  543  * Input:               sc      -- ptr to per ctlr structure
  544  *                      cmd     -- ioctl cmd
  545  *                      buf     -- ptr to buffer in kernel memory, which is
  546  *                                 a copy of the input buffer in user-space
  547  * Output:              buf     -- ptr to buffer in kernel memory, which will
  548  *                                 be copied of the output buffer in user-space
  549  * Return value:        0       -- success
  550  *                      non-zero-- failure
  551  */
  552 int
  553 twa_ioctl(struct twa_softc *sc, int cmd, void *buf)
  554 {
  555         struct twa_ioctl_9k     *user_buf = (struct twa_ioctl_9k *)buf;
  556         struct twa_event_packet event_buf;
  557         int32_t                 event_index;
  558         int32_t                 start_index;
  559         int                     s;
  560         int                     error = 0;
  561                 
  562         switch (cmd) {
  563         case TWA_IOCTL_FIRMWARE_PASS_THROUGH:
  564         {
  565                 struct twa_command_packet       *cmdpkt;
  566                 struct twa_request              *tr;
  567                 u_int32_t                       data_buf_size_adjusted;
  568 
  569 
  570                 twa_dbg_dprint(2, sc, "Firmware PassThru");
  571 
  572                 /* Get a request packet */
  573                 while ((tr = twa_get_request(sc)) == NULL)
  574                         /*
  575                          * No free request packets available.  Sleep until
  576                          * one becomes available.
  577                          */
  578                         tsleep(&(sc->twa_wait_timeout), PPAUSE, "twioctl", hz);
  579 
  580                 /*
  581                  * Make sure that the data buffer sent to firmware is a 
  582                  * 512 byte multiple in size.
  583                  */
  584                 data_buf_size_adjusted = (user_buf->twa_drvr_pkt.buffer_length + 511) & ~511;
  585                 if ((tr->tr_length = data_buf_size_adjusted)) {
  586                         if ((tr->tr_data = malloc(data_buf_size_adjusted, M_DEVBUF, M_WAITOK)) == NULL) {
  587                                 twa_printf(sc, "Could not alloc mem for fw_passthru data_buf.\n");
  588                                 error = ENOMEM;
  589                                 goto fw_passthru_done;
  590                         }
  591                         /* Copy the payload. */
  592                         if ((error = copyin((void *) (user_buf->pdata), 
  593                                         (void *) (tr->tr_data),
  594                                         user_buf->twa_drvr_pkt.buffer_length)) != 0) {
  595                                 twa_printf (sc, "Could not copyin fw_passthru data_buf.\n"); 
  596                                 goto fw_passthru_done;
  597                         }
  598                         tr->tr_flags |= TWA_CMD_DATA_IN | TWA_CMD_DATA_OUT;
  599                 }
  600                 tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_IOCTL;
  601                 cmdpkt = tr->tr_command;
  602 
  603                 /* Copy the command packet. */
  604                 bcopy(&(user_buf->twa_cmd_pkt), cmdpkt,
  605                                         sizeof(struct twa_command_packet));
  606                 cmdpkt->command.cmd_pkt_7k.generic.request_id = tr->tr_request_id;
  607 
  608                 twa_dbg_dprint(3, sc, "cmd_pkt_7k = %x %x %x %x %x %x %x",
  609                                         cmdpkt->command.cmd_pkt_7k.generic.opcode,
  610                                         cmdpkt->command.cmd_pkt_7k.generic.sgl_offset,
  611                                         cmdpkt->command.cmd_pkt_7k.generic.size,
  612                                         cmdpkt->command.cmd_pkt_7k.generic.request_id,
  613                                         cmdpkt->command.cmd_pkt_7k.generic.unit,
  614                                         cmdpkt->command.cmd_pkt_7k.generic.status,
  615                                         cmdpkt->command.cmd_pkt_7k.generic.flags);
  616 
  617                 /* Send down the request, and wait for it to complete. */
  618                 if ((error = twa_wait_request(tr, TWA_REQUEST_TIMEOUT_PERIOD))) {
  619                         twa_printf(sc, "fw_passthru request failed. error = 0x%x\n", error);
  620                         if (error == ETIMEDOUT)
  621                                 break; /* clean-up done by twa_wait_request */
  622                         goto fw_passthru_done;
  623                 }
  624 
  625                 /* Copy the command packet back into user space. */
  626                 bcopy(cmdpkt, &(user_buf->twa_cmd_pkt),
  627                                         sizeof(struct twa_command_packet));
  628         
  629                 /* If there was a payload, copy it back too. */
  630                 if (tr->tr_length)
  631                         error = copyout(tr->tr_data, user_buf->pdata,
  632                                         user_buf->twa_drvr_pkt.buffer_length);
  633 
  634 fw_passthru_done:
  635                 /* Free resources. */
  636                 if (tr->tr_data)
  637                         free(tr->tr_data, M_DEVBUF);
  638                 if (tr)
  639                         twa_release_request(tr);
  640                 break;
  641         }
  642 
  643 
  644         case TWA_IOCTL_SCAN_BUS:
  645                 /* Request CAM for a bus scan. */
  646                 twa_request_bus_scan(sc);
  647                 break;
  648 
  649 
  650         case TWA_IOCTL_GET_FIRST_EVENT:
  651                 twa_dbg_dprint(3, sc, "Get First Event");
  652 
  653                 if (sc->twa_aen_queue_wrapped) {
  654                         if (sc->twa_aen_queue_overflow) {
  655                                 /*
  656                                  * The aen queue has wrapped, even before some
  657                                  * events have been retrieved.  Let the caller
  658                                  * know that he missed out on some AEN's.
  659                                  */
  660                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_OVERFLOW;
  661                                 sc->twa_aen_queue_overflow = FALSE;
  662                         } else
  663                                 user_buf->twa_drvr_pkt.status = 0;
  664                         event_index = sc->twa_aen_head;
  665                 } else {
  666                         if (sc->twa_aen_head == sc->twa_aen_tail) {
  667                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
  668                                 break;
  669                         }
  670                         user_buf->twa_drvr_pkt.status = 0;
  671                         event_index = sc->twa_aen_tail; /* = 0 */
  672                 }
  673                 if ((error = copyout(sc->twa_aen_queue[event_index], user_buf->pdata,
  674                                         sizeof(struct twa_event_packet))) != 0)
  675                         twa_printf(sc, "get_first: Could not copyout to event_buf. error = %x\n", error);
  676                 (sc->twa_aen_queue[event_index])->retrieved = TWA_AEN_RETRIEVED;
  677                 break;
  678 
  679 
  680         case TWA_IOCTL_GET_LAST_EVENT:
  681                 twa_dbg_dprint(3, sc, "Get Last Event");
  682 
  683                 if (sc->twa_aen_queue_wrapped) {
  684                         if (sc->twa_aen_queue_overflow) {
  685                                 /*
  686                                  * The aen queue has wrapped, even before some
  687                                  * events have been retrieved.  Let the caller
  688                                  * know that he missed out on some AEN's.
  689                                  */
  690                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_OVERFLOW;
  691                                 sc->twa_aen_queue_overflow = FALSE;
  692                         } else
  693                                 user_buf->twa_drvr_pkt.status = 0;
  694                 } else {
  695                         if (sc->twa_aen_head == sc->twa_aen_tail) {
  696                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
  697                                 break;
  698                         }
  699                         user_buf->twa_drvr_pkt.status = 0;
  700                 }
  701                 event_index = (sc->twa_aen_head - 1 + TWA_Q_LENGTH) % TWA_Q_LENGTH;
  702                 if ((error = copyout(sc->twa_aen_queue[event_index], user_buf->pdata,
  703                                         sizeof(struct twa_event_packet))) != 0)
  704                         twa_printf(sc, "get_last: Could not copyout to event_buf. error = %x\n", error);
  705                 (sc->twa_aen_queue[event_index])->retrieved = TWA_AEN_RETRIEVED;
  706                 break;
  707 
  708 
  709         case TWA_IOCTL_GET_NEXT_EVENT:
  710                 twa_dbg_dprint(3, sc, "Get Next Event");
  711 
  712                 user_buf->twa_drvr_pkt.status = 0;
  713                 if (sc->twa_aen_queue_wrapped) {
  714                         twa_dbg_dprint(3, sc, "Get Next Event: wrapped");
  715                         if (sc->twa_aen_queue_overflow) {
  716                                 /*
  717                                  * The aen queue has wrapped, even before some
  718                                  * events have been retrieved.  Let the caller
  719                                  * know that he missed out on some AEN's.
  720                                  */
  721                                 twa_dbg_dprint(2, sc, "Get Next Event: overflow");
  722                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_OVERFLOW;
  723                                 sc->twa_aen_queue_overflow = FALSE;
  724                         }
  725                         start_index = sc->twa_aen_head;
  726                 } else {
  727                         if (sc->twa_aen_head == sc->twa_aen_tail) {
  728                                 twa_dbg_dprint(3, sc, "Get Next Event: empty queue");
  729                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
  730                                 break;
  731                         }
  732                         start_index = sc->twa_aen_tail; /* = 0 */
  733                 }
  734                 if ((error = copyin(user_buf->pdata, &event_buf,
  735                                 sizeof(struct twa_event_packet))) != 0)
  736                         twa_printf(sc, "get_next: Could not copyin event_buf.\n");
  737 
  738                 event_index = (start_index + event_buf.sequence_id -
  739                                 (sc->twa_aen_queue[start_index])->sequence_id + 1)
  740                                 % TWA_Q_LENGTH;
  741 
  742                 twa_dbg_dprint(3, sc, "Get Next Event: si = %x, ei = %x, ebsi = %x, sisi = %x, eisi = %x",
  743                                 start_index, event_index, event_buf.sequence_id,
  744                                 (sc->twa_aen_queue[start_index])->sequence_id,
  745                                 (sc->twa_aen_queue[event_index])->sequence_id);
  746 
  747                 if (! ((sc->twa_aen_queue[event_index])->sequence_id >
  748                                                 event_buf.sequence_id)) {
  749                         if (user_buf->twa_drvr_pkt.status == TWA_ERROR_AEN_OVERFLOW)
  750                                 sc->twa_aen_queue_overflow = TRUE; /* so we report the overflow next time */
  751                         user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
  752                         break;
  753                 }
  754                 if ((error = copyout(sc->twa_aen_queue[event_index], user_buf->pdata, 
  755                                         sizeof(struct twa_event_packet))) != 0)
  756                         twa_printf(sc, "get_next: Could not copyout to event_buf. error = %x\n", error);
  757 
  758                 (sc->twa_aen_queue[event_index])->retrieved = TWA_AEN_RETRIEVED;
  759                 break;
  760 
  761 
  762         case TWA_IOCTL_GET_PREVIOUS_EVENT:
  763                 twa_dbg_dprint(3, sc, "Get Previous Event");
  764 
  765                 user_buf->twa_drvr_pkt.status = 0;
  766                 if (sc->twa_aen_queue_wrapped) {
  767                         if (sc->twa_aen_queue_overflow) {
  768                                 /*
  769                                  * The aen queue has wrapped, even before some
  770                                  * events have been retrieved.  Let the caller
  771                                  * know that he missed out on some AEN's.
  772                                  */
  773                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_OVERFLOW;
  774                                 sc->twa_aen_queue_overflow = FALSE;
  775                         }
  776                         start_index = sc->twa_aen_head;
  777                 } else {
  778                         if (sc->twa_aen_head == sc->twa_aen_tail) {
  779                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
  780                                 break;
  781                         }
  782                         start_index = sc->twa_aen_tail; /* = 0 */
  783                 }
  784                 if ((error = copyin(user_buf->pdata, &event_buf,
  785                                 sizeof(struct twa_event_packet))) != 0)
  786                         twa_printf(sc, "get_previous: Could not copyin event_buf.\n");
  787 
  788                 event_index = (start_index + event_buf.sequence_id -
  789                         (sc->twa_aen_queue[start_index])->sequence_id - 1) % TWA_Q_LENGTH;
  790                 if (! ((sc->twa_aen_queue[event_index])->sequence_id < event_buf.sequence_id)) {
  791                         if (user_buf->twa_drvr_pkt.status == TWA_ERROR_AEN_OVERFLOW)
  792                                 sc->twa_aen_queue_overflow = TRUE; /* so we report the overflow next time */
  793                         user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
  794                         break;
  795                 }
  796                 if ((error = copyout(sc->twa_aen_queue [event_index], user_buf->pdata,
  797                                         sizeof(struct twa_event_packet))) != 0)
  798                         twa_printf(sc, "get_previous: Could not copyout to event_buf. error = %x\n", error);
  799 
  800                 (sc->twa_aen_queue[event_index])->retrieved = TWA_AEN_RETRIEVED;
  801                 break;
  802 
  803 
  804         case TWA_IOCTL_GET_LOCK:
  805         {
  806                 struct twa_lock_packet  twa_lock;
  807                 u_int32_t               cur_time;
  808 
  809                 cur_time = time_second - (tz_minuteswest * 60) - 
  810                                         (wall_cmos_clock ? adjkerntz : 0);
  811                 copyin(user_buf->pdata, &twa_lock,
  812                                 sizeof(struct twa_lock_packet));
  813                 s = splcam();
  814                 if ((sc->twa_ioctl_lock.lock == TWA_LOCK_FREE) ||
  815                                 (twa_lock.force_flag) ||
  816                                 (cur_time >= sc->twa_ioctl_lock.timeout)) {
  817                         twa_dbg_dprint(3, sc, "GET_LOCK: Getting lock!");
  818                         sc->twa_ioctl_lock.lock = TWA_LOCK_HELD;
  819                         sc->twa_ioctl_lock.timeout = cur_time + (twa_lock.timeout_msec / 1000);
  820                         twa_lock.time_remaining_msec = twa_lock.timeout_msec;
  821                         user_buf->twa_drvr_pkt.status = 0;
  822                 } else {
  823                         twa_dbg_dprint(2, sc, "GET_LOCK: Lock already held!");
  824                         twa_lock.time_remaining_msec =
  825                                 (sc->twa_ioctl_lock.timeout - cur_time) * 1000;
  826                         user_buf->twa_drvr_pkt.status =
  827                                         TWA_ERROR_IOCTL_LOCK_ALREADY_HELD;
  828                 }
  829                 splx(s);
  830                 copyout(&twa_lock, user_buf->pdata,
  831                                 sizeof(struct twa_lock_packet));
  832                 break;
  833         }
  834 
  835 
  836         case TWA_IOCTL_RELEASE_LOCK:
  837                 s = splcam();
  838                 if (sc->twa_ioctl_lock.lock == TWA_LOCK_FREE) {
  839                         twa_dbg_dprint(2, sc, "twa_ioctl: RELEASE_LOCK: Lock not held!");
  840                         user_buf->twa_drvr_pkt.status = TWA_ERROR_IOCTL_LOCK_NOT_HELD;
  841                 } else {
  842                         twa_dbg_dprint(3, sc, "RELEASE_LOCK: Releasing lock!");
  843                         sc->twa_ioctl_lock.lock = TWA_LOCK_FREE;
  844                         user_buf->twa_drvr_pkt.status = 0;
  845                 }
  846                 splx(s);
  847                 break;
  848 
  849 
  850         case TWA_IOCTL_GET_COMPATIBILITY_INFO:
  851         {
  852                 struct twa_compatibility_packet comp_pkt;
  853 
  854                 bcopy(TWA_DRIVER_VERSION_STRING, comp_pkt.driver_version,
  855                                         sizeof(TWA_DRIVER_VERSION_STRING));
  856                 comp_pkt.working_srl = sc->working_srl;
  857                 comp_pkt.working_branch = sc->working_branch;
  858                 comp_pkt.working_build = sc->working_build;
  859                 user_buf->twa_drvr_pkt.status = 0;
  860 
  861                 /* Copy compatibility information to user space. */
  862                 copyout(&comp_pkt, user_buf->pdata,
  863                                 min(sizeof(struct twa_compatibility_packet),
  864                                         user_buf->twa_drvr_pkt.buffer_length));
  865                 break;
  866         }
  867 
  868         default:        
  869                 /* Unknown opcode. */
  870                 error = ENOTTY;
  871         }
  872 
  873         return(error);
  874 }
  875 
  876 
  877 /*
  878  * Function name:       twa_enable_interrupts
  879  * Description:         Enables interrupts on the controller
  880  *
  881  * Input:               sc      -- ptr to per ctlr structure
  882  * Output:              None
  883  * Return value:        None
  884  */
  885 void
  886 twa_enable_interrupts(struct twa_softc *sc)
  887 {
  888         sc->twa_state |= TWA_STATE_INTR_ENABLED;
  889         TWA_WRITE_CONTROL_REGISTER(sc,
  890                 TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT |
  891                 TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT |
  892                 TWA_CONTROL_ENABLE_INTERRUPTS);
  893 }
  894 
  895 
  896 /*
  897  * Function name:       twa_setup
  898  * Description:         Disables interrupts on the controller
  899  *
  900  * Input:               sc      -- ptr to per ctlr structure
  901  * Output:              None
  902  * Return value:        None
  903  */
  904 void
  905 twa_disable_interrupts(struct twa_softc *sc)
  906 {
  907         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_DISABLE_INTERRUPTS);
  908         sc->twa_state &= ~TWA_STATE_INTR_ENABLED;
  909 }
  910 
  911 
  912 
  913 /*
  914  * Function name:       twa_get_param
  915  * Description:         Get a firmware parameter.
  916  *
  917  * Input:               sc              -- ptr to per ctlr structure
  918  *                      table_id        -- parameter table #
  919  *                      param_id        -- index of the parameter in the table
  920  *                      param_size      -- size of the parameter in bytes
  921  *                      callback        -- ptr to function, if any, to be called
  922  *                                      back on completion; NULL if no callback.
  923  * Output:              None
  924  * Return value:        ptr to param structure  -- success
  925  *                      NULL                    -- failure
  926  */
  927 static void *
  928 twa_get_param(struct twa_softc *sc, int table_id, int param_id,
  929                 size_t param_size, void (* callback)(struct twa_request *tr))
  930 {
  931         struct twa_request      *tr;
  932         union twa_command_7k    *cmd;
  933         struct twa_param_9k     *param = NULL;
  934         int                     error = ENOMEM;
  935 
  936         twa_dbg_dprint_enter(4, sc);
  937 
  938         /* Get a request packet. */
  939         if ((tr = twa_get_request(sc)) == NULL)
  940                 goto out;
  941         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
  942 
  943         /* Allocate memory to read data into. */
  944         if ((param = (struct twa_param_9k *)
  945                         malloc(TWA_SECTOR_SIZE, M_DEVBUF, M_NOWAIT)) == NULL)
  946                 goto out;
  947         bzero(param, sizeof(struct twa_param_9k) - 1 + param_size);
  948         tr->tr_data = param;
  949         tr->tr_length = TWA_SECTOR_SIZE;
  950         tr->tr_flags = TWA_CMD_DATA_IN | TWA_CMD_DATA_OUT;
  951 
  952         /* Build the cmd pkt. */
  953         cmd = &(tr->tr_command->command.cmd_pkt_7k);
  954 
  955         tr->tr_command->cmd_hdr.header_desc.size_header = 128;
  956         
  957         cmd->param.opcode = TWA_OP_GET_PARAM;
  958         cmd->param.sgl_offset = 2;
  959         cmd->param.size = 2;
  960         cmd->param.request_id = tr->tr_request_id;
  961         cmd->param.unit = 0;
  962         cmd->param.param_count = 1;
  963 
  964         /* Specify which parameter we need. */
  965         param->table_id = table_id | TWA_9K_PARAM_DESCRIPTOR;
  966         param->parameter_id = param_id;
  967         param->parameter_size_bytes = param_size;
  968 
  969         /* Submit the command. */
  970         if (callback == NULL) {
  971                 /* There's no call back; wait till the command completes. */
  972                 error = twa_immediate_request(tr, TWA_REQUEST_TIMEOUT_PERIOD);
  973                 if (error == ETIMEDOUT)
  974                         return(NULL); /* clean-up done by twa_immediate_request */
  975                 if (error)
  976                         goto out;
  977                 if ((error = cmd->param.status)) {
  978                         twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
  979                                         cmd->param.opcode,
  980                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
  981                                         tr->tr_command->cmd_hdr.status_block.error,
  982                                         twa_find_msg_string(twa_error_table,
  983                                                 tr->tr_command->cmd_hdr.status_block.error),
  984                                         tr->tr_command->cmd_hdr.err_specific_desc);
  985                         goto out; /* twa_drain_complete_queue will have done the unmapping */
  986                 }
  987                 twa_release_request(tr);
  988                 return(param);
  989         } else {
  990                 /* There's a call back.  Simply submit the command. */
  991                 tr->tr_callback = callback;
  992                 if ((error = twa_map_request(tr))) {
  993                         twa_printf(tr->tr_sc, "%s: twa_map_request returned 0x%x\n",
  994                                                 __func__, error);
  995                         goto out;
  996                 }
  997                 return(callback);
  998         }
  999 
 1000 out:
 1001         twa_printf(sc, "get_param failed. error = 0x%x\n", error);
 1002         if (param)
 1003                 free(param, M_DEVBUF);
 1004         if (tr)
 1005                 twa_release_request(tr);
 1006         return(NULL);
 1007 }
 1008 
 1009 
 1010 /*
 1011  * Function name:       twa_set_param
 1012  * Description:         Set a firmware parameter.
 1013  *
 1014  * Input:               sc              -- ptr to per ctlr structure
 1015  *                      table_id        -- parameter table #
 1016  *                      param_id        -- index of the parameter in the table
 1017  *                      param_size      -- size of the parameter in bytes
 1018  *                      callback        -- ptr to function, if any, to be called
 1019  *                                      back on completion; NULL if no callback.
 1020  * Output:              None
 1021  * Return value:        0       -- success
 1022  *                      non-zero-- failure
 1023  */
 1024 static int
 1025 twa_set_param(struct twa_softc *sc, int table_id,
 1026                         int param_id, int param_size, void *data,
 1027                         void (* callback)(struct twa_request *tr))
 1028 {
 1029         struct twa_request      *tr;
 1030         union twa_command_7k    *cmd;
 1031         struct twa_param_9k     *param = NULL;
 1032         int                     error = ENOMEM;
 1033 
 1034         twa_dbg_dprint_enter(4, sc);
 1035 
 1036         /* Get a request packet. */
 1037         if ((tr = twa_get_request(sc)) == NULL)
 1038                 goto out;
 1039         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
 1040 
 1041         /* Allocate memory to send data using. */
 1042         if ((param = (struct twa_param_9k *)
 1043                         malloc(TWA_SECTOR_SIZE, M_DEVBUF, M_NOWAIT)) == NULL)
 1044                 goto out;
 1045         bzero(param, sizeof(struct twa_param_9k) - 1 + param_size);
 1046         tr->tr_data = param;
 1047         tr->tr_length = TWA_SECTOR_SIZE;
 1048         tr->tr_flags = TWA_CMD_DATA_IN | TWA_CMD_DATA_OUT;
 1049 
 1050         /* Build the cmd pkt. */
 1051         cmd = &(tr->tr_command->command.cmd_pkt_7k);
 1052 
 1053         tr->tr_command->cmd_hdr.header_desc.size_header = 128;
 1054 
 1055         cmd->param.opcode = TWA_OP_SET_PARAM;
 1056         cmd->param.sgl_offset = 2;
 1057         cmd->param.size = 2;
 1058         cmd->param.request_id = tr->tr_request_id;
 1059         cmd->param.unit = 0;
 1060         cmd->param.param_count = 1;
 1061 
 1062         /* Specify which parameter we want to set. */
 1063         param->table_id = table_id | TWA_9K_PARAM_DESCRIPTOR;
 1064         param->parameter_id = param_id;
 1065         param->parameter_size_bytes = param_size;
 1066         bcopy(data, param->data, param_size);
 1067 
 1068         /* Submit the command. */
 1069         if (callback == NULL) {
 1070                 /* There's no call back;  wait till the command completes. */
 1071                 error = twa_immediate_request(tr, TWA_REQUEST_TIMEOUT_PERIOD);
 1072                 if (error == ETIMEDOUT)
 1073                         return(error); /* clean-up done by twa_immediate_request */
 1074                 if (error)
 1075                         goto out;
 1076                 if ((error = cmd->param.status)) {
 1077                         twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
 1078                                         cmd->param.opcode,
 1079                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
 1080                                         tr->tr_command->cmd_hdr.status_block.error,
 1081                                         twa_find_msg_string(twa_error_table,
 1082                                                 tr->tr_command->cmd_hdr.status_block.error),
 1083                                         tr->tr_command->cmd_hdr.err_specific_desc);
 1084                         goto out; /* twa_drain_complete_queue will have done the unmapping */
 1085                 }
 1086                 free(param, M_DEVBUF);
 1087                 twa_release_request(tr);
 1088                 return(error);
 1089         } else {
 1090                 /* There's a call back.  Simply submit the command. */
 1091                 tr->tr_callback = callback;
 1092                 if ((error = twa_map_request(tr))) {
 1093                         twa_printf(tr->tr_sc, "%s: twa_map_request returned 0x%x\n",
 1094                                                 __func__, error);
 1095                         goto out;
 1096                 }
 1097                 return(0);
 1098         }
 1099 
 1100 out:
 1101         twa_printf(sc, "set_param failed. error = 0x%x\n", error);
 1102         if (param)
 1103                 free(param, M_DEVBUF);
 1104         if (tr)
 1105                 twa_release_request(tr);
 1106         return(error);
 1107 }
 1108 
 1109 
 1110 /*
 1111  * Function name:       twa_init_connection
 1112  * Description:         Send init_connection cmd to firmware
 1113  *
 1114  * Input:               sc              -- ptr to per ctlr structure
 1115  *                      message_credits -- max # of requests that we might send
 1116  *                                       down simultaneously.  This will be
 1117  *                                       typically set to 256 at init-time or
 1118  *                                      after a reset, and to 1 at shutdown-time
 1119  *                      set_features    -- indicates if we intend to use 64-bit
 1120  *                                      sg, also indicates if we want to do a
 1121  *                                      basic or an extended init_connection;
 1122  *
 1123  * Note: The following input/output parameters are valid, only in case of an
 1124  *              extended init_connection:
 1125  *
 1126  *                      current_fw_srl          -- srl of fw we are bundled
 1127  *                                              with, if any; 0 otherwise
 1128  *                      current_fw_arch_id      -- arch_id of fw we are bundled
 1129  *                                              with, if any; 0 otherwise
 1130  *                      current_fw_branch       -- branch # of fw we are bundled
 1131  *                                              with, if any; 0 otherwise
 1132  *                      current_fw_build        -- build # of fw we are bundled
 1133  *                                              with, if any; 0 otherwise
 1134  * Output:              fw_on_ctlr_srl          -- srl of fw on ctlr
 1135  *                      fw_on_ctlr_arch_id      -- arch_id of fw on ctlr
 1136  *                      fw_on_ctlr_branch       -- branch # of fw on ctlr
 1137  *                      fw_on_ctlr_build        -- build # of fw on ctlr
 1138  *                      init_connect_result     -- result bitmap of fw response
 1139  * Return value:        0       -- success
 1140  *                      non-zero-- failure
 1141  */
 1142 static int
 1143 twa_init_connection(struct twa_softc *sc, u_int16_t message_credits,
 1144                         u_int32_t set_features, u_int16_t current_fw_srl,
 1145                         u_int16_t current_fw_arch_id, u_int16_t current_fw_branch,
 1146                         u_int16_t current_fw_build, u_int16_t *fw_on_ctlr_srl,
 1147                         u_int16_t *fw_on_ctlr_arch_id, u_int16_t *fw_on_ctlr_branch,
 1148                         u_int16_t *fw_on_ctlr_build, u_int32_t *init_connect_result)
 1149 {
 1150         struct twa_request              *tr;
 1151         struct twa_command_init_connect *init_connect;
 1152         int                             error = 1;
 1153     
 1154         twa_dbg_dprint_enter(3, sc);
 1155 
 1156         /* Get a request packet. */
 1157         if ((tr = twa_get_request(sc)) == NULL)
 1158                 goto out;
 1159         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
 1160         /* Build the cmd pkt. */
 1161         init_connect = &(tr->tr_command->command.cmd_pkt_7k.init_connect);
 1162 
 1163         tr->tr_command->cmd_hdr.header_desc.size_header = 128;
 1164 
 1165         init_connect->opcode = TWA_OP_INIT_CONNECTION;
 1166         init_connect->request_id = tr->tr_request_id;
 1167         init_connect->message_credits = message_credits;
 1168         init_connect->features = set_features;
 1169         if (TWA_64BIT_ADDRESSES)
 1170                 init_connect->features |= TWA_64BIT_SG_ADDRESSES;
 1171         if (set_features & TWA_EXTENDED_INIT_CONNECT) {
 1172                 /* Fill in the extra fields needed for an extended init_connect. */
 1173                 init_connect->size = 6;
 1174                 init_connect->fw_srl = current_fw_srl;
 1175                 init_connect->fw_arch_id = current_fw_arch_id;
 1176                 init_connect->fw_branch = current_fw_branch;
 1177                 init_connect->fw_build = current_fw_build;
 1178         } else
 1179                 init_connect->size = 3;
 1180 
 1181         /* Submit the command, and wait for it to complete. */
 1182         error = twa_immediate_request(tr, TWA_REQUEST_TIMEOUT_PERIOD);
 1183         if (error == ETIMEDOUT)
 1184                 return(error); /* clean-up done by twa_immediate_request */
 1185         if (error)
 1186                 goto out;
 1187         if ((error = init_connect->status)) {
 1188                 twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
 1189                                         init_connect->opcode,
 1190                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
 1191                                         tr->tr_command->cmd_hdr.status_block.error,
 1192                                         twa_find_msg_string(twa_error_table,
 1193                                                 tr->tr_command->cmd_hdr.status_block.error),
 1194                                         tr->tr_command->cmd_hdr.err_specific_desc);
 1195                 goto out; /* twa_drain_complete_queue will have done the unmapping */
 1196         }
 1197         if (set_features & TWA_EXTENDED_INIT_CONNECT) {
 1198                 *fw_on_ctlr_srl = init_connect->fw_srl;
 1199                 *fw_on_ctlr_arch_id = init_connect->fw_arch_id;
 1200                 *fw_on_ctlr_branch = init_connect->fw_branch;
 1201                 *fw_on_ctlr_build = init_connect->fw_build;
 1202                 *init_connect_result = init_connect->result;
 1203         }
 1204         twa_release_request(tr);
 1205         return(error);
 1206 
 1207 out:
 1208         twa_printf(sc, "init_connection failed. error = 0x%x\n", error);
 1209         if (tr)
 1210                 twa_release_request(tr);
 1211         return(error);
 1212 }
 1213 
 1214 
 1215 
 1216 /*
 1217  * Function name:       twa_wait_request
 1218  * Description:         Sends down a firmware cmd, and waits for the completion,
 1219  *                      but NOT in a tight loop.
 1220  *
 1221  * Input:               tr      -- ptr to request pkt
 1222  *                      timeout -- max # of seconds to wait before giving up
 1223  * Output:              None
 1224  * Return value:        0       -- success
 1225  *                      non-zero-- failure
 1226  */
 1227 static int
 1228 twa_wait_request(struct twa_request *tr, u_int32_t timeout)
 1229 {
 1230         time_t  end_time;
 1231         int     error;
 1232 
 1233         twa_dbg_dprint_enter(4, tr->tr_sc);
 1234 
 1235         tr->tr_flags |= TWA_CMD_SLEEP_ON_REQUEST;
 1236         tr->tr_status = TWA_CMD_BUSY;
 1237         if ((error = twa_map_request(tr))) {
 1238                 twa_printf(tr->tr_sc, "%s: twa_map_request returned 0x%x\n",
 1239                                                 __func__, error);
 1240                 return(error);
 1241         }
 1242 
 1243         end_time = time_second + timeout;
 1244         while (tr->tr_status != TWA_CMD_COMPLETE) {
 1245                 if ((error = tr->tr_error))
 1246                         return(error);
 1247                 if ((error = tsleep(tr, PRIBIO, "twawait", timeout * hz)) == 0) {
 1248                         error = (tr->tr_status != TWA_CMD_COMPLETE);
 1249                         break;
 1250                 }
 1251                 if (error == EWOULDBLOCK) {
 1252                         /* Time out! */
 1253                         twa_printf(tr->tr_sc, "%s: Request %p timed out.\n",
 1254                                                                 __func__, tr);
 1255                         /*
 1256                          * We will reset the controller only if the request has
 1257                          * already been submitted, so as to not lose the
 1258                          * request packet.  If a busy request timed out, the
 1259                          * reset will take care of freeing resources.  If a
 1260                          * pending request timed out, we will free resources
 1261                          * for that request, right here.  So, the caller is
 1262                          * expected to NOT cleanup when ETIMEDOUT is returned.
 1263                          */
 1264                         if (tr->tr_status != TWA_CMD_PENDING)
 1265                                 twa_reset(tr->tr_sc);
 1266                         else {
 1267                                 /* Request was never submitted.  Clean up. */
 1268                                 twa_remove_pending(tr);
 1269                                 twa_unmap_request(tr);
 1270                                 if (tr->tr_data)
 1271                                         free(tr->tr_data, M_DEVBUF);
 1272                                 twa_release_request(tr);
 1273                         }
 1274                         return(ETIMEDOUT);
 1275                 }
 1276                 /* 
 1277                  * Either the request got completed, or we were woken up by a
 1278                  * signal.  Calculate the new timeout, in case it was the latter.
 1279                  */
 1280                 timeout = (end_time - time_second);
 1281         }
 1282         twa_unmap_request(tr);
 1283         return(error);
 1284 }
 1285 
 1286 
 1287 
 1288 /*
 1289  * Function name:       twa_immediate_request
 1290  * Description:         Sends down a firmware cmd, and waits for the completion
 1291  *                      in a tight loop.
 1292  *
 1293  * Input:               tr      -- ptr to request pkt
 1294  *                      timeout -- max # of seconds to wait before giving up
 1295  * Output:              None
 1296  * Return value:        0       -- success
 1297  *                      non-zero-- failure
 1298  */
 1299 static int
 1300 twa_immediate_request(struct twa_request *tr, u_int32_t timeout)
 1301 {
 1302         time_t  end_time;
 1303         int     error = 0;
 1304 
 1305         twa_dbg_dprint_enter(4, tr->tr_sc);
 1306 
 1307         if ((error = twa_map_request(tr))) {
 1308                 twa_printf(tr->tr_sc, "%s: twa_map_request returned 0x%x\n",
 1309                                                 __func__, error);
 1310                 return(error);
 1311         }
 1312 
 1313         end_time = time_second + timeout;
 1314         do {
 1315                 if ((error = tr->tr_error))
 1316                         return(error);
 1317                 twa_done(tr->tr_sc);
 1318                 if ((tr->tr_status != TWA_CMD_BUSY) &&
 1319                         (tr->tr_status != TWA_CMD_PENDING)) {
 1320                         twa_unmap_request(tr);
 1321                         return(tr->tr_status != TWA_CMD_COMPLETE);
 1322                 }
 1323         } while (time_second <= end_time);
 1324 
 1325         /* Time out! */
 1326         twa_printf(tr->tr_sc, "%s: Request %p timed out.\n", __func__, tr);
 1327         /*
 1328          * We will reset the controller only if the request has
 1329          * already been submitted, so as to not lose the
 1330          * request packet.  If a busy request timed out, the
 1331          * reset will take care of freeing resources.  If a
 1332          * pending request timed out, we will free resources
 1333          * for that request, right here.  So, the caller is
 1334          * expected to NOT cleanup when ETIMEDOUT is returned.
 1335          */
 1336         if (tr->tr_status != TWA_CMD_PENDING)
 1337                 twa_reset(tr->tr_sc);
 1338         else {
 1339                 /* Request was never submitted.  Clean up. */
 1340                 twa_remove_pending(tr);
 1341                 twa_unmap_request(tr);
 1342                 if (tr->tr_data)
 1343                         free(tr->tr_data, M_DEVBUF);
 1344                 twa_release_request(tr);
 1345         }
 1346         return(ETIMEDOUT);
 1347 }
 1348 
 1349 
 1350 
 1351 /*
 1352  * Function name:       twa_complete_io
 1353  * Description:         Callback on scsi requests to fw.
 1354  *
 1355  * Input:               tr      -- ptr to request pkt
 1356  * Output:              None
 1357  * Return value:        None
 1358  */
 1359 void
 1360 twa_complete_io(struct twa_request *tr)
 1361 {
 1362         struct twa_softc        *sc = tr->tr_sc;
 1363 
 1364         twa_dbg_dprint_enter(8, sc);
 1365 
 1366         if (tr->tr_status != TWA_CMD_COMPLETE)
 1367                 twa_panic(sc, "twa_complete_io on incomplete command");
 1368         if (tr->tr_private) /* This is a scsi cmd.  Complete it. */
 1369                 twa_scsi_complete(tr);
 1370         twa_release_request(tr);
 1371 }
 1372 
 1373 
 1374 /*
 1375  * Function name:       twa_reset
 1376  * Description:         Soft resets and then initializes the controller;
 1377  *                      drains any incomplete requests.
 1378  *
 1379  * Input:               sc      -- ptr to per ctlr structure
 1380  * Output:              None
 1381  * Return value:        0       -- success
 1382  *                      non-zero-- failure
 1383  */
 1384 int
 1385 twa_reset(struct twa_softc *sc)
 1386 {
 1387         int     s;
 1388         int     error = 0;
 1389 
 1390         twa_dbg_dprint_enter(2, sc);
 1391 
 1392         /*
 1393          * Disable interrupts from the controller, and mask any
 1394          * accidental entry into our interrupt handler.
 1395          */
 1396         twa_disable_interrupts(sc);
 1397         s = splcam();
 1398         
 1399         /* Soft reset the controller. */
 1400         if ((error = twa_soft_reset(sc))) {
 1401                 twa_printf (sc, "Controller reset failed.\n");
 1402                 goto out;
 1403         }
 1404 
 1405         /* Re-establish logical connection with the controller. */
 1406         if ((error = twa_init_connection(sc, TWA_INIT_MESSAGE_CREDITS,
 1407                                         0, 0, 0, 0, 0,
 1408                                         NULL, NULL, NULL, NULL, NULL))) {
 1409                 twa_printf(sc, "Can't initialize connection after reset.\n");
 1410                 goto out;
 1411         }
 1412 
 1413         twa_printf(sc, "Controller reset done!\n");
 1414 
 1415         /*
 1416          * Complete all requests in the complete queue; error back all requests
 1417          * in the busy queue.  Any internal requests will be simply freed.
 1418          * Re-submit any requests in the pending queue.
 1419          */
 1420         twa_drain_complete_queue(sc);
 1421         twa_drain_busy_queue(sc);
 1422 
 1423 out:
 1424         splx(s);
 1425         /*
 1426          * Enable interrupts, and also clear attention and response interrupts.
 1427          */
 1428         twa_enable_interrupts(sc);
 1429         return(error);
 1430 }
 1431 
 1432 
 1433 
 1434 /*
 1435  * Function name:       twa_soft_reset
 1436  * Description:         Does the actual soft reset.
 1437  *
 1438  * Input:               sc      -- ptr to per ctlr structure
 1439  * Output:              None
 1440  * Return value:        0       -- success
 1441  *                      non-zero-- failure
 1442  */
 1443 static int
 1444 twa_soft_reset(struct twa_softc *sc)
 1445 {
 1446         u_int32_t       status_reg;
 1447 
 1448         twa_dbg_dprint_enter(1, sc);
 1449 
 1450         twa_printf(sc, "Resetting controller...\n");
 1451         TWA_SOFT_RESET(sc);
 1452 
 1453         if (twa_wait_status(sc, TWA_STATUS_MICROCONTROLLER_READY |
 1454                                 TWA_STATUS_ATTENTION_INTERRUPT, 30)) {
 1455                 twa_printf(sc, "Micro-ctlr not ready/No attn intr after reset.\n");
 1456                 return(1);
 1457         }
 1458         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
 1459         if (twa_drain_response_queue(sc)) {
 1460                 twa_printf(sc, "Can't drain response queue.\n");
 1461                 return(1);
 1462         }
 1463         if (twa_drain_aen_queue(sc)) {
 1464                 twa_printf(sc, "Can't drain AEN queue.\n");
 1465                 return(1);
 1466         }
 1467         if (twa_find_aen(sc, TWA_AEN_SOFT_RESET)) {
 1468                 twa_printf(sc, "Reset not reported by controller.\n");
 1469                 return(1);
 1470         }
 1471         status_reg = TWA_READ_STATUS_REGISTER(sc);
 1472         if (TWA_STATUS_ERRORS(status_reg) ||
 1473                                 twa_check_ctlr_state(sc, status_reg)) {
 1474                 twa_printf(sc, "Controller errors detected.\n");
 1475                 return(1);
 1476         }
 1477         return(0);
 1478 }
 1479 
 1480 
 1481 
 1482 /*
 1483  * Function name:       twa_submit_io
 1484  * Description:         Wrapper to twa_start.
 1485  *
 1486  * Input:               tr      -- ptr to request pkt
 1487  * Output:              None
 1488  * Return value:        0       -- success
 1489  *                      non-zero-- failure
 1490  */
 1491 int
 1492 twa_submit_io(struct twa_request *tr)
 1493 {
 1494         int     error;
 1495 
 1496         if ((error = twa_start(tr))) {
 1497                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
 1498                         if (error == EBUSY)
 1499                                 /*
 1500                                  * Cmd queue is full.  Freeze the simq to
 1501                                  * maintain ccb ordering.  The next ccb that
 1502                                  * gets completed will unfreeze the simq.
 1503                                  */
 1504                                 twa_disallow_new_requests(tr->tr_sc);
 1505                         else
 1506                                 /* It's a controller error. */
 1507                                 twa_printf(tr->tr_sc, "SCSI cmd = 0x%x: ERROR: (0x%02X: 0x%04X)\n",
 1508                                         tr->tr_command->command.cmd_pkt_9k.cdb[0],
 1509                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
 1510                                         error);
 1511                         
 1512                         tr->tr_error = error;
 1513                         twa_scsi_complete(tr);
 1514                 } else {
 1515                         if (error == EBUSY)
 1516                                 error = 0; /* the request will be in the pending queue */
 1517                         else {
 1518                                 twa_printf(tr->tr_sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X)\n",
 1519                                                 (tr->tr_cmd_pkt_type == TWA_CMD_PKT_TYPE_9K) ?
 1520                                                 (tr->tr_command->command.cmd_pkt_9k.command.opcode) :
 1521                                                 (tr->tr_command->command.cmd_pkt_7k.generic.opcode),
 1522                                                 TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
 1523                                                 tr->tr_error);
 1524                                 tr->tr_error = error;
 1525                         }
 1526                 }
 1527         }
 1528         return(error);
 1529 }
 1530 
 1531 
 1532 
 1533 /*
 1534  * Function name:       twa_start
 1535  * Description:         Posts a cmd to firmware.
 1536  *
 1537  * Input:               tr      -- ptr to request pkt
 1538  * Output:              None
 1539  * Return value:        0       -- success
 1540  *                      non-zero-- failure
 1541  */
 1542 int
 1543 twa_start(struct twa_request *tr)
 1544 {
 1545         struct twa_softc        *sc = tr->tr_sc;
 1546         u_int32_t               status_reg;
 1547         int                     s;
 1548         int                     error;
 1549 
 1550         twa_dbg_dprint_enter(10, sc);
 1551 
 1552         s = splcam();
 1553         /* Check to see if we can post a command. */
 1554         status_reg = TWA_READ_STATUS_REGISTER(sc);
 1555         if ((error = twa_check_ctlr_state(sc, status_reg)))
 1556                 goto out;
 1557 
 1558         if (status_reg & TWA_STATUS_COMMAND_QUEUE_FULL) {
 1559                 if ((tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_INTERNAL) ||
 1560                         (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_IOCTL)) {
 1561                         if (tr->tr_status != TWA_CMD_PENDING) {
 1562                                 twa_dbg_dprint(2, sc, "pending internal/ioctl request");
 1563                                 tr->tr_status = TWA_CMD_PENDING;
 1564                                 twa_enqueue_pending(tr);
 1565                         }
 1566                         TWA_WRITE_CONTROL_REGISTER(sc,
 1567                                         TWA_CONTROL_UNMASK_COMMAND_INTERRUPT);
 1568                 }
 1569                 error = EBUSY;
 1570         } else {
 1571                 /* Cmd queue is not full.  Post the command. */
 1572                 TWA_WRITE_COMMAND_QUEUE(sc,
 1573                         tr->tr_cmd_phys + sizeof(struct twa_command_header));
 1574                 /* Mark the request as currently being processed. */
 1575                 tr->tr_status = TWA_CMD_BUSY;
 1576                 /* Move the request into the busy queue. */
 1577                 twa_enqueue_busy(tr);
 1578         }
 1579 
 1580 out:
 1581         splx(s);
 1582         return(error);
 1583 }
 1584 
 1585 
 1586 
 1587 /*
 1588  * Function name:       twa_done
 1589  * Description:         Looks for cmd completions from fw; queues cmds completed
 1590  *                      by fw into complete queue.
 1591  *
 1592  * Input:               sc      -- ptr to per ctlr structure
 1593  * Output:              None
 1594  * Return value:        0       -- no ctlr error
 1595  *                      non-zero-- ctlr error
 1596  */
 1597 static int
 1598 twa_done(struct twa_softc *sc)
 1599 {
 1600         union twa_response_queue        rq;
 1601         struct twa_request              *tr;
 1602         int                             s;
 1603         int                             error = 0;
 1604         u_int32_t                       status_reg;
 1605     
 1606         twa_dbg_dprint_enter(10, sc);
 1607 
 1608         s = splcam();
 1609         for (;;) {
 1610                 status_reg = TWA_READ_STATUS_REGISTER(sc);
 1611                 if ((error = twa_check_ctlr_state(sc, status_reg)))
 1612                         break;
 1613                 if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
 1614                         break;
 1615                 /* Response queue is not empty. */
 1616                 rq = TWA_READ_RESPONSE_QUEUE(sc);
 1617                 tr = sc->twa_lookup[rq.u.response_id];  /* lookup the request */
 1618                 if (tr->tr_status != TWA_CMD_BUSY)
 1619                         twa_printf(sc, "ERROR: Unposted command completed!! req = %p; status = %d\n",
 1620                                         tr, tr->tr_status);
 1621                 tr->tr_status = TWA_CMD_COMPLETE;
 1622                 /* Enqueue request in the complete queue. */
 1623                 twa_remove_busy(tr);
 1624                 twa_enqueue_complete(tr);
 1625         }
 1626         splx(s);
 1627 
 1628         /* Complete this, and other requests in the complete queue. */
 1629         twa_drain_complete_queue(sc);
 1630         return(error);
 1631 }
 1632 
 1633 
 1634 
 1635 /*
 1636  * Function name:       twa_drain_pending_queue
 1637  * Description:         Kick starts any requests in the pending queue.
 1638  *
 1639  * Input:               sc      -- ptr to per ctlr structure
 1640  * Output:              None
 1641  * Return value:        0       -- all pending requests drained
 1642  *                      non-zero-- otherwise
 1643  */
 1644 static int
 1645 twa_drain_pending_queue(struct twa_softc *sc)
 1646 {
 1647         struct twa_request      *tr;
 1648         int                     error = 0;
 1649     
 1650         twa_dbg_dprint_enter(10, sc);
 1651         
 1652         /*
 1653          * Pull requests off the pending queue, and submit them.
 1654          */
 1655         while ((tr = twa_dequeue_pending(sc)) != NULL) {
 1656                 if ((error = twa_start(tr))) {
 1657                         if (error == EBUSY) {
 1658                                 twa_dbg_dprint(2, sc, "Requeueing pending request");
 1659                                 tr->tr_status = TWA_CMD_PENDING;
 1660                                 twa_requeue_pending(tr);/* queue at the head */
 1661                                 break;
 1662                         } else {
 1663                                 twa_printf(sc, "%s: twa_start returned 0x%x\n",
 1664                                                         __func__, error);
 1665                                 if (tr->tr_flags & TWA_CMD_SLEEP_ON_REQUEST)
 1666                                         wakeup_one(tr);/* let the caller know it failed */
 1667                                 tr->tr_error = error;
 1668                                 error = 0;
 1669                         }
 1670                 }
 1671         }
 1672         return(error);
 1673 }
 1674 
 1675 
 1676 
 1677 /*
 1678  * Function name:       twa_drain_complete_queue
 1679  * Description:         Does unmapping for each request completed by fw,
 1680  *                      and lets the request originators know of the completion.
 1681  *
 1682  * Input:               sc      -- ptr to per ctlr structure
 1683  * Output:              None
 1684  * Return value:        None
 1685  */
 1686 static void
 1687 twa_drain_complete_queue(struct twa_softc *sc)
 1688 {
 1689         struct twa_request      *tr;
 1690     
 1691         twa_dbg_dprint_enter(10, sc);
 1692 
 1693         /*
 1694          * Pull commands off the completed list, dispatch them appropriately.
 1695          */
 1696         while ((tr = twa_dequeue_complete(sc)) != NULL) {
 1697                 /* Unmap the command packet, and any associated data buffer. */
 1698                 twa_unmap_request(tr);
 1699 
 1700                 /* Call the callback, if there's one. */
 1701                 if (tr->tr_callback)
 1702                         tr->tr_callback(tr);
 1703                 else
 1704                         if (tr->tr_flags & TWA_CMD_SLEEP_ON_REQUEST) {
 1705                                 /* Wake up the sleeping command originator. */
 1706                                 twa_dbg_dprint(7, sc, "Waking up originator of request %p", tr);
 1707                                 wakeup_one(tr);
 1708                         }
 1709         }
 1710 }
 1711 
 1712 
 1713 
 1714 /*
 1715  * Function name:       twa_wait_status
 1716  * Description:         Wait for a given status to show up in the fw status register.
 1717  *
 1718  * Input:               sc      -- ptr to per ctlr structure
 1719  *                      status  -- status to look for
 1720  *                      timeout -- max # of seconds to wait before giving up
 1721  * Output:              None
 1722  * Return value:        0       -- success
 1723  *                      non-zero-- failure
 1724  */
 1725 static int
 1726 twa_wait_status(struct twa_softc *sc, u_int32_t status, u_int32_t timeout)
 1727 {
 1728         time_t          end_time;
 1729         u_int32_t       status_reg;
 1730 
 1731         twa_dbg_dprint_enter(4, sc);
 1732 
 1733         end_time = time_second + timeout;
 1734         do {
 1735                 status_reg = TWA_READ_STATUS_REGISTER(sc);
 1736                 if ((status_reg & status) == status)/* got the required bit(s)? */
 1737                         return(0);
 1738                 DELAY(100000);
 1739         } while (time_second <= end_time);
 1740 
 1741         return(1);
 1742 }
 1743 
 1744 
 1745 
 1746 /*
 1747  * Function name:       twa_drain_response_queue
 1748  * Description:         Drain the response queue.
 1749  *
 1750  * Input:               sc      -- ptr to per ctlr structure
 1751  * Output:              None
 1752  * Return value:        0       -- success
 1753  *                      non-zero-- failure
 1754  */
 1755 static int
 1756 twa_drain_response_queue(struct twa_softc *sc)
 1757 {
 1758         union twa_response_queue        rq;
 1759         u_int32_t                       status_reg;
 1760 
 1761         twa_dbg_dprint_enter(4, sc);
 1762 
 1763         for (;;) {
 1764                 status_reg = TWA_READ_STATUS_REGISTER(sc);
 1765                 if (twa_check_ctlr_state(sc, status_reg))
 1766                         return(1);
 1767                 if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
 1768                         return(0); /* no more response queue entries */
 1769                 rq = TWA_READ_RESPONSE_QUEUE(sc);
 1770         }
 1771 }
 1772 
 1773 
 1774 
 1775 /*
 1776  * Function name:       twa_host_intr
 1777  * Description:         This function gets called if we triggered an interrupt.
 1778  *                      We don't use it as of now.
 1779  *
 1780  * Input:               sc      -- ptr to per ctlr structure
 1781  * Output:              None
 1782  * Return value:        None
 1783  */
 1784 static void
 1785 twa_host_intr(struct twa_softc *sc)
 1786 {
 1787         twa_dbg_dprint_enter(6, sc);
 1788 
 1789         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_HOST_INTERRUPT);
 1790 }
 1791 
 1792 
 1793 
 1794 /*
 1795  * Function name:       twa_attention_intr
 1796  * Description:         This function gets called if the fw posted an AEN
 1797  *                      (Asynchronous Event Notification).  It fetches
 1798  *                      all the AEN's that the fw might have posted.
 1799  *
 1800  * Input:               sc      -- ptr to per ctlr structure
 1801  * Output:              None
 1802  * Return value:        None
 1803  */
 1804 static void
 1805 twa_attention_intr(struct twa_softc *sc)
 1806 {
 1807         int     error;
 1808 
 1809         twa_dbg_dprint_enter(6, sc);
 1810 
 1811         if ((error = twa_fetch_aen(sc)))
 1812                 twa_printf(sc, "Fetch AEN failed. error = 0x%x\n", error);
 1813         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
 1814 }
 1815 
 1816 
 1817 
 1818 /*
 1819  * Function name:       twa_command_intr
 1820  * Description:         This function gets called if we hit a queue full
 1821  *                      condition earlier, and the fw is now ready for
 1822  *                      new cmds.  Submits any pending requests.
 1823  *
 1824  * Input:               sc      -- ptr to per ctlr structure
 1825  * Output:              None
 1826  * Return value:        None
 1827  */
 1828 static void
 1829 twa_command_intr(struct twa_softc *sc)
 1830 {
 1831         twa_dbg_dprint_enter(6, sc);
 1832 
 1833         /* Start any requests that might be in the pending queue. */
 1834         if (! twa_drain_pending_queue(sc))
 1835                 TWA_WRITE_CONTROL_REGISTER(sc,
 1836                                 TWA_CONTROL_MASK_COMMAND_INTERRUPT);
 1837 }
 1838 
 1839 
 1840 
 1841 /*
 1842  * Function name:       twa_fetch_aen
 1843  * Description:         Send down a Request Sense cmd to fw to fetch an AEN.
 1844  *
 1845  * Input:               sc      -- ptr to per ctlr structure
 1846  * Output:              None
 1847  * Return value:        0       -- success
 1848  *                      non-zero-- failure
 1849  */
 1850 static int
 1851 twa_fetch_aen(struct twa_softc *sc)
 1852 {
 1853         struct twa_request      *tr;
 1854         int                     error = 0;
 1855 
 1856         twa_dbg_dprint_enter(4, sc);
 1857 
 1858         if ((tr = twa_get_request(sc)) == NULL)
 1859                 return(EIO);
 1860         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
 1861         tr->tr_callback = twa_aen_callback;
 1862         if ((error = twa_send_scsi_cmd(tr, 0x03 /* REQUEST_SENSE */))) {
 1863                 if (tr->tr_data)
 1864                         free(tr->tr_data, M_DEVBUF);
 1865                 twa_release_request(tr);
 1866         }
 1867         return(error);
 1868 }
 1869 
 1870 
 1871 
 1872 /*
 1873  * Function name:       twa_aen_callback
 1874  * Description:         Callback for requests to fetch AEN's.
 1875  *
 1876  * Input:               tr      -- ptr to completed request pkt
 1877  * Output:              None
 1878  * Return value:        None
 1879  */
 1880 static void
 1881 twa_aen_callback(struct twa_request *tr)
 1882 {
 1883         struct twa_softc                *sc = tr->tr_sc;
 1884         struct twa_command_header       *cmd_hdr = (struct twa_command_header *)(tr->tr_data);
 1885         struct twa_command_9k           *cmd = &(tr->tr_command->command.cmd_pkt_9k);
 1886         int                             i;
 1887 
 1888         twa_dbg_dprint_enter(4, sc);
 1889 
 1890         twa_dbg_dprint(4, sc, "req_id = 0x%x, status = 0x%x",
 1891                                 cmd->request_id,
 1892                                 cmd->status);
 1893 
 1894         if (! cmd->status) {
 1895                 if ((tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_9K) &&
 1896                         (cmd->cdb[0] == 0x3 /* REQUEST_SENSE */))
 1897                         twa_enqueue_aen(sc, cmd_hdr);
 1898         } else {
 1899                 cmd_hdr->err_specific_desc[sizeof(cmd_hdr->err_specific_desc) - 1] = '\0';
 1900                 twa_printf(sc, "%s: cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
 1901                                 __func__, cmd->command.opcode,
 1902                                 TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
 1903                                 cmd_hdr->status_block.error,
 1904                                 twa_find_msg_string(twa_error_table,
 1905                                                 cmd_hdr->status_block.error),
 1906                                 cmd_hdr->err_specific_desc);
 1907                 twa_dbg_print(2, "sense info: ");
 1908                 for (i = 0; i < 18; i++)
 1909                         twa_dbg_print(2, "%x\t", tr->tr_command->cmd_hdr.sense_data[i]);
 1910                 twa_dbg_print(2, ""); /* print new line */
 1911                 for (i = 0; i < 128; i++)
 1912                         twa_dbg_print(7, "%x\t", ((int8_t *)(tr->tr_data))[i]);
 1913         }
 1914 
 1915         if (tr->tr_data)
 1916                 free(tr->tr_data, M_DEVBUF);
 1917         twa_release_request(tr);
 1918 }
 1919 
 1920 
 1921 
 1922 /*
 1923  * Function name:       twa_drain_aen_queue
 1924  * Description:         Fetches all un-retrieved AEN's posted by fw.
 1925  *
 1926  * Input:               sc      -- ptr to per ctlr structure
 1927  * Output:              None
 1928  * Return value:        0       -- success
 1929  *                      non-zero-- failure
 1930  */
 1931 static int
 1932 twa_drain_aen_queue(struct twa_softc *sc)
 1933 {
 1934         struct twa_request              *tr;
 1935         struct twa_command_header       *cmd_hdr;
 1936         time_t                          end_time;
 1937         int                             error = 0;
 1938 
 1939         for (;;) {
 1940                 if ((tr = twa_get_request(sc)) == NULL) {
 1941                         error = EIO;
 1942                         break;
 1943                 }
 1944                 tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
 1945                 tr->tr_callback = NULL;
 1946                 if ((error = twa_send_scsi_cmd(tr, 0x03 /* REQUEST_SENSE */))) {
 1947                         twa_dbg_dprint(1, sc, "Cannot send command to fetch aen");
 1948                         break;
 1949                 }
 1950 
 1951                 end_time = time_second + TWA_REQUEST_TIMEOUT_PERIOD;
 1952                 do {
 1953                         twa_done(tr->tr_sc);
 1954                         if (tr->tr_status != TWA_CMD_BUSY)
 1955                                 break;
 1956                 } while (time_second <= end_time);
 1957 
 1958                 if (tr->tr_status != TWA_CMD_COMPLETE) {
 1959                         error = ETIMEDOUT;
 1960                         break;
 1961                 }
 1962 
 1963                 if ((error = tr->tr_command->command.cmd_pkt_9k.status))
 1964                         break;
 1965 
 1966                 cmd_hdr = (struct twa_command_header *)(tr->tr_data);
 1967                 if ((cmd_hdr->status_block.error) /* aen_code */
 1968                                 == TWA_AEN_QUEUE_EMPTY)
 1969                         break;
 1970                 twa_enqueue_aen(sc, cmd_hdr);
 1971 
 1972                 free(tr->tr_data, M_DEVBUF);
 1973                 twa_release_request(tr);
 1974         }
 1975 
 1976         if (tr) {
 1977                 if (tr->tr_data)
 1978                         free(tr->tr_data, M_DEVBUF);
 1979                 twa_release_request(tr);
 1980         }
 1981         return(error);
 1982 }
 1983 
 1984 
 1985 
 1986 /*
 1987  * Function name:       twa_enqueue_aen
 1988  * Description:         Queues AEN's to be supplied to user-space tools on request.
 1989  *
 1990  * Input:               sc      -- ptr to per ctlr structure
 1991  *                      cmd_hdr -- ptr to hdr of fw cmd pkt, from where the AEN
 1992  *                                 details can be retrieved.
 1993  * Output:              None
 1994  * Return value:        None
 1995  */
 1996 static void
 1997 twa_enqueue_aen(struct twa_softc *sc, struct twa_command_header *cmd_hdr)
 1998 {
 1999         struct twa_event_packet *event;
 2000         unsigned short          aen_code;
 2001         unsigned long           local_time;
 2002         unsigned long           sync_time;
 2003         int                     s;
 2004 
 2005         twa_dbg_dprint_enter(4, sc);
 2006         s = splcam();
 2007         aen_code = cmd_hdr->status_block.error;
 2008 
 2009         switch (aen_code) {
 2010         case TWA_AEN_SYNC_TIME_WITH_HOST:
 2011                 twa_dbg_dprint(4, sc, "Received AEN_SYNC_TIME");
 2012                 /* Calculate time (in seconds) since last Sunday 12.00 AM. */
 2013                 local_time = time_second - (tz_minuteswest * 60) -
 2014                                         (wall_cmos_clock ? adjkerntz : 0);
 2015                 sync_time = (local_time - (3 * 86400)) % 604800;
 2016                 if (twa_set_param(sc, TWA_PARAM_TIME_TABLE,
 2017                                         TWA_PARAM_TIME_SchedulerTime, 4,
 2018                                         &sync_time, twa_aen_callback))
 2019                         twa_printf(sc, "Unable to sync time with ctlr!\n");
 2020                 break;
 2021 
 2022         case TWA_AEN_QUEUE_EMPTY:
 2023                 twa_dbg_dprint(4, sc, "AEN queue empty");
 2024                 break;
 2025 
 2026         default:
 2027                 /* Queue the event. */
 2028                 event = sc->twa_aen_queue[sc->twa_aen_head];
 2029                 if (event->retrieved == TWA_AEN_NOT_RETRIEVED)
 2030                         sc->twa_aen_queue_overflow = TRUE;
 2031                 event->severity = cmd_hdr->status_block.substatus_block.severity;
 2032                 local_time = time_second - (tz_minuteswest * 60) -
 2033                                         (wall_cmos_clock ? adjkerntz : 0);
 2034                 event->time_stamp_sec = local_time;
 2035                 event->aen_code = aen_code;
 2036                 event->retrieved = TWA_AEN_NOT_RETRIEVED;
 2037                 event->sequence_id = ++(sc->twa_current_sequence_id);
 2038                 cmd_hdr->err_specific_desc[sizeof(cmd_hdr->err_specific_desc) - 1] = '\0';
 2039                 event->parameter_len = strlen(cmd_hdr->err_specific_desc);
 2040                 bcopy(cmd_hdr->err_specific_desc, event->parameter_data,
 2041                                         event->parameter_len);
 2042 
 2043                 twa_dbg_dprint(4, sc, "event = %x %x %x %x %x %x %x\n %s",
 2044                                 event->sequence_id,
 2045                                 event->time_stamp_sec,
 2046                                 event->aen_code,
 2047                                 event->severity,
 2048                                 event->retrieved,
 2049                                 event->repeat_count,
 2050                                 event->parameter_len,
 2051                                 event->parameter_data);
 2052 
 2053                 twa_dbg_dprint(4, sc, "cmd_hdr = %x %lx %x %x %x %x %zx\n %s",
 2054                                 sc->twa_current_sequence_id,
 2055                                 local_time,
 2056                                 cmd_hdr->status_block.error,
 2057                                 cmd_hdr->status_block.substatus_block.severity,
 2058                                 TWA_AEN_NOT_RETRIEVED,
 2059                                 0,
 2060                                 strlen(cmd_hdr->err_specific_desc),
 2061                                 cmd_hdr->err_specific_desc);
 2062 
 2063                 /* Print the event. */
 2064                 if (event->severity < TWA_AEN_SEVERITY_DEBUG)
 2065                         twa_printf(sc,  "%s: (0x%02X: 0x%04X): %s: %s\n",
 2066                                         twa_aen_severity_table[event->severity],
 2067                                         TWA_MESSAGE_SOURCE_CONTROLLER_EVENT,
 2068                                         aen_code,
 2069                                         twa_find_msg_string(twa_aen_table, aen_code),
 2070                                         event->parameter_data);
 2071 
 2072                 if ((sc->twa_aen_head + 1) == TWA_Q_LENGTH)
 2073                         sc->twa_aen_queue_wrapped = TRUE;
 2074                 sc->twa_aen_head = (sc->twa_aen_head + 1) % TWA_Q_LENGTH;
 2075                 break;
 2076         } /* switch */
 2077         splx(s);
 2078 }
 2079 
 2080 
 2081 
 2082 /*
 2083  * Function name:       twa_find_aen
 2084  * Description:         Reports whether a given AEN ever occurred.
 2085  *
 2086  * Input:               sc      -- ptr to per ctlr structure
 2087  *                      aen_code-- AEN to look for
 2088  * Output:              None
 2089  * Return value:        0       -- success
 2090  *                      non-zero-- failure
 2091  */
 2092 static int
 2093 twa_find_aen(struct twa_softc *sc, u_int16_t aen_code)
 2094 {
 2095         u_int32_t       last_index;
 2096         int             s;
 2097         int             i;
 2098 
 2099         s = splcam();
 2100 
 2101         if (sc->twa_aen_queue_wrapped)
 2102                 last_index = sc->twa_aen_head;
 2103         else
 2104                 last_index = 0;
 2105 
 2106         i = sc->twa_aen_head;
 2107         do {
 2108                 i = (i + TWA_Q_LENGTH - 1) % TWA_Q_LENGTH;
 2109                 if ((sc->twa_aen_queue[i])->aen_code == aen_code) {
 2110                         splx(s);
 2111                         return(0);
 2112                 }
 2113         } while (i != last_index);
 2114 
 2115         splx(s);
 2116         return(1);
 2117 }
 2118 
 2119 
 2120 
 2121 /*
 2122  * Function name:       twa_find_msg_string
 2123  * Description:         Looks up a given table, and returns the message string
 2124  *                      corresponding to a given code (error code or AEN code).
 2125  *
 2126  * Input:               sc      -- ptr to per ctlr structure
 2127  *                      code    -- code, the message string corresponding to
 2128  *                                 which is to be returned.
 2129  * Output:              None
 2130  * Return value:        ptr to corresponding msg string -- success
 2131  *                      NULL                            -- failure
 2132  */
 2133 char *
 2134 twa_find_msg_string(struct twa_message *table, u_int16_t code)
 2135 {
 2136         int     i;
 2137 
 2138         for (i = 0; table[i].message != NULL; i++)
 2139                 if (table[i].code == code)
 2140                         return(table[i].message);
 2141 
 2142         return(table[i].message);
 2143 }
 2144 
 2145 
 2146 
 2147 /*
 2148  * Function name:       twa_get_request
 2149  * Description:         Gets a request pkt from the free queue.
 2150  *
 2151  * Input:               sc      -- ptr to per ctlr structure
 2152  * Output:              None
 2153  * Return value:        ptr to request pkt      -- success
 2154  *                      NULL                    -- failure
 2155  */
 2156 struct twa_request *
 2157 twa_get_request(struct twa_softc *sc)
 2158 {
 2159         struct twa_request      *tr;
 2160 
 2161         twa_dbg_dprint_enter(4, sc);
 2162 
 2163         /* Get a free request packet. */
 2164         tr = twa_dequeue_free(sc);
 2165 
 2166         /* Initialize some fields to their defaults. */
 2167         if (tr) {
 2168                 tr->tr_data = NULL;
 2169                 tr->tr_real_data = NULL;
 2170                 tr->tr_length = 0;
 2171                 tr->tr_real_length = 0;
 2172                 tr->tr_status = TWA_CMD_SETUP;/* command is in setup phase */
 2173                 tr->tr_flags = 0;
 2174                 tr->tr_error = 0;
 2175                 tr->tr_private = NULL;
 2176                 tr->tr_callback = NULL;
 2177                 tr->tr_cmd_pkt_type = 0;
 2178 
 2179                 /*
 2180                  * Look at the status field in the command packet to see how
 2181                  * it completed the last time it was used, and zero out only
 2182                  * the portions that might have changed.  Note that we don't
 2183                  * care to zero out the sglist.
 2184                  */
 2185                 if (tr->tr_command->command.cmd_pkt_9k.status)
 2186                         bzero(tr->tr_command,
 2187                                 sizeof(struct twa_command_header) + 28 /* max bytes before sglist */);
 2188                 else
 2189                         bzero(&(tr->tr_command->command), 28 /* max bytes before sglist */);
 2190         }
 2191         return(tr);
 2192 }
 2193 
 2194 
 2195 
 2196 /*
 2197  * Function name:       twa_release_request
 2198  * Description:         Puts a request pkt into the free queue.
 2199  *
 2200  * Input:               tr      -- ptr to request pkt to be freed
 2201  * Output:              None
 2202  * Return value:        None
 2203  */
 2204 void
 2205 twa_release_request(struct twa_request *tr)
 2206 {
 2207         twa_dbg_dprint_enter(4, tr->tr_sc);
 2208 
 2209         twa_enqueue_free(tr);
 2210 }
 2211 
 2212 
 2213 
 2214 /*
 2215  * Function name:       twa_describe_controller
 2216  * Description:         Describes the controller, in terms of its fw version,
 2217  *                      BIOS version etc.
 2218  *
 2219  * Input:               sc      -- ptr to per ctlr structure
 2220  * Output:              None
 2221  * Return value:        None
 2222  */
 2223 void
 2224 twa_describe_controller(struct twa_softc *sc)
 2225 {
 2226         struct twa_param_9k     *p[6];
 2227         u_int8_t                num_ports = 0;
 2228 
 2229         twa_dbg_dprint_enter(2, sc);
 2230 
 2231         /* Get the port count. */
 2232         p[0] = twa_get_param(sc, TWA_PARAM_CONTROLLER_TABLE,
 2233                                 TWA_PARAM_CONTROLLER_PORT_COUNT, 1, NULL);
 2234         if (p[0]) {
 2235                 num_ports = *(u_int8_t *)(p[0]->data);
 2236                 free(p[0], M_DEVBUF);
 2237         }
 2238 
 2239         /* Get the firmware and BIOS versions. */
 2240         p[0] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
 2241                                 TWA_PARAM_VERSION_FW, 16, NULL);
 2242         p[1] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
 2243                                 TWA_PARAM_VERSION_BIOS, 16, NULL);
 2244 
 2245         twa_printf(sc, "%d ports, Firmware %.16s, BIOS %.16s\n",
 2246                         num_ports, p[0]?(p[0]->data):NULL, p[1]?(p[1]->data):NULL);
 2247         if (bootverbose) {
 2248                 /* Get more versions. */
 2249                 p[2] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
 2250                                         TWA_PARAM_VERSION_MONITOR, 16, NULL);
 2251                 p[3] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
 2252                                         TWA_PARAM_VERSION_PCBA, 8, NULL);
 2253                 p[4] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
 2254                                         TWA_PARAM_VERSION_ATA, 8, NULL);
 2255                 p[5] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
 2256                                         TWA_PARAM_VERSION_PCI, 8, NULL);
 2257 
 2258                 twa_printf(sc, "Monitor %.16s, PCB %.8s, Achip %.8s, Pchip %.8s\n",
 2259                                 p[2]?(p[2]->data):NULL, p[3]?(p[3]->data):NULL,
 2260                                 p[4]?(p[4]->data):NULL, p[5]?(p[5]->data):NULL);
 2261 
 2262                 if (p[2])
 2263                         free(p[2], M_DEVBUF);
 2264                 if (p[3])
 2265                         free(p[3], M_DEVBUF);
 2266                 if (p[4])
 2267                         free(p[4], M_DEVBUF);
 2268                 if (p[5])
 2269                         free(p[5], M_DEVBUF);
 2270         }
 2271         if (p[0])
 2272                 free(p[0], M_DEVBUF);
 2273         if (p[1])
 2274                 free(p[1], M_DEVBUF);
 2275 }
 2276 
 2277 
 2278 
 2279 /*
 2280  * Function name:       twa_check_ctlr_state
 2281  * Description:         Makes sure that the fw status register reports a
 2282  *                      proper status.
 2283  *
 2284  * Input:               sc              -- ptr to per ctlr structure
 2285  *                      status_reg      -- value in the status register
 2286  * Output:              None
 2287  * Return value:        0       -- no errors
 2288  *                      non-zero-- errors
 2289  */
 2290 static int
 2291 twa_check_ctlr_state(struct twa_softc *sc, u_int32_t status_reg)
 2292 {
 2293         int             result = 0;
 2294         static time_t   last_warning[2] = {0, 0};
 2295 
 2296         /* Check if the 'micro-controller ready' bit is not set. */
 2297         if ((status_reg & TWA_STATUS_EXPECTED_BITS) !=
 2298                                 TWA_STATUS_EXPECTED_BITS) {
 2299                 if (time_second > (last_warning[0] + 5)) {
 2300                         twa_printf(sc, "Missing expected status bit(s) %b\n",
 2301                                         ~status_reg & TWA_STATUS_EXPECTED_BITS,
 2302                                         TWA_STATUS_BITS_DESCRIPTION);
 2303                         last_warning[0] = time_second;
 2304                 }
 2305                 result = 1;
 2306         }
 2307 
 2308         /* Check if any error bits are set. */
 2309         if ((status_reg & TWA_STATUS_UNEXPECTED_BITS) != 0) {
 2310                 if (time_second > (last_warning[1] + 5)) {
 2311                         twa_printf(sc, "Unexpected status bit(s) %b\n",
 2312                                         status_reg & TWA_STATUS_UNEXPECTED_BITS,
 2313                                         TWA_STATUS_BITS_DESCRIPTION);
 2314                         last_warning[1] = time_second;
 2315                 }
 2316                 if (status_reg & TWA_STATUS_PCI_PARITY_ERROR_INTERRUPT) {
 2317                         twa_printf(sc, "PCI parity error: clearing... Re-seat/move/replace card.\n");
 2318                         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_PARITY_ERROR);
 2319                         twa_write_pci_config(sc, TWA_PCI_CONFIG_CLEAR_PARITY_ERROR, 2);
 2320                 }
 2321                 if (status_reg & TWA_STATUS_PCI_ABORT_INTERRUPT) {
 2322                         twa_printf(sc, "PCI abort: clearing...\n");
 2323                         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_PCI_ABORT);
 2324                         twa_write_pci_config(sc, TWA_PCI_CONFIG_CLEAR_PCI_ABORT, 2);
 2325                 }
 2326                 if (status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) {
 2327                         twa_printf(sc, "Controller queue error: clearing...\n");
 2328                         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_PCI_ABORT);
 2329                 }
 2330                 if (status_reg & TWA_STATUS_SBUF_WRITE_ERROR) {
 2331                         twa_printf(sc, "SBUF write error: clearing...\n");
 2332                         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_SBUF_WRITE_ERROR);
 2333                 }
 2334                 if (status_reg & TWA_STATUS_MICROCONTROLLER_ERROR) {
 2335                         twa_printf(sc, "Micro-controller error!\n");
 2336                         result = 1;
 2337                 }
 2338         }
 2339         return(result);
 2340 }       
 2341 
 2342 
 2343 
 2344 /*
 2345  * Function name:       twa_print_controller
 2346  * Description:         Prints the current status of the controller.
 2347  *
 2348  * Input:               sc      -- ptr to per ctlr structure
 2349  * Output:              None
 2350  * Return value:        None
 2351  */
 2352 void
 2353 twa_print_controller(struct twa_softc *sc)
 2354 {
 2355         u_int32_t       status_reg;
 2356 
 2357         /* Print current controller details. */
 2358         status_reg = TWA_READ_STATUS_REGISTER(sc);
 2359         twa_printf(sc, "status   %b\n", status_reg, TWA_STATUS_BITS_DESCRIPTION);
 2360 #ifdef TWA_DEBUG
 2361         twa_printf(sc, "q type    current  max\n");
 2362         twa_printf(sc, "free      %04d     %04d\n",
 2363                 sc->twa_qstats[TWAQ_FREE].q_length, sc->twa_qstats[TWAQ_FREE].q_max);
 2364         twa_printf(sc, "busy      %04d     %04d\n",
 2365                 sc->twa_qstats[TWAQ_BUSY].q_length, sc->twa_qstats[TWAQ_BUSY].q_max);
 2366         twa_printf(sc, "pending   %04d     %04d\n",
 2367                 sc->twa_qstats[TWAQ_PENDING].q_length, sc->twa_qstats[TWAQ_PENDING].q_max);
 2368         twa_printf(sc, "complete  %04d     %04d\n",
 2369                 sc->twa_qstats[TWAQ_COMPLETE].q_length, sc->twa_qstats[TWAQ_COMPLETE].q_max);
 2370 #endif /* TWA_DEBUG */
 2371         twa_printf(sc, "AEN queue head %d  tail %d\n",
 2372                         sc->twa_aen_head, sc->twa_aen_tail);
 2373 }       
 2374 
 2375 
 2376 
 2377 /*
 2378  * Function name:       twa_panic
 2379  * Description:         Called when something is seriously wrong with the ctlr.
 2380  *                      Hits the debugger if the debugger is turned on, else
 2381  *                      resets the ctlr.
 2382  *
 2383  * Input:               sc      -- ptr to per ctlr structure
 2384  *                      reason  -- string describing what went wrong
 2385  * Output:              None
 2386  * Return value:        None
 2387  */
 2388 static void
 2389 twa_panic(struct twa_softc *sc, int8_t *reason)
 2390 {
 2391         twa_print_controller(sc);
 2392 #ifdef TWA_DEBUG
 2393         panic(reason);
 2394 #else
 2395         twa_printf(sc, "twa_panic: RESETTING CONTROLLER...\n");
 2396         twa_reset(sc);
 2397 #endif
 2398 }
 2399 

Cache object: 17add03a97cc728b9069748d96385f8a


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