/* * Copyright (c) 2021 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include #include #include #include #include "sg_pt.h" #include "sg_lib.h" #include "sg_pr2serr.h" /* Version 1.02 20210618 */ /* List of function names with external linkage that need to be defined * * check_pt_file_handle * clear_scsi_pt_obj * construct_scsi_pt_obj * construct_scsi_pt_obj_with_fd * destruct_scsi_pt_obj * do_scsi_pt * do_nvm_pt * get_pt_actual_lengths * get_pt_duration_ns * get_pt_file_handle * get_pt_nvme_nsid * get_pt_req_lengths * get_pt_result * get_scsi_pt_cdb_buf * get_scsi_pt_cdb_len * get_scsi_pt_duration_ms * get_scsi_pt_os_err * get_scsi_pt_os_err_str * get_scsi_pt_resid * get_scsi_pt_result_category * get_scsi_pt_sense_buf * get_scsi_pt_sense_len * get_scsi_pt_status_response * get_scsi_pt_transport_err * get_scsi_pt_transport_err_str * partial_clear_scsi_pt_obj * pt_device_is_nvme * scsi_pt_close_device * scsi_pt_open_device * scsi_pt_open_flags * set_pt_file_handle * set_pt_metadata_xfer * set_scsi_pt_cdb * set_scsi_pt_data_in * set_scsi_pt_data_out * set_scsi_pt_flags * set_scsi_pt_packet_id * set_scsi_pt_sense * set_scsi_pt_tag * set_scsi_pt_task_attr * set_scsi_pt_task_management * set_scsi_pt_transport_err */ /* Simply defines all the functions needed by the pt interface (see sg_pt.h). * They do nothing. This allows decoding of hex files (e.g. with the --in= * or --inhex= option) with utilities like sg_vpd and sg_logs. */ struct sg_pt_dummy { int dummy; }; struct sg_pt_base { struct sg_pt_dummy impl; }; /* Returns >= 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_open_device(const char * device_name, bool read_only, int verbose) { int oflags = 0 /* O_NONBLOCK*/ ; oflags |= (read_only ? O_RDONLY : O_RDWR); return scsi_pt_open_flags(device_name, oflags, verbose); } /* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed * together. The 'flags' argument is ignored in OSF-1. * Returns >= 0 if successful, otherwise returns negated errno. */ int scsi_pt_open_flags(const char * device_name, int flags, int verbose) { if (device_name) {} if (flags) {} if (verbose) {} errno = EINVAL; return -1; } /* Returns 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_close_device(int device_fd) { if (device_fd) {} return 0; } struct sg_pt_base * construct_scsi_pt_obj_with_fd(int device_fd, int verbose) { struct sg_pt_dummy * ptp; if (device_fd) {} ptp = (struct sg_pt_dummy *)malloc(sizeof(struct sg_pt_dummy)); if (ptp) { memset(ptp, 0, sizeof(struct sg_pt_dummy)); } else if (verbose) pr2ws("%s: malloc() out of memory\n", __func__); return (struct sg_pt_base *)ptp; } struct sg_pt_base * construct_scsi_pt_obj(void) { return construct_scsi_pt_obj_with_fd(-1, 0); } void destruct_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_dummy * ptp = &vp->impl; if (ptp) free(ptp); } void clear_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_dummy * ptp = &vp->impl; if (ptp) { ptp->dummy = 0; } } void partial_clear_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_dummy * ptp = &vp->impl; if (NULL == ptp) return; ptp->dummy = 0; } void set_scsi_pt_cdb(struct sg_pt_base * vp, const uint8_t * cdb, int cdb_len) { if (vp) {} if (cdb) {} if (cdb_len) {} } int get_scsi_pt_cdb_len(const struct sg_pt_base * vp) { if (vp) {} return 6; } uint8_t * get_scsi_pt_cdb_buf(const struct sg_pt_base * vp) { if (vp) {} return NULL; } void set_scsi_pt_sense(struct sg_pt_base * vp, uint8_t * sense, int max_sense_len) { if (vp) {} if (sense) {} if (max_sense_len) {} } /* from device */ void set_scsi_pt_data_in(struct sg_pt_base * vp, uint8_t * dxferp, int dxfer_len) { if (vp) {} if (dxferp) {} if (dxfer_len) {} } /* to device */ void set_scsi_pt_data_out(struct sg_pt_base * vp, const uint8_t * dxferp, int dxfer_len) { if (vp) {} if (dxferp) {} if (dxfer_len) {} } void set_scsi_pt_packet_id(struct sg_pt_base * vp, int pack_id) { if (vp) {} if (pack_id) {} } void set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag) { if (vp) {} if (tag) {} } void set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code) { if (vp) {} if (tmf_code) {} } void set_scsi_pt_task_attr(struct sg_pt_base * vp, int attrib, int priority) { if (vp) {} if (attrib) {} if (priority) {} } void set_scsi_pt_flags(struct sg_pt_base * vp, int flags) { if (vp) {} if (flags) {} } int do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose) { if (vp) {} if (device_fd) {} if (time_secs) {} if (verbose) {} return 0; } int get_scsi_pt_result_category(const struct sg_pt_base * vp) { if (vp) {} return 0; } int get_scsi_pt_resid(const struct sg_pt_base * vp) { if (vp) {} return 0; } void get_pt_req_lengths(const struct sg_pt_base * vp, int * req_dinp, int * req_doutp) { if (vp) {} if (req_dinp) {} if (req_doutp) {} } void get_pt_actual_lengths(const struct sg_pt_base * vp, int * act_dinp, int * act_doutp) { if (vp) {} if (act_dinp) {} if (act_doutp) {} } int get_scsi_pt_status_response(const struct sg_pt_base * vp) { if (vp) {} return 0; } int get_scsi_pt_sense_len(const struct sg_pt_base * vp) { if (vp) {} return 0; } uint8_t * get_scsi_pt_sense_buf(const struct sg_pt_base * vp) { if (vp) {} return NULL; } int get_scsi_pt_duration_ms(const struct sg_pt_base * vp) { if (vp) {} return 0; } /* If not available return 0 otherwise return number of nanoseconds that the * lower layers (and hardware) took to execute the command just completed. */ uint64_t get_pt_duration_ns(const struct sg_pt_base * vp __attribute__ ((unused))) { return 0; } int get_scsi_pt_transport_err(const struct sg_pt_base * vp) { if (vp) {} return 0; } int get_scsi_pt_os_err(const struct sg_pt_base * vp) { if (vp) {} return 0; } bool pt_device_is_nvme(const struct sg_pt_base * vp) { if (vp) {} return false; } char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { if (vp) {} if (max_b_len) {} if (b) {} return NULL; } char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { if (vp) {} if (max_b_len) {} if (b) {} return NULL; } int do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int verbose) { if (vp) { } if (submq) { } if (timeout_secs) { } if (verbose) { } return SCSI_PT_DO_NOT_SUPPORTED; } int check_pt_file_handle(int device_fd, const char * device_name, int vb) { if (device_fd) {} if (device_name) {} if (vb) {} return 0; } /* Valid file handles (which is the return value) are >= 0 . Returns -1 * if there is no valid file handle. */ int get_pt_file_handle(const struct sg_pt_base * vp) { if (vp) { } return -1; } /* If a NVMe block device (which includes the NSID) handle is associated * with 'vp', then its NSID is returned (values range from 0x1 to * 0xffffffe). Otherwise 0 is returned. */ uint32_t get_pt_nvme_nsid(const struct sg_pt_base * vp) { if (vp) { } return 0; } uint32_t get_pt_result(const struct sg_pt_base * vp) { if (vp) { } return 0; } int set_pt_file_handle(struct sg_pt_base * vp, int dev_han, int vb) { if (vp) { } if (dev_han) { } if (vb) { } return 0; } void set_pt_metadata_xfer(struct sg_pt_base * vp, uint8_t * mdxferp, uint32_t mdxfer_len, bool out_true) { if (vp) { } if (mdxferp) { } if (mdxfer_len) { } if (out_true) { } } void set_scsi_pt_transport_err(struct sg_pt_base * vp, int err) { if (vp) { } if (err) { } }