summaryrefslogtreecommitdiffstats
path: root/debian/grub-extras/disabled/gpxe/src/include/gpxe/scsi.h
blob: 97416970d4250c4de7ce4cae9362fbab82def175 (plain)
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
#ifndef _GPXE_SCSI_H
#define _GPXE_SCSI_H

#include <stdint.h>
#include <gpxe/blockdev.h>
#include <gpxe/uaccess.h>
#include <gpxe/refcnt.h>

/** @file
 *
 * SCSI devices
 *
 */

FILE_LICENCE ( GPL2_OR_LATER );

/**
 * @defgroup scsiops SCSI operation codes
 * @{
 */

#define SCSI_OPCODE_READ_10		0x28	/**< READ (10) */
#define SCSI_OPCODE_READ_16		0x88	/**< READ (16) */
#define SCSI_OPCODE_WRITE_10		0x2a	/**< WRITE (10) */
#define SCSI_OPCODE_WRITE_16		0x8a	/**< WRITE (16) */
#define SCSI_OPCODE_READ_CAPACITY_10	0x25	/**< READ CAPACITY (10) */
#define SCSI_OPCODE_SERVICE_ACTION_IN	0x9e	/**< SERVICE ACTION IN */
#define SCSI_SERVICE_ACTION_READ_CAPACITY_16 0x10 /**< READ CAPACITY (16) */

/** @} */

/**
 * @defgroup scsiflags SCSI flags
 * @{
 */

#define SCSI_FL_FUA_NV		0x02	/**< Force unit access to NVS */
#define SCSI_FL_FUA		0x08	/**< Force unit access */
#define SCSI_FL_DPO		0x10	/**< Disable cache page out */

/** @} */

/**
 * @defgroup scsicdbs SCSI command data blocks
 * @{
 */

/** A SCSI "READ (10)" CDB */
struct scsi_cdb_read_10 {
	/** Opcode (0x28) */
	uint8_t opcode;
	/** Flags */
	uint8_t flags;
	/** Start address
	 *
	 * This is a logical block number, in big-endian order.
	 */
	uint32_t lba;
	/** Group number */
	uint8_t group;
	/** Transfer length
	 *
	 * This is a logical block count, in big-endian order.
	 */
	uint16_t len;
	/** Control byte */
	uint8_t control;
} __attribute__ (( packed ));

/** A SCSI "READ (16)" CDB */
struct scsi_cdb_read_16 {
	/** Opcode (0x88) */
	uint8_t opcode;
	/** Flags */
	uint8_t flags;
	/** Start address
	 *
	 * This is a logical block number, in big-endian order.
	 */
	uint64_t lba;
	/** Transfer length
	 *
	 * This is a logical block count, in big-endian order.
	 */
	uint32_t len;
	/** Group number */
	uint8_t group;
	/** Control byte */
	uint8_t control;
} __attribute__ (( packed ));

/** A SCSI "WRITE (10)" CDB */
struct scsi_cdb_write_10 {
	/** Opcode (0x2a) */
	uint8_t opcode;
	/** Flags */
	uint8_t flags;
	/** Start address
	 *
	 * This is a logical block number, in big-endian order.
	 */
	uint32_t lba;
	/** Group number */
	uint8_t group;
	/** Transfer length
	 *
	 * This is a logical block count, in big-endian order.
	 */
	uint16_t len;
	/** Control byte */
	uint8_t control;
} __attribute__ (( packed ));

/** A SCSI "WRITE (16)" CDB */
struct scsi_cdb_write_16 {
	/** Opcode (0x8a) */
	uint8_t opcode;
	/** Flags */
	uint8_t flags;
	/** Start address
	 *
	 * This is a logical block number, in big-endian order.
	 */
	uint64_t lba;
	/** Transfer length
	 *
	 * This is a logical block count, in big-endian order.
	 */
	uint32_t len;
	/** Group number */
	uint8_t group;
	/** Control byte */
	uint8_t control;
} __attribute__ (( packed ));

/** A SCSI "READ CAPACITY (10)" CDB */
struct scsi_cdb_read_capacity_10 {
	/** Opcode (0x25) */
	uint8_t opcode;
	/** Reserved */
	uint8_t reserved_a;
	/** Logical block address
	 *
	 * Applicable only if the PMI bit is set.
	 */
	uint32_t lba;
	/** Reserved */
	uint8_t reserved_b[3];
	/** Control byte */
	uint8_t control;	
} __attribute__ (( packed ));

/** SCSI "READ CAPACITY (10)" parameter data */
struct scsi_capacity_10 {
	/** Maximum logical block number */
	uint32_t lba;
	/** Block length in bytes */
	uint32_t blksize;
} __attribute__ (( packed ));

/** A SCSI "READ CAPACITY (16)" CDB */
struct scsi_cdb_read_capacity_16 {
	/** Opcode (0x9e) */
	uint8_t opcode;
	/** Service action */
	uint8_t service_action;
	/** Logical block address
	 *
	 * Applicable only if the PMI bit is set.
	 */
	uint64_t lba;
	/** Transfer length
	 *
	 * This is the size of the data-in buffer, in bytes.
	 */
	uint32_t len;
	/** Reserved */
	uint8_t reserved;
	/** Control byte */
	uint8_t control;
} __attribute__ (( packed ));

/** SCSI "READ CAPACITY (16)" parameter data */
struct scsi_capacity_16 {
	/** Maximum logical block number */
	uint64_t lba;
	/** Block length in bytes */
	uint32_t blksize;
	/** Reserved */
	uint8_t reserved[20];
} __attribute__ (( packed ));

/** A SCSI Command Data Block */
union scsi_cdb {
	struct scsi_cdb_read_10 read10;
	struct scsi_cdb_read_16 read16;
	struct scsi_cdb_write_10 write10;
	struct scsi_cdb_write_16 write16;
	struct scsi_cdb_read_capacity_10 readcap10;
	struct scsi_cdb_read_capacity_16 readcap16;
	unsigned char bytes[16];
};

/** printf() format for dumping a scsi_cdb */
#define SCSI_CDB_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" \
			"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"

/** printf() parameters for dumping a scsi_cdb */
#define SCSI_CDB_DATA(cdb)						  \
	(cdb).bytes[0], (cdb).bytes[1], (cdb).bytes[2], (cdb).bytes[3],	  \
	(cdb).bytes[4], (cdb).bytes[5], (cdb).bytes[6], (cdb).bytes[7],	  \
	(cdb).bytes[8], (cdb).bytes[9], (cdb).bytes[10], (cdb).bytes[11], \
	(cdb).bytes[12], (cdb).bytes[13], (cdb).bytes[14], (cdb).bytes[15]

/** @} */

/** A SCSI command */
struct scsi_command {
	/** CDB for this command */
	union scsi_cdb cdb;
	/** Data-out buffer (may be NULL) */
	userptr_t data_out;
	/** Data-out buffer length
	 *
	 * Must be zero if @c data_out is NULL
	 */
	size_t data_out_len;
	/** Data-in buffer (may be NULL) */
	userptr_t data_in;
	/** Data-in buffer length
	 *
	 * Must be zero if @c data_in is NULL
	 */
	size_t data_in_len;
	/** SCSI status code */
	uint8_t status;
	/** SCSI sense response code */
	uint8_t sense_response;
	/** Command status code */
	int rc;
};

/** A SCSI LUN
 *
 * This is a four-level LUN as specified by SAM-2, in big-endian
 * order.
 */
struct scsi_lun {
	uint16_t u16[4];
}  __attribute__ (( packed ));

/** A SCSI device */
struct scsi_device {
	/** Block device interface */
	struct block_device blockdev;
	/**
	 * Issue SCSI command
	 *
	 * @v scsi		SCSI device
	 * @v command		SCSI command
	 * @ret rc		Return status code
	 *
	 * Note that a successful return status code indicates only
	 * that the SCSI command was issued.  The caller must check
	 * the status field in the command structure to see when the
	 * command completes and whether, for example, the device
	 * returned CHECK CONDITION or some other non-success status
	 * code.
	 */
	int ( * command ) ( struct scsi_device *scsi,
			    struct scsi_command *command );
	/** Backing device */
	struct refcnt *backend;
};

extern int scsi_detached_command ( struct scsi_device *scsi,
				   struct scsi_command *command );
extern int init_scsidev ( struct scsi_device *scsi );
extern int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun );

#endif /* _GPXE_SCSI_H */