/* start with dtrace -C -s */ #define request_get_target_id(request) \ ((*request->ccb).ccb_h.target_id) #define request_get_func_code(request) \ ((*request->ccb).ccb_h.func_code) #define request_get_req_map(request) \ ((*request->ccb).ctio.req_map) #define request_get_address(request) \ (request->req_pbuf) #define mpt_get_dev_unit(mpt) \ (mpt->dev->unit) #define indexfunc(mpt, request) \ mpt_get_dev_unit(mpt), request->serno #define time (timestamp/1000) #define XPT_FC_QUEUED 0x100 #define XPT_FC_DEV_QUEUED 0x800 #define XPT_SCSI_IO (0x01 | XPT_FC_DEV_QUEUED | XPT_FC_QUEUED) /** * void mpt_send_cmd(struct mpt_softc *mpt, request_t *re * fbt::mpt_send_cmd:entry /request_get_func_code(args[1]) == XPT_SCSI_IO/ { requests[ indexfunc(args[0], args[1]) ] = time; } fbt::mpt_send_cmd:entry / request_get_func_code(args[1]) == XPT_SCSI_IO && &(args[1]->links) != NULL / { requests[ indexfunc(args[0], args[1]) ] = time; @next[ mpt_get_dev_unit(args[0]), request_get_target_id(args[1]) ] = count(); } */ /** * static void * mpt_execute_req_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) */ fbt::mpt_execute_req_a64:entry { req = (request_t*)args[0]; mpt = (struct mpt_softc*) req->ccb->ccb_h.sim_priv.entries[0].ptr; requests[indexfunc(mpt,req)] = time; } struct MSG_SCSI_IO_REQUEST { U8 TargetID; /* 00h */ U8 Bus; /* 01h */ U8 ChainOffset; /* 02h */ U8 Function; /* 03h */ U8 CDBLength; /* 04h */ U8 SenseBufferLength; /* 05h */ U8 Reserved; /* 06h */ U8 MsgFlags; /* 07h */ U32 MsgContext; /* 08h */ U8 LUN[8]; /* 0Ch */ U32 Control; /* 14h */ U8 CDB[16]; /* 18h */ U32 DataLength; /* 28h */ U32 SenseBufferLowAddr; /* 2Ch */ SGE_SIMPLE64* SGL; /* 30h */ }; struct SGE_SIMPLE64 { U32 FlagsLength; U64 Address; } struct U64 { uint32_t Low; uint32_t High; }; /** * mpt_scsi_reply_handler(struct mpt_softc *mpt, request_t *req, * uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame) */ fbt::mpt_scsi_reply_handler:entry /request_get_func_code(args[1]) == XPT_SCSI_IO && requests[ indexfunc(args[0], args[1]) ] != 0/ { start = requests[ indexfunc(args[0], args[1]) ]; hdrp = (MSG_SCSI_IO_REQUEST*) args[1]->req_vbuf; se = (SGE_SIMPLE64*) hdrp->SGL; printf("%u,%u,%u,%u\n", mpt_get_dev_unit(args[0]), request_get_target_id(args[1]), args[1]->req_pbuf, se.Low, time-start); requests[ indexfunc(args[0], args[1]) ] = 0; } /* fbt::mpt_scsi_reply_handler:entry /request_get_func_code(args[1]) == XPT_SCSI_IO && requests[ indexfunc(args[0], args[1]) ] != 0/ { start = requests[ indexfunc(args[0], args[1]) ]; @delay[ mpt_get_dev_unit(args[0]), request_get_target_id(args[1]) ] = quantize( time - start ); requests[ indexfunc(args[0], args[1]) ] = 0; } profile:::tick-1sec { printa(@delay); } */ /* * Code-Excerpts for reference union ccb { struct ccb_hdr ccb_h; struct ccb_scsiio csio; struct ccb_getdev cgd; struct ccb_getdevlist cgdl; struct ccb_pathinq cpi; struct ccb_relsim crs; struct ccb_setasync csa; struct ccb_setdev csd; struct ccb_pathstats cpis; struct ccb_getdevstats cgds; struct ccb_dev_match cdm; struct ccb_trans_settings cts; struct ccb_calc_geometry ccg; struct ccb_sim_knob knob; struct ccb_abort cab; struct ccb_resetbus crb; struct ccb_resetdev crd; struct ccb_termio tio; struct ccb_accept_tio atio; struct ccb_scsiio ctio; struct ccb_en_lun cel; struct ccb_immed_notify cin; struct ccb_notify_ack cna; struct ccb_immediate_notify cin1; struct ccb_notify_acknowledge cna2; struct ccb_eng_inq cei; struct ccb_eng_exec cee; struct ccb_rescan crcn; struct ccb_debug cdbg; struct ccb_ataio ataio; }; struct ccb_hdr { cam_pinfo pinfo; * Info for priority scheduling * camq_entry xpt_links; * For chaining in the XPT layer * camq_entry sim_links; * For chaining in the SIM layer * camq_entry periph_links; * For chaining in the type driver * u_int32_t retry_count; void (*cbfcnp)(struct cam_periph *, union ccb *); * Callback on completion function * xpt_opcode func_code; * XPT function code * u_int32_t status; * Status returned by CAM subsystem * struct cam_path *path; * Compiled path for this ccb * path_id_t path_id; * Path ID for the request * target_id_t target_id; * Target device ID * lun_id_t target_lun; * Target LUN number * u_int32_t flags; * ccb_flags * ccb_ppriv_area periph_priv; ccb_spriv_area sim_priv; u_int32_t timeout; * Timeout value * * * Deprecated, only for use by non-MPSAFE SIMs. All others must * allocate and initialize their own callout storage. * struct callout_handle timeout_ch; }; func_code: XPT_SCSI_IO = (0x01 | XPT_FC_DEV_QUEUED = 0x800 | XPT_FC_QUEUED, XPT_FC_QUEUED = 0x100) = 0x901 * SCSI I/O Request CCB used for the XPT_SCSI_IO and XPT_CONT_TARGET_IO * function codes. struct ccb_scsiio { struct ccb_hdr ccb_h; union ccb *next_ccb; * Ptr for next CCB for action * u_int8_t *req_map; * Ptr to mapping info * u_int8_t *data_ptr; * Ptr to the data buf/SG list * u_int32_t dxfer_len; * Data transfer length * * Autosense storage * struct scsi_sense_data sense_data; u_int8_t sense_len; * Number of bytes to autosense * u_int8_t cdb_len; * Number of bytes for the CDB * u_int16_t sglist_cnt; * Number of SG list entries * u_int8_t scsi_status; * Returned SCSI status * u_int8_t sense_resid; * Autosense resid length: 2's comp * u_int32_t resid; * Transfer residual length: 2's comp * cdb_t cdb_io; * Union for CDB bytes/pointer * u_int8_t *msg_ptr; * Pointer to the message buffer * u_int16_t msg_len; * Number of bytes for the Message * u_int8_t tag_action; * What to do for tag queueing * * * The tag action should be either the define below (to send a * non-tagged transaction) or one of the defined scsi tag messages * from scsi_message.h. * #define CAM_TAG_ACTION_NONE 0x00 u_int tag_id; * tag id from initator (target mode) * u_int init_id; * initiator id of who selected * }; request_t => req_entry struct req_entry { struct req_entry { TAILQ_ENTRY(req_entry) links; * Pointer to next in list * mpt_req_state_t state; * Request State Information * uint16_t index; * Index of this entry * uint16_t IOCStatus; * Completion status * uint16_t ResponseCode; * TMF Reponse Code * uint16_t serno; * serial number * union ccb *ccb; * CAM request * void *req_vbuf; * Virtual Address of Entry * void *sense_vbuf; * Virtual Address of sense data * bus_addr_t req_pbuf; * Physical Address of Entry * bus_addr_t sense_pbuf; * Physical Address of sense data * bus_dmamap_t dmap; * DMA map for data buffers * struct req_entry *chain; * for SGE overallocations * struct callout callout; * Timeout for the request * }; */