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

Cache object: bd951047cb8743a56f9a6a0d9e19c478


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