#include "osd_types.h"
#include <linux/blkdev.h>
+#include <scsi/scsi_device.h>
/* Note: "NI" in comments below means "Not Implemented yet" */
+/* Configure of code:
+ * #undef if you *don't* want OSD v1 support in runtime.
+ * If #defined the initiator will dynamically configure to encode OSD v1
+ * CDB's if the target is detected to be OSD v1 only.
+ * OSD v2 only commands, options, and attributes will be ignored if target
+ * is v1 only.
+ * If #defined will result in bigger/slower code (OK Slower maybe not)
+ * Q: Should this be CONFIG_SCSI_OSD_VER1_SUPPORT and set from Kconfig?
+ */
+#define OSD_VER1_SUPPORT y
+
+enum osd_std_version {
+ OSD_VER_NONE = 0,
+ OSD_VER1 = 1,
+ OSD_VER2 = 2,
+};
+
/*
* Object-based Storage Device.
* This object represents an OSD device.
*/
struct osd_dev {
struct scsi_device *scsi_device;
+ struct file *file;
unsigned def_timeout;
+
+#ifdef OSD_VER1_SUPPORT
+ enum osd_std_version version;
+#endif
};
+/* Retrieve/return osd_dev(s) for use by Kernel clients */
+struct osd_dev *osduld_path_lookup(const char *dev_name); /*Use IS_ERR/ERR_PTR*/
+void osduld_put_device(struct osd_dev *od);
+
/* Add/remove test ioctls from external modules */
typedef int (do_test_fn)(struct osd_dev *od, unsigned cmd, unsigned long arg);
int osduld_register_test(unsigned ioctl, do_test_fn *do_test);
void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
void osd_dev_fini(struct osd_dev *od);
+/* some hi level device operations */
+int osd_auto_detect_ver(struct osd_dev *od, void *caps); /* GFP_KERNEL */
+static inline struct request_queue *osd_request_queue(struct osd_dev *od)
+{
+ return od->scsi_device->request_queue;
+}
+
+/* we might want to use function vector in the future */
+static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v)
+{
+#ifdef OSD_VER1_SUPPORT
+ od->version = v;
+#endif
+}
+
struct osd_request;
typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
int async_error;
};
+/* OSD Version control */
+static inline bool osd_req_is_ver1(struct osd_request *or)
+{
+#ifdef OSD_VER1_SUPPORT
+ return or->osd_dev->version == OSD_VER1;
+#else
+ return false;
+#endif
+}
+
/*
* How to use the osd library:
*
osd_req_done_fn *done, void *private);
/**
+ * osd_req_decode_sense_full - Decode sense information after execution.
+ *
+ * @or: - osd_request to examine
+ * @osi - Recievs a more detailed error report information (optional).
+ * @silent - Do not print to dmsg (Even if enabled)
+ * @bad_obj_list - Some commands act on multiple objects. Failed objects will
+ * be recieved here (optional)
+ * @max_obj - Size of @bad_obj_list.
+ * @bad_attr_list - List of failing attributes (optional)
+ * @max_attr - Size of @bad_attr_list.
+ *
+ * After execution, sense + return code can be analyzed using this function. The
+ * return code is the final disposition on the error. So it is possible that a
+ * CHECK_CONDITION was returned from target but this will return NO_ERROR, for
+ * example on recovered errors. All parameters are optional if caller does
+ * not need any returned information.
+ * Note: This function will also dump the error to dmsg according to settings
+ * of the SCSI_OSD_DPRINT_SENSE Kconfig value. Set @silent if you know the
+ * command would routinely fail, to not spam the dmsg file.
+ */
+struct osd_sense_info {
+ int key; /* one of enum scsi_sense_keys */
+ int additional_code ; /* enum osd_additional_sense_codes */
+ union { /* Sense specific information */
+ u16 sense_info;
+ u16 cdb_field_offset; /* scsi_invalid_field_in_cdb */
+ };
+ union { /* Command specific information */
+ u64 command_info;
+ };
+
+ u32 not_initiated_command_functions; /* osd_command_functions_bits */
+ u32 completed_command_functions; /* osd_command_functions_bits */
+ struct osd_obj_id obj;
+ struct osd_attr attr;
+};
+
+int osd_req_decode_sense_full(struct osd_request *or,
+ struct osd_sense_info *osi, bool silent,
+ struct osd_obj_id *bad_obj_list, int max_obj,
+ struct osd_attr *bad_attr_list, int max_attr);
+
+static inline int osd_req_decode_sense(struct osd_request *or,
+ struct osd_sense_info *osi)
+{
+ return osd_req_decode_sense_full(or, osi, false, NULL, 0, NULL, 0);
+}
+
+/**
* osd_end_request - return osd_request to free store
*
* @or: osd_request to free
void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *);
void osd_req_write(struct osd_request *or,
- const struct osd_obj_id *, struct bio *data_out, u64 offset);
+ const struct osd_obj_id *obj, u64 offset, struct bio *bio, u64 len);
+int osd_req_write_kern(struct osd_request *or,
+ const struct osd_obj_id *obj, u64 offset, void *buff, u64 len);
void osd_req_append(struct osd_request *or,
const struct osd_obj_id *, struct bio *data_out);/* NI */
void osd_req_create_write(struct osd_request *or,
/*V2*/ u64 offset, /*V2*/ u64 len);
void osd_req_read(struct osd_request *or,
- const struct osd_obj_id *, struct bio *data_in, u64 offset);
+ const struct osd_obj_id *obj, u64 offset, struct bio *bio, u64 len);
+int osd_req_read_kern(struct osd_request *or,
+ const struct osd_obj_id *obj, u64 offset, void *buff, u64 len);
/*
* Root/Partition/Collection/Object Attributes commands