/* * Function name: tw_cli_scsi_complete * Description: Completion routine for SCSI requests. * * Input: req -- ptr to CL internal request context * Output: None * Return value: None */ TW_VOID tw_cli_scsi_complete(struct tw_cli_req_context *req) { struct tw_cl_req_packet *req_pkt = (struct tw_cl_req_packet *)(req->orig_req); struct tw_cl_scsi_req_packet *scsi_req = &(req_pkt->gen_req_pkt.scsi_req); struct tw_cl_command_9k *cmd = &(req->cmd_pkt->command.cmd_pkt_9k); struct tw_cl_command_header *cmd_hdr; TW_UINT16 error; TW_UINT8 *cdb; tw_cli_dbg_printf(8, req->ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); scsi_req->scsi_status = cmd->status; if (! cmd->status) return; tw_cli_dbg_printf(1, req->ctlr->ctlr_handle, tw_osl_cur_func(), "req_id = 0x%x, status = 0x%x", GET_REQ_ID(cmd->lun_l4__req_id), cmd->status); cmd_hdr = &(req->cmd_pkt->cmd_hdr); error = cmd_hdr->status_block.error; if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) || (error == TWA_ERROR_UNIT_OFFLINE)) { if (GET_LUN_L4(cmd->lun_l4__req_id)) req_pkt->status |= TW_CL_ERR_REQ_INVALID_LUN; else req_pkt->status |= TW_CL_ERR_REQ_INVALID_TARGET; } else { tw_cli_dbg_printf(2, req->ctlr->ctlr_handle, tw_osl_cur_func(), "cmd = %x %x %x %x %x %x %x", GET_OPCODE(cmd->res__opcode), GET_SGL_OFF(cmd->res__opcode), cmd->unit, cmd->lun_l4__req_id, cmd->status, cmd->sgl_offset, cmd->lun_h4__sgl_entries); cdb = (TW_UINT8 *)(cmd->cdb); tw_cli_dbg_printf(2, req->ctlr->ctlr_handle, tw_osl_cur_func(), "cdb = %x %x %x %x %x %x %x %x " "%x %x %x %x %x %x %x %x", cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11], cdb[12], cdb[13], cdb[14], cdb[15]); #if 0 /* * Print the error. Firmware doesn't yet support * the 'Mode Sense' cmd. Don't print if the cmd * is 'Mode Sense', and the error is 'Invalid field * in CDB'. */ if (! ((cdb[0] == 0x1A) && (error == 0x10D))) tw_cli_create_ctlr_event(req->ctlr, TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR, cmd_hdr); #endif // 0 } if (scsi_req->sense_data) { tw_osl_memcpy(scsi_req->sense_data, cmd_hdr->sense_data, TWA_SENSE_DATA_LENGTH); scsi_req->sense_len = TWA_SENSE_DATA_LENGTH; req_pkt->status |= TW_CL_ERR_REQ_AUTO_SENSE_VALID; } req_pkt->status |= TW_CL_ERR_REQ_SCSI_ERROR; }
/* * Function name: tw_cli_print_req_info * Description: Prints CL internal details of a given request. * * Input: req -- ptr to CL internal request context * Output: None * Return value: None */ TW_VOID tw_cl_print_req_info(struct tw_cl_req_handle *req_handle) { struct tw_cli_req_context *req = req_handle->cl_req_ctxt; struct tw_cli_ctlr_context *ctlr = req->ctlr; struct tw_cl_ctlr_handle *ctlr_handle = ctlr->ctlr_handle; struct tw_cl_command_packet *cmd_pkt = req->cmd_pkt; struct tw_cl_command_9k *cmd9k; union tw_cl_command_7k *cmd7k; TW_UINT8 *cdb; TW_VOID *sgl; TW_UINT32 sgl_entries; TW_UINT32 i; tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(), "CL details for request:"); tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(), "req_handle = %p, ctlr = %p,\n" "cmd_pkt = %p, cmd_pkt_phys = 0x%llx,\n" "data = %p, length = 0x%x, data_phys = 0x%llx,\n" "state = 0x%x, flags = 0x%x, error = 0x%x,\n" "orig_req = %p, callback = %p, req_id = 0x%x,\n" "next_req = %p, prev_req = %p", req_handle, ctlr, cmd_pkt, req->cmd_pkt_phys, req->data, req->length, req->data_phys, req->state, req->flags, req->error_code, req->orig_req, req->tw_cli_callback, req->request_id, req->link.next, req->link.prev); if (req->flags & TW_CLI_REQ_FLAGS_9K) { cmd9k = &(cmd_pkt->command.cmd_pkt_9k); sgl = cmd9k->sg_list; sgl_entries = TW_CL_SWAP16( GET_SGL_ENTRIES(cmd9k->lun_h4__sgl_entries)); tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(), "9K cmd: opcode = 0x%x, unit = 0x%x, req_id = 0x%x,\n" "status = 0x%x, sgl_offset = 0x%x, sgl_entries = 0x%x", GET_OPCODE(cmd9k->res__opcode), cmd9k->unit, TW_CL_SWAP16(GET_REQ_ID(cmd9k->lun_l4__req_id)), cmd9k->status, cmd9k->sgl_offset, sgl_entries); cdb = (TW_UINT8 *)(cmd9k->cdb); tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(), "CDB: %x %x %x %x %x %x %x %x" "%x %x %x %x %x %x %x %x", cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11], cdb[12], cdb[13], cdb[14], cdb[15]); } else { cmd7k = &(cmd_pkt->command.cmd_pkt_7k); sgl = cmd7k->param.sgl; sgl_entries = (cmd7k->generic.size - GET_SGL_OFF(cmd7k->generic.sgl_off__opcode)) / ((ctlr->flags & TW_CL_64BIT_ADDRESSES) ? 3 : 2); tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(), "7K cmd: opcode = 0x%x, sgl_offset = 0x%x,\n" "size = 0x%x, req_id = 0x%x, unit = 0x%x,\n" "status = 0x%x, flags = 0x%x, count = 0x%x", GET_OPCODE(cmd7k->generic.sgl_off__opcode), GET_SGL_OFF(cmd7k->generic.sgl_off__opcode), cmd7k->generic.size, TW_CL_SWAP16(cmd7k->generic.request_id), GET_UNIT(cmd7k->generic.host_id__unit), cmd7k->generic.status, cmd7k->generic.flags, TW_CL_SWAP16(cmd7k->generic.count)); } tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(), "SG entries:"); if (ctlr->flags & TW_CL_64BIT_ADDRESSES) { struct tw_cl_sg_desc64 *sgl64 = (struct tw_cl_sg_desc64 *)sgl; for (i = 0; i < sgl_entries; i++) { tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(), "0x%llx 0x%x", sgl64[i].address, sgl64[i].length); } } else { struct tw_cl_sg_desc32 *sgl32 = (struct tw_cl_sg_desc32 *)sgl; for (i = 0; i < sgl_entries; i++) { tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(), "0x%x 0x%x", sgl32[i].address, sgl32[i].length); } } }