|
2 | 2 | #ifndef _UAPIBSG_H |
3 | 3 | #define _UAPIBSG_H |
4 | 4 |
|
| 5 | +#ifdef __KERNEL__ |
| 6 | +#include <linux/build_bug.h> |
| 7 | +#endif /* __KERNEL__ */ |
5 | 8 | #include <linux/types.h> |
6 | 9 |
|
7 | 10 | #define BSG_PROTOCOL_SCSI 0 |
@@ -63,5 +66,77 @@ struct sg_io_v4 { |
63 | 66 | __u32 padding; |
64 | 67 | }; |
65 | 68 |
|
| 69 | +struct bsg_uring_cmd { |
| 70 | + __u64 request; /* [i], [*i] command descriptor address */ |
| 71 | + __u32 request_len; /* [i] command descriptor length in bytes */ |
| 72 | + __u32 protocol; /* [i] protocol type (BSG_PROTOCOL_*) */ |
| 73 | + __u32 subprotocol; /* [i] subprotocol type (BSG_SUB_PROTOCOL_*) */ |
| 74 | + __u32 max_response_len; /* [i] response buffer size in bytes */ |
| 75 | + |
| 76 | + __u64 response; /* [i], [*o] response data address */ |
| 77 | + __u64 dout_xferp; /* [i], [*i] */ |
| 78 | + __u32 dout_xfer_len; /* [i] bytes to be transferred to device */ |
| 79 | + __u32 dout_iovec_count; /* [i] 0 -> "flat" dout transfer else |
| 80 | + * dout_xferp points to array of iovec |
| 81 | + */ |
| 82 | + __u64 din_xferp; /* [i], [*o] */ |
| 83 | + __u32 din_xfer_len; /* [i] bytes to be transferred from device */ |
| 84 | + __u32 din_iovec_count; /* [i] 0 -> "flat" din transfer */ |
| 85 | + |
| 86 | + __u32 timeout_ms; /* [i] timeout in milliseconds */ |
| 87 | + __u8 reserved[12]; /* reserved for future extension */ |
| 88 | +}; |
| 89 | + |
| 90 | +#ifdef __KERNEL__ |
| 91 | +/* Must match IORING_OP_URING_CMD payload size (e.g. SQE128). */ |
| 92 | +static_assert(sizeof(struct bsg_uring_cmd) == 80); |
| 93 | +#endif /* __KERNEL__ */ |
| 94 | + |
| 95 | + |
| 96 | +/* |
| 97 | + * SCSI BSG io_uring completion (res2, 64-bit) |
| 98 | + * |
| 99 | + * When using BSG_PROTOCOL_SCSI + BSG_SUB_PROTOCOL_SCSI_CMD with |
| 100 | + * IORING_OP_URING_CMD, the completion queue entry (CQE) contains: |
| 101 | + * - result: errno (0 on success) |
| 102 | + * - res2: packed SCSI status |
| 103 | + * |
| 104 | + * res2 bit layout: |
| 105 | + * [0..7] device_status (SCSI status byte, e.g. CHECK_CONDITION) |
| 106 | + * [8..15] driver_status (e.g. DRIVER_SENSE when sense data is valid) |
| 107 | + * [16..23] host_status (e.g. DID_OK, DID_TIME_OUT) |
| 108 | + * [24..31] sense_len_wr (bytes of sense data written to response buffer) |
| 109 | + * [32..63] resid_len (residual transfer length) |
| 110 | + */ |
| 111 | +static inline __u8 bsg_scsi_res2_device_status(__u64 res2) |
| 112 | +{ |
| 113 | + return res2 & 0xff; |
| 114 | +} |
| 115 | +static inline __u8 bsg_scsi_res2_driver_status(__u64 res2) |
| 116 | +{ |
| 117 | + return res2 >> 8; |
| 118 | +} |
| 119 | +static inline __u8 bsg_scsi_res2_host_status(__u64 res2) |
| 120 | +{ |
| 121 | + return res2 >> 16; |
| 122 | +} |
| 123 | +static inline __u8 bsg_scsi_res2_sense_len(__u64 res2) |
| 124 | +{ |
| 125 | + return res2 >> 24; |
| 126 | +} |
| 127 | +static inline __u32 bsg_scsi_res2_resid_len(__u64 res2) |
| 128 | +{ |
| 129 | + return res2 >> 32; |
| 130 | +} |
| 131 | +static inline __u64 bsg_scsi_res2_build(__u8 device_status, __u8 driver_status, |
| 132 | + __u8 host_status, __u8 sense_len_wr, |
| 133 | + __u32 resid_len) |
| 134 | +{ |
| 135 | + return ((__u64)(__u32)(resid_len) << 32) | |
| 136 | + ((__u64)sense_len_wr << 24) | |
| 137 | + ((__u64)host_status << 16) | |
| 138 | + ((__u64)driver_status << 8) | |
| 139 | + (__u64)device_status; |
| 140 | +} |
66 | 141 |
|
67 | 142 | #endif /* _UAPIBSG_H */ |
0 commit comments