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

Cache object: 76d90c18895a749f070ab36418eb2bcc


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