Home | History | Annotate | Download | only in linux
      1 #ifndef __TARGET_CORE_USER_H
      2 #define __TARGET_CORE_USER_H
      3 
      4 /* This header will be used by application too */
      5 
      6 #include <linux/types.h>
      7 #include <linux/uio.h>
      8 
      9 #define TCMU_VERSION "1.0"
     10 
     11 /*
     12  * Ring Design
     13  * -----------
     14  *
     15  * The mmaped area is divided into three parts:
     16  * 1) The mailbox (struct tcmu_mailbox, below)
     17  * 2) The command ring
     18  * 3) Everything beyond the command ring (data)
     19  *
     20  * The mailbox tells userspace the offset of the command ring from the
     21  * start of the shared memory region, and how big the command ring is.
     22  *
     23  * The kernel passes SCSI commands to userspace by putting a struct
     24  * tcmu_cmd_entry in the ring, updating mailbox->cmd_head, and poking
     25  * userspace via uio's interrupt mechanism.
     26  *
     27  * tcmu_cmd_entry contains a header. If the header type is PAD,
     28  * userspace should skip hdr->length bytes (mod cmdr_size) to find the
     29  * next cmd_entry.
     30  *
     31  * Otherwise, the entry will contain offsets into the mmaped area that
     32  * contain the cdb and data buffers -- the latter accessible via the
     33  * iov array. iov addresses are also offsets into the shared area.
     34  *
     35  * When userspace is completed handling the command, set
     36  * entry->rsp.scsi_status, fill in rsp.sense_buffer if appropriate,
     37  * and also set mailbox->cmd_tail equal to the old cmd_tail plus
     38  * hdr->length, mod cmdr_size. If cmd_tail doesn't equal cmd_head, it
     39  * should process the next packet the same way, and so on.
     40  */
     41 
     42 #define TCMU_MAILBOX_VERSION 1
     43 #define ALIGN_SIZE 64 /* Should be enough for most CPUs */
     44 
     45 struct tcmu_mailbox {
     46 	__u16 version;
     47 	__u16 flags;
     48 	__u32 cmdr_off;
     49 	__u32 cmdr_size;
     50 
     51 	__u32 cmd_head;
     52 
     53 	/* Updated by user. On its own cacheline */
     54 	__u32 cmd_tail __attribute__((__aligned__(ALIGN_SIZE)));
     55 
     56 } __packed;
     57 
     58 enum tcmu_opcode {
     59 	TCMU_OP_PAD = 0,
     60 	TCMU_OP_CMD,
     61 };
     62 
     63 /*
     64  * Only a few opcodes, and length is 8-byte aligned, so use low bits for opcode.
     65  */
     66 struct tcmu_cmd_entry_hdr {
     67 		__u32 len_op;
     68 } __packed;
     69 
     70 #define TCMU_OP_MASK 0x7
     71 
     72 static inline enum tcmu_opcode tcmu_hdr_get_op(struct tcmu_cmd_entry_hdr *hdr)
     73 {
     74 	return hdr->len_op & TCMU_OP_MASK;
     75 }
     76 
     77 static inline void tcmu_hdr_set_op(struct tcmu_cmd_entry_hdr *hdr, enum tcmu_opcode op)
     78 {
     79 	hdr->len_op &= ~TCMU_OP_MASK;
     80 	hdr->len_op |= (op & TCMU_OP_MASK);
     81 }
     82 
     83 static inline __u32 tcmu_hdr_get_len(struct tcmu_cmd_entry_hdr *hdr)
     84 {
     85 	return hdr->len_op & ~TCMU_OP_MASK;
     86 }
     87 
     88 static inline void tcmu_hdr_set_len(struct tcmu_cmd_entry_hdr *hdr, __u32 len)
     89 {
     90 	hdr->len_op &= TCMU_OP_MASK;
     91 	hdr->len_op |= len;
     92 }
     93 
     94 /* Currently the same as SCSI_SENSE_BUFFERSIZE */
     95 #define TCMU_SENSE_BUFFERSIZE 96
     96 
     97 struct tcmu_cmd_entry {
     98 	struct tcmu_cmd_entry_hdr hdr;
     99 
    100 	uint16_t cmd_id;
    101 	uint16_t __pad1;
    102 
    103 	union {
    104 		struct {
    105 			uint64_t cdb_off;
    106 			uint64_t iov_cnt;
    107 			struct iovec iov[0];
    108 		} req;
    109 		struct {
    110 			uint8_t scsi_status;
    111 			uint8_t __pad1;
    112 			uint16_t __pad2;
    113 			uint32_t __pad3;
    114 			char sense_buffer[TCMU_SENSE_BUFFERSIZE];
    115 		} rsp;
    116 	};
    117 
    118 } __packed;
    119 
    120 #define TCMU_OP_ALIGN_SIZE sizeof(uint64_t)
    121 
    122 enum tcmu_genl_cmd {
    123 	TCMU_CMD_UNSPEC,
    124 	TCMU_CMD_ADDED_DEVICE,
    125 	TCMU_CMD_REMOVED_DEVICE,
    126 	__TCMU_CMD_MAX,
    127 };
    128 #define TCMU_CMD_MAX (__TCMU_CMD_MAX - 1)
    129 
    130 enum tcmu_genl_attr {
    131 	TCMU_ATTR_UNSPEC,
    132 	TCMU_ATTR_DEVICE,
    133 	TCMU_ATTR_MINOR,
    134 	__TCMU_ATTR_MAX,
    135 };
    136 #define TCMU_ATTR_MAX (__TCMU_ATTR_MAX - 1)
    137 
    138 #endif
    139