1*4318e08cSChristof Schmitt /* 2*4318e08cSChristof Schmitt * zfcp device driver 3*4318e08cSChristof Schmitt * 4*4318e08cSChristof Schmitt * Fibre Channel related definitions and inline functions for the zfcp 5*4318e08cSChristof Schmitt * device driver 6*4318e08cSChristof Schmitt * 7*4318e08cSChristof Schmitt * Copyright IBM Corporation 2009 8*4318e08cSChristof Schmitt */ 9*4318e08cSChristof Schmitt 10*4318e08cSChristof Schmitt #ifndef ZFCP_FC_H 11*4318e08cSChristof Schmitt #define ZFCP_FC_H 12*4318e08cSChristof Schmitt 13*4318e08cSChristof Schmitt #include <scsi/fc/fc_fcp.h> 14*4318e08cSChristof Schmitt #include <scsi/scsi_cmnd.h> 15*4318e08cSChristof Schmitt #include <scsi/scsi_tcq.h> 16*4318e08cSChristof Schmitt 17*4318e08cSChristof Schmitt /** 18*4318e08cSChristof Schmitt * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd 19*4318e08cSChristof Schmitt * @fcp: fcp_cmnd to setup 20*4318e08cSChristof Schmitt * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB 21*4318e08cSChristof Schmitt */ 22*4318e08cSChristof Schmitt static inline 23*4318e08cSChristof Schmitt void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi) 24*4318e08cSChristof Schmitt { 25*4318e08cSChristof Schmitt char tag[2]; 26*4318e08cSChristof Schmitt 27*4318e08cSChristof Schmitt int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun); 28*4318e08cSChristof Schmitt 29*4318e08cSChristof Schmitt if (scsi_populate_tag_msg(scsi, tag)) { 30*4318e08cSChristof Schmitt switch (tag[0]) { 31*4318e08cSChristof Schmitt case MSG_ORDERED_TAG: 32*4318e08cSChristof Schmitt fcp->fc_pri_ta |= FCP_PTA_ORDERED; 33*4318e08cSChristof Schmitt break; 34*4318e08cSChristof Schmitt case MSG_SIMPLE_TAG: 35*4318e08cSChristof Schmitt fcp->fc_pri_ta |= FCP_PTA_SIMPLE; 36*4318e08cSChristof Schmitt break; 37*4318e08cSChristof Schmitt }; 38*4318e08cSChristof Schmitt } else 39*4318e08cSChristof Schmitt fcp->fc_pri_ta = FCP_PTA_SIMPLE; 40*4318e08cSChristof Schmitt 41*4318e08cSChristof Schmitt if (scsi->sc_data_direction == DMA_FROM_DEVICE) 42*4318e08cSChristof Schmitt fcp->fc_flags |= FCP_CFL_RDDATA; 43*4318e08cSChristof Schmitt if (scsi->sc_data_direction == DMA_TO_DEVICE) 44*4318e08cSChristof Schmitt fcp->fc_flags |= FCP_CFL_WRDATA; 45*4318e08cSChristof Schmitt 46*4318e08cSChristof Schmitt memcpy(fcp->fc_cdb, scsi->cmnd, scsi->cmd_len); 47*4318e08cSChristof Schmitt 48*4318e08cSChristof Schmitt fcp->fc_dl = scsi_bufflen(scsi); 49*4318e08cSChristof Schmitt } 50*4318e08cSChristof Schmitt 51*4318e08cSChristof Schmitt /** 52*4318e08cSChristof Schmitt * zfcp_fc_fcp_tm - setup FCP command as task management command 53*4318e08cSChristof Schmitt * @fcp: fcp_cmnd to setup 54*4318e08cSChristof Schmitt * @dev: scsi_device where to send the task management command 55*4318e08cSChristof Schmitt * @tm: task management flags to setup tm command 56*4318e08cSChristof Schmitt */ 57*4318e08cSChristof Schmitt static inline 58*4318e08cSChristof Schmitt void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags) 59*4318e08cSChristof Schmitt { 60*4318e08cSChristof Schmitt int_to_scsilun(dev->lun, (struct scsi_lun *) &fcp->fc_lun); 61*4318e08cSChristof Schmitt fcp->fc_tm_flags |= tm_flags; 62*4318e08cSChristof Schmitt } 63*4318e08cSChristof Schmitt 64*4318e08cSChristof Schmitt /** 65*4318e08cSChristof Schmitt * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly 66*4318e08cSChristof Schmitt * @fcp_rsp: FCP RSP IU to evaluate 67*4318e08cSChristof Schmitt * @scsi: SCSI command where to update status and sense buffer 68*4318e08cSChristof Schmitt */ 69*4318e08cSChristof Schmitt static inline 70*4318e08cSChristof Schmitt void zfcp_fc_eval_fcp_rsp(struct fcp_resp_with_ext *fcp_rsp, 71*4318e08cSChristof Schmitt struct scsi_cmnd *scsi) 72*4318e08cSChristof Schmitt { 73*4318e08cSChristof Schmitt struct fcp_resp_rsp_info *rsp_info; 74*4318e08cSChristof Schmitt char *sense; 75*4318e08cSChristof Schmitt u32 sense_len, resid; 76*4318e08cSChristof Schmitt u8 rsp_flags; 77*4318e08cSChristof Schmitt 78*4318e08cSChristof Schmitt set_msg_byte(scsi, COMMAND_COMPLETE); 79*4318e08cSChristof Schmitt scsi->result |= fcp_rsp->resp.fr_status; 80*4318e08cSChristof Schmitt 81*4318e08cSChristof Schmitt rsp_flags = fcp_rsp->resp.fr_flags; 82*4318e08cSChristof Schmitt 83*4318e08cSChristof Schmitt if (unlikely(rsp_flags & FCP_RSP_LEN_VAL)) { 84*4318e08cSChristof Schmitt rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; 85*4318e08cSChristof Schmitt if (rsp_info->rsp_code == FCP_TMF_CMPL) 86*4318e08cSChristof Schmitt set_host_byte(scsi, DID_OK); 87*4318e08cSChristof Schmitt else { 88*4318e08cSChristof Schmitt set_host_byte(scsi, DID_ERROR); 89*4318e08cSChristof Schmitt return; 90*4318e08cSChristof Schmitt } 91*4318e08cSChristof Schmitt } 92*4318e08cSChristof Schmitt 93*4318e08cSChristof Schmitt if (unlikely(rsp_flags & FCP_SNS_LEN_VAL)) { 94*4318e08cSChristof Schmitt sense = (char *) &fcp_rsp[1]; 95*4318e08cSChristof Schmitt if (rsp_flags & FCP_RSP_LEN_VAL) 96*4318e08cSChristof Schmitt sense += fcp_rsp->ext.fr_sns_len; 97*4318e08cSChristof Schmitt sense_len = min(fcp_rsp->ext.fr_sns_len, 98*4318e08cSChristof Schmitt (u32) SCSI_SENSE_BUFFERSIZE); 99*4318e08cSChristof Schmitt memcpy(scsi->sense_buffer, sense, sense_len); 100*4318e08cSChristof Schmitt } 101*4318e08cSChristof Schmitt 102*4318e08cSChristof Schmitt if (unlikely(rsp_flags & FCP_RESID_UNDER)) { 103*4318e08cSChristof Schmitt resid = fcp_rsp->ext.fr_resid; 104*4318e08cSChristof Schmitt scsi_set_resid(scsi, resid); 105*4318e08cSChristof Schmitt if (scsi_bufflen(scsi) - resid < scsi->underflow && 106*4318e08cSChristof Schmitt !(rsp_flags & FCP_SNS_LEN_VAL) && 107*4318e08cSChristof Schmitt fcp_rsp->resp.fr_status == SAM_STAT_GOOD) 108*4318e08cSChristof Schmitt set_host_byte(scsi, DID_ERROR); 109*4318e08cSChristof Schmitt } 110*4318e08cSChristof Schmitt } 111*4318e08cSChristof Schmitt 112*4318e08cSChristof Schmitt #endif 113