-
Notifications
You must be signed in to change notification settings - Fork 0
/
scsi.h
130 lines (115 loc) · 3.06 KB
/
scsi.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* Copyright 2021 IBM Corporation
*
* Author: Constantine Gavrilov
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _IO_BENCH_SCSI_H_
#define _IO_BENCH_SCSI_H_
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <scsi/sg.h>
#include <arpa/inet.h>
#include <byteswap.h>
#include <endian.h>
#ifndef SG_FLAG_MMAP_IO
#define SG_FLAG_MMAP_IO 4
#endif
#if __BYTE_ORDER == __LITTLE_ENDIAN
#ifndef ntohll
#define ntohll bswap_64
#endif
#ifndef htonll
#define htonll bswap_64
#endif
#elif __BYTE_ORDER == __BIG_ENDIAN
#ifndef ntohll
#define ntohll(x) (x)
#endif
#ifndef htonll
#define htonll(x) (x)
#endif
#endif
#define SENSE_BUF_LEN (64)
typedef struct {
int fd;
char *buf;
sg_io_hdr_t sg_cmd;
sg_io_hdr_t sg_resp;
uint8_t cdb[16];
unsigned char sense_buf[SENSE_BUF_LEN];
} sg_ioctx_t;
typedef struct {
const char *name;
sg_ioctx_t *ioctx;
uint32_t qs;
uint32_t bs;
uint32_t bs_lbas;
uint32_t lba_size;
uint64_t capacity;
} sg_open_params_t;
void close_sg_io_contexts(sg_open_params_t *params);
int open_sg_io_contexts(sg_open_params_t *params);
static inline void fill_rw_cdb16(uint8_t *cdb, uint64_t lba, uint32_t sectors)
{
uint64_t *p1 = (void *)&cdb[2];
uint32_t *p2 = (void *)&cdb[10];
*p1 = htonll(lba);
*p2 = htonl(sectors);
}
static inline int frame_sg_cmd(sg_ioctx_t *sg_ioctx, int direction, uint32_t bs)
{
sg_ioctx->sg_cmd = (sg_io_hdr_t) {
.interface_id = 'S',
.dxfer_direction = direction,
.cmd_len = 16,
.mx_sb_len = sizeof(sg_ioctx->sense_buf),
.iovec_count = 0,
.dxfer_len = bs,
.cmdp = sg_ioctx->cdb,
.sbp = sg_ioctx->sense_buf,
.timeout = 300000,
.flags = SG_FLAG_MMAP_IO
};
int rc = write(sg_ioctx->fd, &sg_ioctx->sg_cmd, sizeof(sg_ioctx->sg_cmd));
if (rc <= 0)
rc = errno ? -errno : -1;
return rc > 0 ? 0 : rc;
}
static inline int frame_sg_read_io(sg_ioctx_t *sg_ioctx, uint64_t lba, uint32_t sectors, uint32_t bs)
{
memset(sg_ioctx->cdb, 0, sizeof(sg_ioctx->cdb));
fill_rw_cdb16(sg_ioctx->cdb, lba, sectors);
sg_ioctx->cdb[0] = 0x88;
return frame_sg_cmd(sg_ioctx, SG_DXFER_FROM_DEV, bs);
}
static inline int frame_sg_write_io(sg_ioctx_t *sg_ioctx, uint64_t lba, uint32_t sectors, uint32_t bs)
{
memset(sg_ioctx->cdb, 0, sizeof(sg_ioctx->cdb));
fill_rw_cdb16(sg_ioctx->cdb, lba, sectors);
sg_ioctx->cdb[0] = 0x8a;
return frame_sg_cmd(sg_ioctx, SG_DXFER_TO_DEV, bs);
}
static int inline decode_sg_status(int rc, sg_io_hdr_t *sg_io)
{
if (rc > 0) {
if(!sg_io->status && (sg_io->host_status || sg_io->driver_status))
rc = -1;
else
rc = sg_io->status;
} else if (rc == 0) {
rc = -1;
}
return rc;
}
#endif