/* * Function name: tw_cli_init_connection * Description: Sends init_connection cmd to firmware * * Input: ctlr -- ptr to per ctlr structure * message_credits -- max # of requests that we might send * down simultaneously. This will be * typically set to 256 at init-time or * after a reset, and to 1 at shutdown-time * set_features -- indicates if we intend to use 64-bit * sg, also indicates if we want to do a * basic or an extended init_connection; * * Note: The following input/output parameters are valid, only in case of an * extended init_connection: * * current_fw_srl -- srl of fw we are bundled * with, if any; 0 otherwise * current_fw_arch_id -- arch_id of fw we are bundled * with, if any; 0 otherwise * current_fw_branch -- branch # of fw we are bundled * with, if any; 0 otherwise * current_fw_build -- build # of fw we are bundled * with, if any; 0 otherwise * Output: fw_on_ctlr_srl -- srl of fw on ctlr * fw_on_ctlr_arch_id -- arch_id of fw on ctlr * fw_on_ctlr_branch -- branch # of fw on ctlr * fw_on_ctlr_build -- build # of fw on ctlr * init_connect_result -- result bitmap of fw response * Return value: 0 -- success * non-zero-- failure */ TW_INT32 tw_cli_init_connection(struct tw_cli_ctlr_context *ctlr, TW_UINT16 message_credits, TW_UINT32 set_features, TW_UINT16 current_fw_srl, TW_UINT16 current_fw_arch_id, TW_UINT16 current_fw_branch, TW_UINT16 current_fw_build, TW_UINT16 *fw_on_ctlr_srl, TW_UINT16 *fw_on_ctlr_arch_id, TW_UINT16 *fw_on_ctlr_branch, TW_UINT16 *fw_on_ctlr_build, TW_UINT32 *init_connect_result) { struct tw_cli_req_context *req; struct tw_cl_command_init_connect *init_connect; TW_INT32 error = TW_OSL_EBUSY; tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); /* Get a request packet. */ if ((req = tw_cli_get_request(ctlr )) == TW_CL_NULL) goto out; req->flags |= TW_CLI_REQ_FLAGS_INTERNAL; /* Build the cmd pkt. */ init_connect = &(req->cmd_pkt->command.cmd_pkt_7k.init_connect); req->cmd_pkt->cmd_hdr.header_desc.size_header = 128; init_connect->res1__opcode = BUILD_RES__OPCODE(0, TWA_FW_CMD_INIT_CONNECTION); init_connect->request_id = (TW_UINT8)(TW_CL_SWAP16(req->request_id)); init_connect->message_credits = TW_CL_SWAP16(message_credits); init_connect->features = TW_CL_SWAP32(set_features); if (ctlr->flags & TW_CL_64BIT_ADDRESSES) init_connect->features |= TW_CL_SWAP32(TWA_64BIT_SG_ADDRESSES); if (set_features & TWA_EXTENDED_INIT_CONNECT) { /* * Fill in the extra fields needed for an extended * init_connect. */ init_connect->size = 6; init_connect->fw_srl = TW_CL_SWAP16(current_fw_srl); init_connect->fw_arch_id = TW_CL_SWAP16(current_fw_arch_id); init_connect->fw_branch = TW_CL_SWAP16(current_fw_branch); init_connect->fw_build = TW_CL_SWAP16(current_fw_build); } else init_connect->size = 3; /* Submit the command, and wait for it to complete. */ error = tw_cli_submit_and_poll_request(req, TW_CLI_REQUEST_TIMEOUT_PERIOD); if (error == TW_OSL_ETIMEDOUT) /* Clean-up done by tw_cli_submit_and_poll_request. */ return(error); if (error) goto out; if ((error = init_connect->status)) { tw_cli_create_ctlr_event(ctlr, TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR, &(req->cmd_pkt->cmd_hdr)); goto out; } if (set_features & TWA_EXTENDED_INIT_CONNECT) { *fw_on_ctlr_srl = TW_CL_SWAP16(init_connect->fw_srl); *fw_on_ctlr_arch_id = TW_CL_SWAP16(init_connect->fw_arch_id); *fw_on_ctlr_branch = TW_CL_SWAP16(init_connect->fw_branch); *fw_on_ctlr_build = TW_CL_SWAP16(init_connect->fw_build); *init_connect_result = TW_CL_SWAP32(init_connect->result); } tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); return(error); out: tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 0x1016, 0x1, TW_CL_SEVERITY_ERROR_STRING, "init_connection failed", "error = %d", error); if (req) tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); return(error); }
/* * Function name: tw_cl_start_io * Description: Interface to OS Layer for accepting SCSI requests. * * Input: ctlr_handle -- controller handle * req_pkt -- OSL built request packet * req_handle -- request handle * Output: None * Return value: 0 -- success * non-zero-- failure */ TW_INT32 tw_cl_start_io(struct tw_cl_ctlr_handle *ctlr_handle, struct tw_cl_req_packet *req_pkt, struct tw_cl_req_handle *req_handle) { struct tw_cli_ctlr_context *ctlr; struct tw_cli_req_context *req; struct tw_cl_command_9k *cmd; struct tw_cl_scsi_req_packet *scsi_req; TW_INT32 error = TW_CL_ERR_REQ_SUCCESS; tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered"); ctlr = (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt); /* * If working with a firmware version that does not support multiple * luns, and this request is directed at a non-zero lun, error it * back right away. */ if ((req_pkt->gen_req_pkt.scsi_req.lun) && (ctlr->working_srl < TWA_MULTI_LUN_FW_SRL)) { req_pkt->status |= (TW_CL_ERR_REQ_INVALID_LUN | TW_CL_ERR_REQ_SCSI_ERROR); req_pkt->tw_osl_callback(req_handle); return(TW_CL_ERR_REQ_SUCCESS); } if ((req = tw_cli_get_request(ctlr )) == TW_CL_NULL) { tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(), "Out of request context packets: returning busy"); return(TW_OSL_EBUSY); } req_handle->cl_req_ctxt = req; req->req_handle = req_handle; req->orig_req = req_pkt; req->tw_cli_callback = tw_cli_complete_io; req->flags |= TW_CLI_REQ_FLAGS_EXTERNAL; req->flags |= TW_CLI_REQ_FLAGS_9K; scsi_req = &(req_pkt->gen_req_pkt.scsi_req); /* Build the cmd pkt. */ cmd = &(req->cmd_pkt->command.cmd_pkt_9k); req->cmd_pkt->cmd_hdr.header_desc.size_header = 128; cmd->res__opcode = BUILD_RES__OPCODE(0, TWA_FW_CMD_EXECUTE_SCSI); cmd->unit = (TW_UINT8)(scsi_req->unit); cmd->lun_l4__req_id = TW_CL_SWAP16( BUILD_LUN_L4__REQ_ID(scsi_req->lun, req->request_id)); cmd->status = 0; cmd->sgl_offset = 16; /* offset from end of hdr = max cdb len */ tw_osl_memcpy(cmd->cdb, scsi_req->cdb, scsi_req->cdb_len); if (req_pkt->flags & TW_CL_REQ_CALLBACK_FOR_SGLIST) { TW_UINT32 num_sgl_entries; req_pkt->tw_osl_sgl_callback(req_handle, cmd->sg_list, &num_sgl_entries); cmd->lun_h4__sgl_entries = TW_CL_SWAP16(BUILD_LUN_H4__SGL_ENTRIES(scsi_req->lun, num_sgl_entries)); } else { cmd->lun_h4__sgl_entries = TW_CL_SWAP16(BUILD_LUN_H4__SGL_ENTRIES(scsi_req->lun, scsi_req->sgl_entries)); tw_cli_fill_sg_list(ctlr, scsi_req->sg_list, cmd->sg_list, scsi_req->sgl_entries); } if (((TW_CL_Q_FIRST_ITEM(&(ctlr->req_q_head[TW_CLI_PENDING_Q]))) != TW_CL_NULL) || (ctlr->reset_in_progress)) { tw_cli_req_q_insert_tail(req, TW_CLI_PENDING_Q); TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle, TWA_CONTROL_UNMASK_COMMAND_INTERRUPT); } else if ((error = tw_cli_submit_cmd(req))) { tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(), "Could not start request. request = %p, error = %d", req, error); tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); } return(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); } } }