/* * Compose a SMP DISCOVER request and put it into a CCB. This is current * as of SPL Revision 7. */ void smp_discover(struct ccb_smpio *smpio, uint32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), struct smp_discover_request *request, int request_len, uint8_t *response, int response_len, int long_response, int ignore_zone_group, int phy, uint32_t timeout) { cam_fill_smpio(smpio, retries, cbfcnp, /*flags*/CAM_DIR_BOTH, (uint8_t *)request, request_len - SMP_CRC_LEN, response, response_len, timeout); bzero(request, sizeof(*request)); request->frame_type = SMP_FRAME_TYPE_REQUEST; request->function = SMP_FUNC_DISCOVER; request->response_len = long_response ? SMP_DIS_RESPONSE_LEN : 0; request->request_len = long_response ? SMP_DIS_REQUEST_LEN : 0; if (ignore_zone_group != 0) request->ignore_zone_group |= SMP_DIS_IGNORE_ZONE_GROUP; request->phy = phy; }
/* * Compose a SMP PHY CONTROL request and put it into a CCB. This is * current as of SPL Revision 7. */ void smp_phy_control(struct ccb_smpio *smpio, uint32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), struct smp_phy_control_request *request, int request_len, uint8_t *response, int response_len, int long_response, uint32_t expected_exp_change_count, int phy, int phy_op, int update_pp_timeout_val, uint64_t attached_device_name, int prog_min_prl, int prog_max_prl, int slumber_partial, int pp_timeout_value, uint32_t timeout) { cam_fill_smpio(smpio, retries, cbfcnp, /*flags*/CAM_DIR_BOTH, (uint8_t *)request, request_len - SMP_CRC_LEN, response, response_len, timeout); bzero(request, sizeof(*request)); request->frame_type = SMP_FRAME_TYPE_REQUEST; request->function = SMP_FUNC_PHY_CONTROL; request->response_len = long_response ? SMP_PC_RESPONSE_LEN : 0; request->request_len = long_response ? SMP_PC_REQUEST_LEN : 0; scsi_ulto2b(expected_exp_change_count, request->expected_exp_chg_cnt); request->phy = phy; request->phy_operation = phy_op; if (update_pp_timeout_val != 0) request->update_pp_timeout |= SMP_PC_UPDATE_PP_TIMEOUT; scsi_u64to8b(attached_device_name, request->attached_device_name); request->prog_min_phys_link_rate = (prog_min_prl << SMP_PC_PROG_MIN_PL_RATE_SHIFT) & SMP_PC_PROG_MIN_PL_RATE_MASK; request->prog_max_phys_link_rate = (prog_max_prl << SMP_PC_PROG_MAX_PL_RATE_SHIFT) & SMP_PC_PROG_MAX_PL_RATE_MASK; request->config_bits0 = slumber_partial; request->pp_timeout_value = pp_timeout_value; }
/* * Compose a SMP REPORT MANUFACTURER INFORMATION request and put it into a * CCB. This is current as of SPL Revision 7. */ void smp_report_manuf_info(struct ccb_smpio *smpio, uint32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), struct smp_report_manuf_info_request *request, int request_len, uint8_t *response, int response_len, int long_response, uint32_t timeout) { cam_fill_smpio(smpio, retries, cbfcnp, /*flags*/CAM_DIR_BOTH, (uint8_t *)request, request_len - SMP_CRC_LEN, response, response_len, timeout); bzero(request, sizeof(*request)); request->frame_type = SMP_FRAME_TYPE_REQUEST; request->function = SMP_FUNC_REPORT_MANUF_INFO; request->response_len = long_response ? SMP_RMI_RESPONSE_LEN : 0; request->request_len = long_response ? SMP_RMI_REQUEST_LEN : 0; }
int smp_send_req(const struct smp_target_obj * tobj, struct smp_req_resp * rresp, int verbose) { union ccb *ccb; struct tobj_cam_t * tcp; int retval, emsk; int flags = 0; if ((NULL == tobj) || (0 == tobj->opened) || (NULL == tobj->vp)) { if (verbose) fprintf(stderr, "smp_send_req: nothing open??\n"); return -1; } if (I_CAM != tobj->interface_selector) { fprintf(stderr, "smp_send_req: unknown transport [%d]\n", tobj->interface_selector); return -1; } tcp = (struct tobj_cam_t *)tobj->vp; if (! (ccb = cam_getccb(tcp->cam_dev))) { fprintf(stderr, "cam_getccb: failed\n"); return -1; } // clear out structure, except for header that was filled in for us bzero(&(&ccb->ccb_h)[1], sizeof(union ccb) - sizeof(struct ccb_hdr)); flags |= CAM_DEV_QFRZDIS; /* CAM does not want request_len including CRC */ cam_fill_smpio(&ccb->smpio, /*retries*/ 2, /* guess */ /*cbfcnp*/ NULL, /*flags*/ flags, /*smp_request*/ rresp->request, /*smp_request_len*/ rresp->request_len - 4, /*smp_response*/ rresp->response, /*smp_response_len*/ rresp->max_response_len, /*timeout*/ 5000); /* milliseconds ? */ ccb->smpio.flags = SMP_FLAG_NONE; emsk = 0; if (((retval = cam_send_ccb(tcp->cam_dev, ccb)) < 0) || ((((emsk = (ccb->ccb_h.status & CAM_STATUS_MASK))) != CAM_REQ_CMP) && (emsk != CAM_SMP_STATUS_ERROR))) { cam_error_print(tcp->cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); cam_freeccb(ccb); return -1; } if (((emsk == CAM_REQ_CMP) || (emsk == CAM_SMP_STATUS_ERROR)) && (rresp->max_response_len > 0)) { if ((emsk == CAM_SMP_STATUS_ERROR) && (verbose > 3)) cam_error_print(tcp->cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); rresp->act_response_len = -1; cam_freeccb(ccb); return 0; } else { fprintf(stderr, "smp_send_req(cam): not sure how it got here\n"); cam_freeccb(ccb); return emsk ? emsk : -1; } }