Last active
June 27, 2016 18:33
-
-
Save barakmich/d59dfce33a7a68ad57f144001074df8c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __TARGET_CORE_USER_H | |
#define __TARGET_CORE_USER_H | |
/* This header will be used by application too */ | |
#include <linux/types.h> | |
#include <linux/uio.h> | |
#define TCMU_VERSION "2.0" | |
/* | |
* Ring Design | |
* ----------- | |
* | |
* The mmaped area is divided into three parts: | |
* 1) The mailbox (struct tcmu_mailbox, below) | |
* 2) The command ring | |
* 3) Everything beyond the command ring (data) | |
* | |
* The mailbox tells userspace the offset of the command ring from the | |
* start of the shared memory region, and how big the command ring is. | |
* | |
* The kernel passes SCSI commands to userspace by putting a struct | |
* tcmu_cmd_entry in the ring, updating mailbox->cmd_head, and poking | |
* userspace via uio's interrupt mechanism. | |
* | |
* tcmu_cmd_entry contains a header. If the header type is PAD, | |
* userspace should skip hdr->length bytes (mod cmdr_size) to find the | |
* next cmd_entry. | |
* | |
* Otherwise, the entry will contain offsets into the mmaped area that | |
* contain the cdb and data buffers -- the latter accessible via the | |
* iov array. iov addresses are also offsets into the shared area. | |
* | |
* When userspace is completed handling the command, set | |
* entry->rsp.scsi_status, fill in rsp.sense_buffer if appropriate, | |
* and also set mailbox->cmd_tail equal to the old cmd_tail plus | |
* hdr->length, mod cmdr_size. If cmd_tail doesn't equal cmd_head, it | |
* should process the next packet the same way, and so on. | |
*/ | |
#define TCMU_MAILBOX_VERSION 2 | |
#define ALIGN_SIZE 64 /* Should be enough for most CPUs */ | |
struct tcmu_mailbox { | |
__u16 version; | |
__u16 flags; | |
__u32 cmdr_off; | |
__u32 cmdr_size; | |
__u32 cmd_head; | |
/* Updated by user. On its own cacheline */ | |
__u32 cmd_tail __attribute__((__aligned__(ALIGN_SIZE))); | |
} __attribute__((packed)); | |
enum tcmu_opcode { | |
TCMU_OP_PAD = 0, | |
TCMU_OP_CMD, | |
}; | |
/* | |
* Only a few opcodes, and length is 8-byte aligned, so use low bits for opcode. | |
*/ | |
struct tcmu_cmd_entry_hdr { | |
__u32 len_op; | |
__u16 cmd_id; | |
__u8 kflags; | |
#define TCMU_UFLAG_UNKNOWN_OP 0x1 | |
__u8 uflags; | |
} __attribute__((packed)); | |
#define TCMU_OP_MASK 0x7 | |
static __inline__ enum tcmu_opcode tcmu_hdr_get_op(__u32 len_op) | |
{ | |
return len_op & TCMU_OP_MASK; | |
} | |
static __inline__ void tcmu_hdr_set_op(__u32 *len_op, enum tcmu_opcode op) | |
{ | |
*len_op &= ~TCMU_OP_MASK; | |
*len_op |= (op & TCMU_OP_MASK); | |
} | |
static __inline__ __u32 tcmu_hdr_get_len(__u32 len_op) | |
{ | |
return len_op & ~TCMU_OP_MASK; | |
} | |
static __inline__ void tcmu_hdr_set_len(__u32 *len_op, __u32 len) | |
{ | |
*len_op &= TCMU_OP_MASK; | |
*len_op |= len; | |
} | |
/* Currently the same as SCSI_SENSE_BUFFERSIZE */ | |
#define TCMU_SENSE_BUFFERSIZE 96 | |
struct tcmu_cmd_entry { | |
struct tcmu_cmd_entry_hdr hdr; | |
union { | |
struct { | |
uint32_t iov_cnt; | |
uint32_t iov_bidi_cnt; | |
uint32_t iov_dif_cnt; | |
uint64_t cdb_off; | |
uint64_t __pad1; | |
uint64_t __pad2; | |
struct iovec iov[0]; | |
} req; | |
struct { | |
uint8_t scsi_status; | |
uint8_t __pad1; | |
uint16_t __pad2; | |
uint32_t __pad3; | |
char sense_buffer[TCMU_SENSE_BUFFERSIZE]; | |
} rsp; | |
}; | |
} __attribute__((packed)); | |
#define TCMU_OP_ALIGN_SIZE sizeof(uint64_t) | |
enum tcmu_genl_cmd { | |
TCMU_CMD_UNSPEC, | |
TCMU_CMD_ADDED_DEVICE, | |
TCMU_CMD_REMOVED_DEVICE, | |
__TCMU_CMD_MAX, | |
}; | |
#define TCMU_CMD_MAX (__TCMU_CMD_MAX - 1) | |
enum tcmu_genl_attr { | |
TCMU_ATTR_UNSPEC, | |
TCMU_ATTR_DEVICE, | |
TCMU_ATTR_MINOR, | |
__TCMU_ATTR_MAX, | |
}; | |
#define TCMU_ATTR_MAX (__TCMU_ATTR_MAX - 1) | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <unistd.h> | |
#include <sys/types.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <linux/target_core_user.h> | |
int main(int argc, char *argv[]) { | |
char buf[128]; | |
memset(buf, 0x0, 128); | |
struct tcmu_cmd_entry* cmd = (struct tcmu_cmd_entry*)buf; | |
printf("%d\n", sizeof(struct tcmu_cmd_entry)); | |
cmd->hdr.len_op = 0x1; | |
cmd->hdr.cmd_id = 0x2; | |
cmd->hdr.kflags = 0x3; | |
cmd->hdr.uflags = 0x4; | |
cmd->req.iov_cnt = 0x5; | |
cmd->req.iov_bidi_cnt = 0x6; | |
cmd->req.iov_dif_cnt = 0x7; | |
cmd->req.cdb_off = 0x8; | |
cmd->req.__pad1 = 0xf; | |
cmd->req.__pad2 = 0xf; | |
cmd->req.iov[0].iov_base = (void*)0x23; | |
cmd->req.iov[0].iov_len = 0x24; | |
int i; | |
for (i=0;i<128;i++) { | |
printf("0x%02x ", buf[i]); | |
if (i%16==15) | |
printf("\n"); | |
} | |
printf("sizeof iov %d\n", sizeof(cmd->req.iov[0])); | |
printf("sizeof iov_base %d\n", sizeof(cmd->req.iov[0].iov_base)); | |
printf("sizeof iov_len %d\n", sizeof(cmd->req.iov[0].iov_len)); | |
memset(buf, 0x0, 128); | |
cmd->rsp.scsi_status = 0x2; | |
cmd->rsp.sense_buffer[0] = 0x6; | |
cmd->rsp.sense_buffer[1] = 0x7; | |
for (i=0;i<128;i++) { | |
printf("0x%02x ", buf[i]); | |
if (i%16==15) | |
printf("\n"); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment