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/tw_cl_intr.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
    5  * Copyright (c) 2004-05 Vinod Kashyap
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      $FreeBSD: releng/12.0/sys/dev/twa/tw_cl_intr.c 326255 2017-11-27 14:52:40Z pfg $
   30  */
   31 
   32 /*
   33  * AMCC'S 3ware driver for 9000 series storage controllers.
   34  *
   35  * Author: Vinod Kashyap
   36  * Modifications by: Adam Radford
   37  * Modifications by: Manjunath Ranganathaiah
   38  */
   39 
   40 
   41 /*
   42  * Common Layer interrupt handling functions.
   43  */
   44 
   45 
   46 #include "tw_osl_share.h"
   47 #include "tw_cl_share.h"
   48 #include "tw_cl_fwif.h"
   49 #include "tw_cl_ioctl.h"
   50 #include "tw_cl.h"
   51 #include "tw_cl_externs.h"
   52 #include "tw_osl_ioctl.h"
   53 
   54 
   55 
   56 /*
   57  * Function name:       twa_interrupt
   58  * Description:         Interrupt handler.  Determines the kind of interrupt,
   59  *                      and returns TW_CL_TRUE if it recognizes the interrupt.
   60  *
   61  * Input:               ctlr_handle     -- controller handle
   62  * Output:              None
   63  * Return value:        TW_CL_TRUE -- interrupt recognized
   64  *                      TW_CL_FALSE-- interrupt not recognized
   65  */
   66 TW_INT32
   67 tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle)
   68 {
   69         struct tw_cli_ctlr_context      *ctlr =
   70                 (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
   71         TW_UINT32                       status_reg;
   72         TW_INT32                        rc = TW_CL_FALSE;
   73 
   74         tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
   75 
   76         /* If we don't have controller context, bail */
   77         if (ctlr == NULL)
   78                 goto out;
   79 
   80         /*
   81          * Bail If we get an interrupt while resetting, or shutting down.
   82          */
   83         if (ctlr->reset_in_progress || !(ctlr->active))
   84                 goto out;
   85 
   86         /* Read the status register to determine the type of interrupt. */
   87         status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
   88         if (tw_cli_check_ctlr_state(ctlr, status_reg))
   89                 goto out;
   90 
   91         /* Clear the interrupt. */
   92         if (status_reg & TWA_STATUS_HOST_INTERRUPT) {
   93                 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
   94                         "Host interrupt");
   95                 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
   96                         TWA_CONTROL_CLEAR_HOST_INTERRUPT);
   97         }
   98         if (status_reg & TWA_STATUS_ATTENTION_INTERRUPT) {
   99                 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
  100                         "Attention interrupt");
  101                 rc |= TW_CL_TRUE; /* request for a deferred isr call */
  102                 tw_cli_process_attn_intr(ctlr);
  103                 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
  104                         TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
  105         }
  106         if (status_reg & TWA_STATUS_COMMAND_INTERRUPT) {
  107                 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
  108                         "Command interrupt");
  109                 rc |= TW_CL_TRUE; /* request for a deferred isr call */
  110                 tw_cli_process_cmd_intr(ctlr);
  111                 if ((TW_CL_Q_FIRST_ITEM(&(ctlr->req_q_head[TW_CLI_PENDING_Q]))) == TW_CL_NULL)
  112                         TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
  113                                 TWA_CONTROL_MASK_COMMAND_INTERRUPT);
  114         }
  115         if (status_reg & TWA_STATUS_RESPONSE_INTERRUPT) {
  116                 tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(),
  117                         "Response interrupt");
  118                 rc |= TW_CL_TRUE; /* request for a deferred isr call */
  119                 tw_cli_process_resp_intr(ctlr);
  120         }
  121 out:
  122         return(rc);
  123 }
  124 
  125 
  126 
  127 /*
  128  * Function name:       tw_cli_process_host_intr
  129  * Description:         This function gets called if we triggered an interrupt.
  130  *                      We don't use it as of now.
  131  *
  132  * Input:               ctlr    -- ptr to CL internal ctlr context
  133  * Output:              None
  134  * Return value:        None
  135  */
  136 TW_VOID
  137 tw_cli_process_host_intr(struct tw_cli_ctlr_context *ctlr)
  138 {
  139         tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  140 }
  141 
  142 
  143 
  144 /*
  145  * Function name:       tw_cli_process_attn_intr
  146  * Description:         This function gets called if the fw posted an AEN
  147  *                      (Asynchronous Event Notification).  It fetches
  148  *                      all the AEN's that the fw might have posted.
  149  *
  150  * Input:               ctlr    -- ptr to CL internal ctlr context
  151  * Output:              None
  152  * Return value:        None
  153  */
  154 TW_VOID
  155 tw_cli_process_attn_intr(struct tw_cli_ctlr_context *ctlr)
  156 {
  157         TW_INT32        error;
  158 
  159         tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  160 
  161         if ((error = tw_cli_get_aen(ctlr))) {
  162                 /*
  163                  * If the driver is already in the process of retrieveing AEN's,
  164                  * we will be returned TW_OSL_EBUSY.  In this case,
  165                  * tw_cli_param_callback or tw_cli_aen_callback will eventually
  166                  * retrieve the AEN this attention interrupt is for.  So, we
  167                  * don't need to print the failure.
  168                  */ 
  169                 if (error != TW_OSL_EBUSY)
  170                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  171                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  172                                 0x1200, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  173                                 "Failed to fetch AEN",
  174                                 "error = %d", error);
  175         }
  176 }
  177 
  178 
  179 
  180 /*
  181  * Function name:       tw_cli_process_cmd_intr
  182  * Description:         This function gets called if we hit a queue full
  183  *                      condition earlier, and the fw is now ready for
  184  *                      new cmds.  Submits any pending requests.
  185  *
  186  * Input:               ctlr    -- ptr to CL internal ctlr context
  187  * Output:              None
  188  * Return value:        None
  189  */
  190 TW_VOID
  191 tw_cli_process_cmd_intr(struct tw_cli_ctlr_context *ctlr)
  192 {
  193         tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  194 
  195         /* Start any requests that might be in the pending queue. */
  196         tw_cli_submit_pending_queue(ctlr);
  197 
  198         /*
  199          * If tw_cli_submit_pending_queue was unsuccessful due to a "cmd queue
  200          * full" condition, cmd_intr will already have been unmasked by
  201          * tw_cli_submit_cmd.  We don't need to do it again... simply return.
  202          */
  203 }
  204 
  205 
  206 
  207 /*
  208  * Function name:       tw_cli_process_resp_intr
  209  * Description:         Looks for cmd completions from fw; queues cmds completed
  210  *                      by fw into complete queue.
  211  *
  212  * Input:               ctlr    -- ptr to CL internal ctlr context
  213  * Output:              None
  214  * Return value:        0       -- no ctlr error
  215  *                      non-zero-- ctlr error
  216  */
  217 TW_INT32
  218 tw_cli_process_resp_intr(struct tw_cli_ctlr_context *ctlr)
  219 {
  220         TW_UINT32                       resp;
  221         struct tw_cli_req_context       *req;
  222         TW_INT32                        error;
  223         TW_UINT32                       status_reg;
  224     
  225         tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  226 
  227         for (;;) {
  228                 status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
  229                 if ((error = tw_cli_check_ctlr_state(ctlr, status_reg)))
  230                         break;
  231                 if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY) {
  232                         tw_cli_dbg_printf(7, ctlr->ctlr_handle,
  233                                 tw_osl_cur_func(), "Response queue empty");
  234                         break;
  235                 }
  236 
  237                 /* Response queue is not empty. */
  238                 resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
  239                 {
  240                         req = &(ctlr->req_ctxt_buf[GET_RESP_ID(resp)]);
  241                 }
  242 
  243                 if (req->state != TW_CLI_REQ_STATE_BUSY) {
  244                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  245                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  246                                 0x1201, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  247                                 "Unposted command completed!!",
  248                                 "request = %p, status = %d",
  249                                 req, req->state);
  250 #ifdef TW_OSL_DEBUG
  251                         tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
  252 #endif /* TW_OSL_DEBUG */
  253                         continue;
  254                 }
  255 
  256                 /*
  257                  * Remove the request from the busy queue, mark it as complete,
  258                  * and enqueue it in the complete queue.
  259                  */
  260                 tw_cli_req_q_remove_item(req, TW_CLI_BUSY_Q);
  261                 req->state = TW_CLI_REQ_STATE_COMPLETE;
  262                 tw_cli_req_q_insert_tail(req, TW_CLI_COMPLETE_Q);
  263 
  264         }
  265 
  266         /* Complete this, and other requests in the complete queue. */
  267         tw_cli_process_complete_queue(ctlr);
  268         
  269         return(error);
  270 }
  271 
  272 
  273 
  274 /*
  275  * Function name:       tw_cli_submit_pending_queue
  276  * Description:         Kick starts any requests in the pending queue.
  277  *
  278  * Input:               ctlr    -- ptr to CL internal ctlr context
  279  * Output:              None
  280  * Return value:        0       -- all pending requests submitted successfully
  281  *                      non-zero-- otherwise
  282  */
  283 TW_INT32
  284 tw_cli_submit_pending_queue(struct tw_cli_ctlr_context *ctlr)
  285 {
  286         struct tw_cli_req_context       *req;
  287         TW_INT32                        error = TW_OSL_ESUCCESS;
  288     
  289         tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  290         
  291         /*
  292          * Pull requests off the pending queue, and submit them.
  293          */
  294         while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) !=
  295                 TW_CL_NULL) {
  296                 if ((error = tw_cli_submit_cmd(req))) {
  297                         if (error == TW_OSL_EBUSY) {
  298                                 tw_cli_dbg_printf(2, ctlr->ctlr_handle,
  299                                         tw_osl_cur_func(),
  300                                         "Requeueing pending request");
  301                                 req->state = TW_CLI_REQ_STATE_PENDING;
  302                                 /*
  303                                  * Queue the request at the head of the pending
  304                                  * queue, and break away, so we don't try to
  305                                  * submit any more requests.
  306                                  */
  307                                 tw_cli_req_q_insert_head(req, TW_CLI_PENDING_Q);
  308                                 break;
  309                         } else {
  310                                 tw_cl_create_event(ctlr->ctlr_handle,
  311                                         TW_CL_FALSE,
  312                                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  313                                         0x1202, 0x1,
  314                                         TW_CL_SEVERITY_ERROR_STRING,
  315                                         "Could not start request "
  316                                         "in pending queue",
  317                                         "request = %p, opcode = 0x%x, "
  318                                         "error = %d", req,
  319                                         GET_OPCODE(req->cmd_pkt->
  320                                                 command.cmd_pkt_9k.res__opcode),
  321                                         error);
  322                                 /*
  323                                  * Set the appropriate error and call the CL
  324                                  * internal callback if there's one.  If the
  325                                  * request originator is polling for completion,
  326                                  * he should be checking req->error to
  327                                  * determine that the request did not go
  328                                  * through.  The request originators are
  329                                  * responsible for the clean-up.
  330                                  */
  331                                 req->error_code = error;
  332                                 req->state = TW_CLI_REQ_STATE_COMPLETE;
  333                                 if (req->tw_cli_callback)
  334                                         req->tw_cli_callback(req);
  335                                 error = TW_OSL_ESUCCESS;
  336                         }
  337                 }
  338         }
  339         return(error);
  340 }
  341 
  342 
  343 
  344 /*
  345  * Function name:       tw_cli_process_complete_queue
  346  * Description:         Calls the CL internal callback routine, if any, for
  347  *                      each request in the complete queue.
  348  *
  349  * Input:               ctlr    -- ptr to CL internal ctlr context
  350  * Output:              None
  351  * Return value:        None
  352  */
  353 TW_VOID
  354 tw_cli_process_complete_queue(struct tw_cli_ctlr_context *ctlr)
  355 {
  356         struct tw_cli_req_context       *req;
  357     
  358         tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  359 
  360         /*
  361          * Pull commands off the completed list, dispatch them appropriately.
  362          */
  363         while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) !=
  364                 TW_CL_NULL) {
  365                 /* Call the CL internal callback, if there's one. */
  366                 if (req->tw_cli_callback)
  367                         req->tw_cli_callback(req);
  368         }
  369 }
  370 
  371 
  372 
  373 /*
  374  * Function name:       tw_cli_complete_io
  375  * Description:         CL internal callback for SCSI/fw passthru requests.
  376  *
  377  * Input:               req     -- ptr to CL internal request context
  378  * Output:              None
  379  * Return value:        None
  380  */
  381 TW_VOID
  382 tw_cli_complete_io(struct tw_cli_req_context *req)
  383 {
  384         struct tw_cli_ctlr_context      *ctlr = req->ctlr;
  385         struct tw_cl_req_packet         *req_pkt =
  386                 (struct tw_cl_req_packet *)(req->orig_req);
  387 
  388         tw_cli_dbg_printf(8, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  389 
  390         req_pkt->status = TW_CL_ERR_REQ_SUCCESS;
  391         if (req->error_code) {
  392                 req_pkt->status = TW_CL_ERR_REQ_UNABLE_TO_SUBMIT_COMMAND;
  393                 goto out;
  394         }
  395 
  396         if (req->state != TW_CLI_REQ_STATE_COMPLETE) {
  397                 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  398                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  399                         0x1203, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  400                         "I/O completion on incomplete command!!",
  401                         "request = %p, status = %d",
  402                         req, req->state);
  403 #ifdef TW_OSL_DEBUG
  404                 tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
  405 #endif /* TW_OSL_DEBUG */
  406                 return;
  407         }
  408 
  409         if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
  410                 /* Copy the command packet back into OSL's space. */
  411                 tw_osl_memcpy(req_pkt->gen_req_pkt.pt_req.cmd_pkt, req->cmd_pkt,
  412                         sizeof(struct tw_cl_command_packet));
  413         } else
  414                 tw_cli_scsi_complete(req);
  415 
  416 out:
  417         req_pkt->tw_osl_callback(req->req_handle);
  418         tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
  419 }
  420 
  421 
  422 
  423 /*
  424  * Function name:       tw_cli_scsi_complete
  425  * Description:         Completion routine for SCSI requests.
  426  *
  427  * Input:               req     -- ptr to CL internal request context
  428  * Output:              None
  429  * Return value:        None
  430  */
  431 TW_VOID
  432 tw_cli_scsi_complete(struct tw_cli_req_context *req)
  433 {
  434         struct tw_cl_req_packet         *req_pkt =
  435                 (struct tw_cl_req_packet *)(req->orig_req);
  436         struct tw_cl_scsi_req_packet    *scsi_req =
  437                 &(req_pkt->gen_req_pkt.scsi_req);
  438         struct tw_cl_command_9k         *cmd =
  439                 &(req->cmd_pkt->command.cmd_pkt_9k);
  440         struct tw_cl_command_header     *cmd_hdr;
  441         TW_UINT16                       error;
  442         TW_UINT8                        *cdb;
  443 
  444         tw_cli_dbg_printf(8, req->ctlr->ctlr_handle, tw_osl_cur_func(),
  445                 "entered");
  446 
  447         scsi_req->scsi_status = cmd->status;
  448         if (! cmd->status)
  449                 return;
  450 
  451         tw_cli_dbg_printf(1, req->ctlr->ctlr_handle, tw_osl_cur_func(),
  452                 "req_id = 0x%x, status = 0x%x",
  453                 GET_REQ_ID(cmd->lun_l4__req_id), cmd->status);
  454 
  455         cmd_hdr = &(req->cmd_pkt->cmd_hdr);
  456         error = cmd_hdr->status_block.error;
  457         if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
  458                         (error == TWA_ERROR_UNIT_OFFLINE)) {
  459                 if (GET_LUN_L4(cmd->lun_l4__req_id))
  460                         req_pkt->status |= TW_CL_ERR_REQ_INVALID_LUN;
  461                 else
  462                         req_pkt->status |= TW_CL_ERR_REQ_INVALID_TARGET;
  463         } else {
  464                 tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
  465                         tw_osl_cur_func(),
  466                         "cmd = %x %x %x %x %x %x %x",
  467                         GET_OPCODE(cmd->res__opcode),
  468                         GET_SGL_OFF(cmd->res__opcode),
  469                         cmd->unit,
  470                         cmd->lun_l4__req_id,
  471                         cmd->status,
  472                         cmd->sgl_offset,
  473                         cmd->lun_h4__sgl_entries);
  474 
  475                 cdb = (TW_UINT8 *)(cmd->cdb);
  476                 tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
  477                         tw_osl_cur_func(),
  478                         "cdb = %x %x %x %x %x %x %x %x "
  479                         "%x %x %x %x %x %x %x %x",
  480                         cdb[0], cdb[1], cdb[2], cdb[3],
  481                         cdb[4], cdb[5], cdb[6], cdb[7],
  482                         cdb[8], cdb[9], cdb[10], cdb[11],
  483                         cdb[12], cdb[13], cdb[14], cdb[15]);
  484 
  485 #if       0
  486                 /* 
  487                  * Print the error. Firmware doesn't yet support
  488                  * the 'Mode Sense' cmd.  Don't print if the cmd
  489                  * is 'Mode Sense', and the error is 'Invalid field
  490                  * in CDB'.
  491                  */
  492                 if (! ((cdb[0] == 0x1A) && (error == 0x10D)))
  493                         tw_cli_create_ctlr_event(req->ctlr,
  494                                 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
  495                                 cmd_hdr);
  496 #endif // 0
  497         }
  498 
  499         if (scsi_req->sense_data) {
  500                 tw_osl_memcpy(scsi_req->sense_data, cmd_hdr->sense_data,
  501                         TWA_SENSE_DATA_LENGTH);
  502                 scsi_req->sense_len = TWA_SENSE_DATA_LENGTH;
  503                 req_pkt->status |= TW_CL_ERR_REQ_AUTO_SENSE_VALID;
  504         }
  505         req_pkt->status |= TW_CL_ERR_REQ_SCSI_ERROR;
  506 }
  507 
  508 
  509 
  510 /*
  511  * Function name:       tw_cli_param_callback
  512  * Description:         Callback for get/set_param requests.
  513  *
  514  * Input:               req     -- ptr to completed request pkt
  515  * Output:              None
  516  * Return value:        None
  517  */
  518 TW_VOID
  519 tw_cli_param_callback(struct tw_cli_req_context *req)
  520 {
  521         struct tw_cli_ctlr_context      *ctlr = req->ctlr;
  522         union tw_cl_command_7k          *cmd =
  523                 &(req->cmd_pkt->command.cmd_pkt_7k);
  524         TW_INT32                        error;
  525 
  526         tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  527 
  528         /*
  529          * If the request was never submitted to the controller, the function
  530          * that sets req->error is responsible for calling tw_cl_create_event.
  531          */
  532         if (! req->error_code)
  533                 if (cmd->param.status) {
  534 #if       0
  535                         tw_cli_create_ctlr_event(ctlr,
  536                                 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
  537                                 &(req->cmd_pkt->cmd_hdr));
  538 #endif // 0
  539                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  540                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  541                                 0x1204, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  542                                 "get/set_param failed",
  543                                 "status = %d", cmd->param.status);
  544                 }
  545 
  546         ctlr->internal_req_busy = TW_CL_FALSE;
  547         tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
  548 
  549         if ((ctlr->get_more_aens) && (!(ctlr->reset_in_progress))) {
  550                 ctlr->get_more_aens = TW_CL_FALSE;
  551                 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  552                         "Fetching more AEN's");
  553                 if ((error = tw_cli_get_aen(ctlr)))
  554                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  555                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  556                                 0x1205, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  557                                 "Failed to fetch all AEN's from param_callback",
  558                                 "error = %d", error);
  559         }
  560 }
  561 
  562 
  563 
  564 /*
  565  * Function name:       tw_cli_aen_callback
  566  * Description:         Callback for requests to fetch AEN's.
  567  *
  568  * Input:               req     -- ptr to completed request pkt
  569  * Output:              None
  570  * Return value:        None
  571  */
  572 TW_VOID
  573 tw_cli_aen_callback(struct tw_cli_req_context *req)
  574 {
  575         struct tw_cli_ctlr_context      *ctlr = req->ctlr;
  576         struct tw_cl_command_header     *cmd_hdr;
  577         struct tw_cl_command_9k         *cmd =
  578                 &(req->cmd_pkt->command.cmd_pkt_9k);
  579         TW_UINT16                       aen_code = TWA_AEN_QUEUE_EMPTY;
  580         TW_INT32                        error;
  581 
  582         tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  583 
  584         tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  585                 "req_id = 0x%x, req error = %d, status = 0x%x",
  586                 GET_REQ_ID(cmd->lun_l4__req_id), req->error_code, cmd->status);
  587 
  588         /*
  589          * If the request was never submitted to the controller, the function
  590          * that sets error is responsible for calling tw_cl_create_event.
  591          */
  592         if (!(error = req->error_code))
  593                 if ((error = cmd->status)) {
  594                         cmd_hdr = (struct tw_cl_command_header *)
  595                                 (&(req->cmd_pkt->cmd_hdr));
  596 #if       0
  597                         tw_cli_create_ctlr_event(ctlr,
  598                                 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
  599                                 cmd_hdr);
  600 #endif // 0
  601                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  602                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  603                                 0x1206, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  604                                 "Request Sense failed",
  605                                 "opcode = 0x%x, status = %d",
  606                                 GET_OPCODE(cmd->res__opcode), cmd->status);
  607                 }
  608 
  609         if (error) {
  610                 ctlr->internal_req_busy = TW_CL_FALSE;
  611                 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
  612                 return;
  613         }
  614 
  615         tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  616                 "Request Sense command succeeded");
  617 
  618         aen_code = tw_cli_manage_aen(ctlr, req);
  619 
  620         if (aen_code != TWA_AEN_SYNC_TIME_WITH_HOST) {
  621                 ctlr->internal_req_busy = TW_CL_FALSE;
  622                 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
  623                 if (aen_code != TWA_AEN_QUEUE_EMPTY)
  624                         if ((error = tw_cli_get_aen(ctlr)))
  625                                 tw_cl_create_event(ctlr->ctlr_handle,
  626                                         TW_CL_FALSE,
  627                                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  628                                         0x1207, 0x1,
  629                                         TW_CL_SEVERITY_ERROR_STRING,
  630                                         "Failed to fetch all AEN's",
  631                                         "error = %d", error);
  632         }
  633 }
  634 
  635 
  636 
  637 /*
  638  * Function name:       tw_cli_manage_aen
  639  * Description:         Handles AEN's.
  640  *
  641  * Input:               ctlr    -- ptr to CL internal ctlr context
  642  *                      req     -- ptr to CL internal request context
  643  * Output:              None
  644  * Return value:        None
  645  */
  646 TW_UINT16
  647 tw_cli_manage_aen(struct tw_cli_ctlr_context *ctlr,
  648         struct tw_cli_req_context *req)
  649 {
  650         struct tw_cl_command_header     *cmd_hdr;
  651         TW_UINT16                       aen_code;
  652         TW_TIME                         local_time;
  653         TW_TIME                         sync_time;
  654         TW_UINT32                       error;
  655 
  656         tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  657 
  658         cmd_hdr = (struct tw_cl_command_header *)(req->data);
  659         aen_code = cmd_hdr->status_block.error;
  660 
  661         switch (aen_code) {
  662         case TWA_AEN_SYNC_TIME_WITH_HOST:
  663                 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  664                         "Received AEN_SYNC_TIME");
  665                 /*
  666                  * Free the internal req pkt right here, since
  667                  * tw_cli_set_param will need it.
  668                  */
  669                 ctlr->internal_req_busy = TW_CL_FALSE;
  670                 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
  671 
  672                 /*
  673                  * We will use a callback in tw_cli_set_param only when
  674                  * interrupts are enabled and we can expect our callback
  675                  * to get called.  Setting the get_more_aens
  676                  * flag will make the callback continue to try to retrieve
  677                  * more AEN's.
  678                  */
  679                 if (ctlr->interrupts_enabled)
  680                         ctlr->get_more_aens = TW_CL_TRUE;
  681                 /* Calculate time (in seconds) since last Sunday 12.00 AM. */
  682                 local_time = tw_osl_get_local_time();
  683                 sync_time = (local_time - (3 * 86400)) % 604800;
  684                 if ((error = tw_cli_set_param(ctlr, TWA_PARAM_TIME_TABLE,
  685                                 TWA_PARAM_TIME_SCHED_TIME, 4,
  686                                 &sync_time,
  687                                 (ctlr->interrupts_enabled)
  688                                 ? tw_cli_param_callback : TW_CL_NULL)))
  689                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  690                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  691                                 0x1208, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  692                                 "Unable to sync time with ctlr",
  693                                 "error = %d", error);
  694 
  695                 break;
  696 
  697 
  698         case TWA_AEN_QUEUE_EMPTY:
  699                 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  700                         "AEN queue empty");
  701                 break;
  702 
  703 
  704         default:
  705                 /* Queue the event. */
  706 
  707                 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  708                         "Queueing AEN");
  709                 tw_cli_create_ctlr_event(ctlr,
  710                         TW_CL_MESSAGE_SOURCE_CONTROLLER_EVENT,
  711                         cmd_hdr);
  712                 break;
  713         } /* switch */
  714         return(aen_code);
  715 }
  716 
  717 
  718 
  719 /*
  720  * Function name:       tw_cli_enable_interrupts
  721  * Description:         Enables interrupts on the controller
  722  *
  723  * Input:               ctlr    -- ptr to CL internal ctlr context
  724  * Output:              None
  725  * Return value:        None
  726  */
  727 TW_VOID
  728 tw_cli_enable_interrupts(struct tw_cli_ctlr_context *ctlr)
  729 {
  730         tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  731 
  732         ctlr->interrupts_enabled = TW_CL_TRUE;
  733         TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
  734                 TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT |
  735                 TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT |
  736                 TWA_CONTROL_ENABLE_INTERRUPTS);
  737 }
  738 
  739 
  740 
  741 /*
  742  * Function name:       twa_setup
  743  * Description:         Disables interrupts on the controller
  744  *
  745  * Input:               ctlr    -- ptr to CL internal ctlr context
  746  * Output:              None
  747  * Return value:        None
  748  */
  749 TW_VOID
  750 tw_cli_disable_interrupts(struct tw_cli_ctlr_context *ctlr)
  751 {
  752         tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  753 
  754         TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
  755                 TWA_CONTROL_DISABLE_INTERRUPTS);
  756         ctlr->interrupts_enabled = TW_CL_FALSE;
  757 }
  758 

Cache object: a65972acd5b3d9f459c5a520b0de2294


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