/* * Function name: tw_cli_aen_callback * Description: Callback for requests to fetch AEN's. * * Input: req -- ptr to completed request pkt * Output: None * Return value: None */ TW_VOID tw_cli_aen_callback(struct tw_cli_req_context *req) { struct tw_cli_ctlr_context *ctlr = req->ctlr; struct tw_cl_command_header *cmd_hdr; struct tw_cl_command_9k *cmd = &(req->cmd_pkt->command.cmd_pkt_9k); TW_UINT16 aen_code = TWA_AEN_QUEUE_EMPTY; TW_INT32 error; tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "req_id = 0x%x, req error = %d, status = 0x%x", GET_REQ_ID(cmd->lun_l4__req_id), req->error_code, cmd->status); /* * If the request was never submitted to the controller, the function * that sets error is responsible for calling tw_cl_create_event. */ if (!(error = req->error_code)) if ((error = cmd->status)) { cmd_hdr = (struct tw_cl_command_header *) (&(req->cmd_pkt->cmd_hdr)); tw_cli_create_ctlr_event(ctlr, TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR, cmd_hdr); tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 0x1206, 0x1, TW_CL_SEVERITY_ERROR_STRING, "Request Sense failed", "opcode = 0x%x, status = %d", GET_OPCODE(cmd->res__opcode), cmd->status); } if (error) { ctlr->internal_req_busy = TW_CL_FALSE; tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); return; } tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "Request Sense command succeeded"); aen_code = tw_cli_manage_aen(ctlr, req); if (aen_code != TWA_AEN_SYNC_TIME_WITH_HOST) { ctlr->internal_req_busy = TW_CL_FALSE; tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); if (aen_code != TWA_AEN_QUEUE_EMPTY) if ((error = tw_cli_get_aen(ctlr))) tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 0x1207, 0x1, TW_CL_SEVERITY_ERROR_STRING, "Failed to fetch all AEN's", "error = %d", error); } }
/* * Function name: tw_cli_drain_aen_queue * Description: Fetches all un-retrieved AEN's posted by fw. * * Input: ctlr -- ptr to CL internal ctlr context * Output: None * Return value: 0 -- success * non-zero-- failure */ TW_INT32 tw_cli_drain_aen_queue(struct tw_cli_ctlr_context *ctlr) { struct tw_cli_req_context *req; struct tw_cl_command_header *cmd_hdr; TW_TIME end_time; TW_UINT16 aen_code; TW_INT32 error; tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); for (;;) { if ((req = tw_cli_get_request(ctlr )) == TW_CL_NULL) { error = TW_OSL_EBUSY; break; } req->flags |= TW_CLI_REQ_FLAGS_INTERNAL; req->tw_cli_callback = TW_CL_NULL; if ((error = tw_cli_send_scsi_cmd(req, 0x03 /* REQUEST_SENSE */))) { tw_cli_dbg_printf(1, ctlr->ctlr_handle, tw_osl_cur_func(), "Cannot send command to fetch aen"); break; } end_time = tw_osl_get_local_time() + TW_CLI_REQUEST_TIMEOUT_PERIOD; do { if ((error = req->error_code)) /* * This will take care of completion due to * a reset, or a failure in * tw_cli_submit_pending_queue. */ goto out; tw_cli_process_resp_intr(req->ctlr); if ((req->state != TW_CLI_REQ_STATE_BUSY) && (req->state != TW_CLI_REQ_STATE_PENDING)) break; } while (tw_osl_get_local_time() <= end_time); if (req->state != TW_CLI_REQ_STATE_COMPLETE) { error = TW_OSL_ETIMEDOUT; break; } if ((error = req->cmd_pkt->command.cmd_pkt_9k.status)) { cmd_hdr = &req->cmd_pkt->cmd_hdr; #if 0 tw_cli_create_ctlr_event(ctlr, TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR, cmd_hdr); #endif // 0 break; } aen_code = tw_cli_manage_aen(ctlr, req); if (aen_code == TWA_AEN_QUEUE_EMPTY) break; if (aen_code == TWA_AEN_SYNC_TIME_WITH_HOST) continue; ctlr->internal_req_busy = TW_CL_FALSE; tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); } out: if (req) { if (req->data) ctlr->internal_req_busy = TW_CL_FALSE; tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); } return(error); }