1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2003 Silicon Graphics International Corp.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon
16 * including a substantially similar Disclaimer requirement for further
17 * binary redistribution.
18 *
19 * NO WARRANTY
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGES.
31 *
32 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_util.c#2 $
33 */
34 /*
35 * CAM Target Layer SCSI library
36 *
37 * Author: Ken Merry <ken@FreeBSD.org>
38 */
39
40 #ifdef _KERNEL
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/types.h>
45 #include <sys/malloc.h>
46 #else /* __KERNEL__ */
47 #include <sys/types.h>
48 #include <sys/time.h>
49 #include <stdint.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #endif /* __KERNEL__ */
54 #include <sys/sbuf.h>
55 #include <sys/queue.h>
56 #include <sys/callout.h>
57 #include <cam/scsi/scsi_all.h>
58 #include <cam/ctl/ctl_io.h>
59 #include <cam/ctl/ctl_nvme_all.h>
60 #include <cam/ctl/ctl_scsi_all.h>
61 #include <cam/ctl/ctl_util.h>
62
63 struct ctl_status_desc {
64 ctl_io_status status;
65 const char *description;
66 };
67
68 struct ctl_task_desc {
69 ctl_task_type task_action;
70 const char *description;
71 };
72 static struct ctl_status_desc ctl_status_table[] = {
73 {CTL_STATUS_NONE, "No Status"},
74 {CTL_SUCCESS, "Command Completed Successfully"},
75 {CTL_CMD_TIMEOUT, "Command Timed Out"},
76 {CTL_SEL_TIMEOUT, "Selection Timeout"},
77 {CTL_ERROR, "Command Failed"},
78 {CTL_SCSI_ERROR, "SCSI Error"},
79 {CTL_CMD_ABORTED, "Command Aborted"},
80 };
81
82 static struct ctl_task_desc ctl_task_table[] = {
83 {CTL_TASK_ABORT_TASK, "Abort Task"},
84 {CTL_TASK_ABORT_TASK_SET, "Abort Task Set"},
85 {CTL_TASK_CLEAR_ACA, "Clear ACA"},
86 {CTL_TASK_CLEAR_TASK_SET, "Clear Task Set"},
87 {CTL_TASK_I_T_NEXUS_RESET, "I_T Nexus Reset"},
88 {CTL_TASK_LUN_RESET, "LUN Reset"},
89 {CTL_TASK_TARGET_RESET, "Target Reset"},
90 {CTL_TASK_BUS_RESET, "Bus Reset"},
91 {CTL_TASK_PORT_LOGIN, "Port Login"},
92 {CTL_TASK_PORT_LOGOUT, "Port Logout"},
93 {CTL_TASK_QUERY_TASK, "Query Task"},
94 {CTL_TASK_QUERY_TASK_SET, "Query Task Set"},
95 {CTL_TASK_QUERY_ASYNC_EVENT, "Query Async Event"}
96 };
97
98 void
ctl_scsi_tur(union ctl_io * io,ctl_tag_type tag_type,uint8_t control)99 ctl_scsi_tur(union ctl_io *io, ctl_tag_type tag_type, uint8_t control)
100 {
101 struct ctl_scsiio *ctsio;
102 struct scsi_test_unit_ready *cdb;
103
104 ctl_scsi_zero_io(io);
105
106 io->io_hdr.io_type = CTL_IO_SCSI;
107 ctsio = &io->scsiio;
108 cdb = (struct scsi_test_unit_ready *)ctsio->cdb;
109
110 cdb->opcode = TEST_UNIT_READY;
111 cdb->control = control;
112 io->io_hdr.flags = CTL_FLAG_DATA_NONE;
113 ctsio->tag_type = tag_type;
114 ctsio->cdb_len = sizeof(*cdb);
115 ctsio->ext_data_len = 0;
116 ctsio->ext_data_ptr = NULL;
117 ctsio->ext_sg_entries = 0;
118 ctsio->ext_data_filled = 0;
119 ctsio->sense_len = SSD_FULL_SIZE;
120 }
121
122 void
ctl_scsi_inquiry(union ctl_io * io,uint8_t * data_ptr,int32_t data_len,uint8_t byte2,uint8_t page_code,ctl_tag_type tag_type,uint8_t control)123 ctl_scsi_inquiry(union ctl_io *io, uint8_t *data_ptr, int32_t data_len,
124 uint8_t byte2, uint8_t page_code, ctl_tag_type tag_type,
125 uint8_t control)
126 {
127 struct ctl_scsiio *ctsio;
128 struct scsi_inquiry *cdb;
129
130 ctl_scsi_zero_io(io);
131
132 io->io_hdr.io_type = CTL_IO_SCSI;
133 ctsio = &io->scsiio;
134 cdb = (struct scsi_inquiry *)ctsio->cdb;
135
136 cdb->opcode = INQUIRY;
137 cdb->byte2 = byte2;
138 cdb->page_code = page_code;
139 cdb->control = control;
140 scsi_ulto2b(data_len, cdb->length);
141 io->io_hdr.io_type = CTL_IO_SCSI;
142 io->io_hdr.flags = CTL_FLAG_DATA_IN;
143 ctsio->tag_type = tag_type;
144 ctsio->cdb_len = sizeof(*cdb);
145 ctsio->ext_data_len = data_len;
146 ctsio->ext_data_ptr = data_ptr;
147 ctsio->ext_sg_entries = 0;
148 ctsio->ext_data_filled = 0;
149 ctsio->sense_len = SSD_FULL_SIZE;
150 }
151
152 void
ctl_scsi_request_sense(union ctl_io * io,uint8_t * data_ptr,int32_t data_len,uint8_t byte2,ctl_tag_type tag_type,uint8_t control)153 ctl_scsi_request_sense(union ctl_io *io, uint8_t *data_ptr,
154 int32_t data_len, uint8_t byte2, ctl_tag_type tag_type,
155 uint8_t control)
156 {
157 struct ctl_scsiio *ctsio;
158 struct scsi_request_sense *cdb;
159
160 ctl_scsi_zero_io(io);
161
162 io->io_hdr.io_type = CTL_IO_SCSI;
163 ctsio = &io->scsiio;
164 cdb = (struct scsi_request_sense *)ctsio->cdb;
165
166 cdb->opcode = REQUEST_SENSE;
167 cdb->byte2 = byte2;
168 cdb->control = control;
169 cdb->length = data_len;
170 io->io_hdr.io_type = CTL_IO_SCSI;
171 io->io_hdr.flags = CTL_FLAG_DATA_IN;
172 ctsio->tag_type = tag_type;
173 ctsio->cdb_len = sizeof(*cdb);
174 ctsio->ext_data_ptr = data_ptr;
175 ctsio->ext_data_len = data_len;
176 ctsio->ext_sg_entries = 0;
177 ctsio->ext_data_filled = 0;
178 ctsio->sense_len = SSD_FULL_SIZE;
179 }
180
181 void
ctl_scsi_report_luns(union ctl_io * io,uint8_t * data_ptr,uint32_t data_len,uint8_t select_report,ctl_tag_type tag_type,uint8_t control)182 ctl_scsi_report_luns(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
183 uint8_t select_report, ctl_tag_type tag_type,
184 uint8_t control)
185 {
186 struct ctl_scsiio *ctsio;
187 struct scsi_report_luns *cdb;
188
189 ctl_scsi_zero_io(io);
190
191 io->io_hdr.io_type = CTL_IO_SCSI;
192 ctsio = &io->scsiio;
193 cdb = (struct scsi_report_luns *)ctsio->cdb;
194
195 cdb->opcode = REPORT_LUNS;
196 cdb->select_report = select_report;
197 scsi_ulto4b(data_len, cdb->length);
198 cdb->control = control;
199 io->io_hdr.io_type = CTL_IO_SCSI;
200 io->io_hdr.flags = CTL_FLAG_DATA_IN;
201 ctsio->tag_type = tag_type;
202 ctsio->cdb_len = sizeof(*cdb);
203 ctsio->ext_data_ptr = data_ptr;
204 ctsio->ext_data_len = data_len;
205 ctsio->ext_sg_entries = 0;
206 ctsio->ext_data_filled = 0;
207 ctsio->sense_len = SSD_FULL_SIZE;
208 }
209
210 void
ctl_scsi_read_write_buffer(union ctl_io * io,uint8_t * data_ptr,uint32_t data_len,int read_buffer,uint8_t mode,uint8_t buffer_id,uint32_t buffer_offset,ctl_tag_type tag_type,uint8_t control)211 ctl_scsi_read_write_buffer(union ctl_io *io, uint8_t *data_ptr,
212 uint32_t data_len, int read_buffer, uint8_t mode,
213 uint8_t buffer_id, uint32_t buffer_offset,
214 ctl_tag_type tag_type, uint8_t control)
215 {
216 struct ctl_scsiio *ctsio;
217 struct scsi_write_buffer *cdb;
218
219 ctl_scsi_zero_io(io);
220
221 io->io_hdr.io_type = CTL_IO_SCSI;
222 ctsio = &io->scsiio;
223 cdb = (struct scsi_write_buffer *)ctsio->cdb;
224
225 if (read_buffer != 0)
226 cdb->opcode = READ_BUFFER;
227 else
228 cdb->opcode = WRITE_BUFFER;
229
230 cdb->byte2 = mode & RWB_MODE;
231 cdb->buffer_id = buffer_id;
232 scsi_ulto3b(buffer_offset, cdb->offset);
233 scsi_ulto3b(data_len, cdb->length);
234 cdb->control = control;
235 io->io_hdr.io_type = CTL_IO_SCSI;
236 if (read_buffer != 0)
237 io->io_hdr.flags = CTL_FLAG_DATA_IN;
238 else
239 io->io_hdr.flags = CTL_FLAG_DATA_OUT;
240 ctsio->tag_type = tag_type;
241 ctsio->cdb_len = sizeof(*cdb);
242 ctsio->ext_data_ptr = data_ptr;
243 ctsio->ext_data_len = data_len;
244 ctsio->ext_sg_entries = 0;
245 ctsio->ext_data_filled = 0;
246 ctsio->sense_len = SSD_FULL_SIZE;
247 }
248
249 void
ctl_scsi_read_write(union ctl_io * io,uint8_t * data_ptr,uint32_t data_len,int read_op,uint8_t byte2,int minimum_cdb_size,uint64_t lba,uint32_t num_blocks,ctl_tag_type tag_type,uint8_t control)250 ctl_scsi_read_write(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
251 int read_op, uint8_t byte2, int minimum_cdb_size,
252 uint64_t lba, uint32_t num_blocks, ctl_tag_type tag_type,
253 uint8_t control)
254 {
255 struct ctl_scsiio *ctsio;
256
257 ctl_scsi_zero_io(io);
258
259 io->io_hdr.io_type = CTL_IO_SCSI;
260 ctsio = &io->scsiio;
261
262 /*
263 * Pick out the smallest CDB that will hold the user's request.
264 * minimum_cdb_size allows cranking the CDB size up, even for
265 * requests that would not normally need a large CDB. This can be
266 * useful for testing (e.g. to make sure READ_16 support works without
267 * having an array larger than 2TB) and for compatibility -- e.g.
268 * if your device doesn't support READ_6. (ATAPI drives don't.)
269 */
270 if ((minimum_cdb_size < 10)
271 && ((lba & 0x1fffff) == lba)
272 && ((num_blocks & 0xff) == num_blocks)
273 && (byte2 == 0)) {
274 struct scsi_rw_6 *cdb;
275
276 /*
277 * Note that according to SBC-2, the target should return 256
278 * blocks if the transfer length in a READ(6) or WRITE(6) CDB
279 * is set to 0. Since it's possible that some targets
280 * won't do the right thing, we only send a READ(6) or
281 * WRITE(6) for transfer sizes up to and including 255 blocks.
282 */
283 cdb = (struct scsi_rw_6 *)ctsio->cdb;
284
285 cdb->opcode = (read_op) ? READ_6 : WRITE_6;
286 scsi_ulto3b(lba, cdb->addr);
287 cdb->length = num_blocks & 0xff;
288 cdb->control = control;
289
290 ctsio->cdb_len = sizeof(*cdb);
291
292 } else if ((minimum_cdb_size < 12)
293 && ((num_blocks & 0xffff) == num_blocks)
294 && ((lba & 0xffffffff) == lba)) {
295 struct scsi_rw_10 *cdb;
296
297 cdb = (struct scsi_rw_10 *)ctsio->cdb;
298
299 cdb->opcode = (read_op) ? READ_10 : WRITE_10;
300 cdb->byte2 = byte2;
301 scsi_ulto4b(lba, cdb->addr);
302 cdb->reserved = 0;
303 scsi_ulto2b(num_blocks, cdb->length);
304 cdb->control = control;
305
306 ctsio->cdb_len = sizeof(*cdb);
307 } else if ((minimum_cdb_size < 16)
308 && ((num_blocks & 0xffffffff) == num_blocks)
309 && ((lba & 0xffffffff) == lba)) {
310 struct scsi_rw_12 *cdb;
311
312 cdb = (struct scsi_rw_12 *)ctsio->cdb;
313
314 cdb->opcode = (read_op) ? READ_12 : WRITE_12;
315 cdb->byte2 = byte2;
316 scsi_ulto4b(lba, cdb->addr);
317 scsi_ulto4b(num_blocks, cdb->length);
318 cdb->reserved = 0;
319 cdb->control = control;
320
321 ctsio->cdb_len = sizeof(*cdb);
322 } else {
323 struct scsi_rw_16 *cdb;
324
325 cdb = (struct scsi_rw_16 *)ctsio->cdb;
326
327 cdb->opcode = (read_op) ? READ_16 : WRITE_16;
328 cdb->byte2 = byte2;
329 scsi_u64to8b(lba, cdb->addr);
330 scsi_ulto4b(num_blocks, cdb->length);
331 cdb->reserved = 0;
332 cdb->control = control;
333
334 ctsio->cdb_len = sizeof(*cdb);
335 }
336
337 io->io_hdr.io_type = CTL_IO_SCSI;
338 if (read_op != 0)
339 io->io_hdr.flags = CTL_FLAG_DATA_IN;
340 else
341 io->io_hdr.flags = CTL_FLAG_DATA_OUT;
342 ctsio->tag_type = tag_type;
343 ctsio->ext_data_ptr = data_ptr;
344 ctsio->ext_data_len = data_len;
345 ctsio->ext_sg_entries = 0;
346 ctsio->ext_data_filled = 0;
347 ctsio->sense_len = SSD_FULL_SIZE;
348 }
349
350 void
ctl_scsi_write_same(union ctl_io * io,uint8_t * data_ptr,uint32_t data_len,uint8_t byte2,uint64_t lba,uint32_t num_blocks,ctl_tag_type tag_type,uint8_t control)351 ctl_scsi_write_same(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
352 uint8_t byte2, uint64_t lba, uint32_t num_blocks,
353 ctl_tag_type tag_type, uint8_t control)
354 {
355 struct ctl_scsiio *ctsio;
356 struct scsi_write_same_16 *cdb;
357
358 ctl_scsi_zero_io(io);
359
360 io->io_hdr.io_type = CTL_IO_SCSI;
361 ctsio = &io->scsiio;
362 ctsio->cdb_len = sizeof(*cdb);
363 cdb = (struct scsi_write_same_16 *)ctsio->cdb;
364 cdb->opcode = WRITE_SAME_16;
365 cdb->byte2 = byte2;
366 scsi_u64to8b(lba, cdb->addr);
367 scsi_ulto4b(num_blocks, cdb->length);
368 cdb->group = 0;
369 cdb->control = control;
370
371 io->io_hdr.io_type = CTL_IO_SCSI;
372 io->io_hdr.flags = CTL_FLAG_DATA_OUT;
373 ctsio->tag_type = tag_type;
374 ctsio->ext_data_ptr = data_ptr;
375 ctsio->ext_data_len = data_len;
376 ctsio->ext_sg_entries = 0;
377 ctsio->ext_data_filled = 0;
378 ctsio->sense_len = SSD_FULL_SIZE;
379 }
380
381 void
ctl_scsi_read_capacity(union ctl_io * io,uint8_t * data_ptr,uint32_t data_len,uint32_t addr,int reladr,int pmi,ctl_tag_type tag_type,uint8_t control)382 ctl_scsi_read_capacity(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
383 uint32_t addr, int reladr, int pmi,
384 ctl_tag_type tag_type, uint8_t control)
385 {
386 struct scsi_read_capacity *cdb;
387
388 ctl_scsi_zero_io(io);
389
390 io->io_hdr.io_type = CTL_IO_SCSI;
391 cdb = (struct scsi_read_capacity *)io->scsiio.cdb;
392
393 cdb->opcode = READ_CAPACITY;
394 if (reladr)
395 cdb->byte2 = SRC_RELADR;
396 if (pmi)
397 cdb->pmi = SRC_PMI;
398 scsi_ulto4b(addr, cdb->addr);
399 cdb->control = control;
400 io->io_hdr.io_type = CTL_IO_SCSI;
401 io->io_hdr.flags = CTL_FLAG_DATA_IN;
402 io->scsiio.tag_type = tag_type;
403 io->scsiio.ext_data_ptr = data_ptr;
404 io->scsiio.ext_data_len = data_len;
405 io->scsiio.ext_sg_entries = 0;
406 io->scsiio.ext_data_filled = 0;
407 io->scsiio.sense_len = SSD_FULL_SIZE;
408 }
409
410 void
ctl_scsi_read_capacity_16(union ctl_io * io,uint8_t * data_ptr,uint32_t data_len,uint64_t addr,int reladr,int pmi,ctl_tag_type tag_type,uint8_t control)411 ctl_scsi_read_capacity_16(union ctl_io *io, uint8_t *data_ptr,
412 uint32_t data_len, uint64_t addr, int reladr,
413 int pmi, ctl_tag_type tag_type, uint8_t control)
414 {
415 struct scsi_read_capacity_16 *cdb;
416
417 ctl_scsi_zero_io(io);
418
419 io->io_hdr.io_type = CTL_IO_SCSI;
420 cdb = (struct scsi_read_capacity_16 *)io->scsiio.cdb;
421
422 cdb->opcode = SERVICE_ACTION_IN;
423 cdb->service_action = SRC16_SERVICE_ACTION;
424 if (reladr)
425 cdb->reladr |= SRC16_RELADR;
426 if (pmi)
427 cdb->reladr |= SRC16_PMI;
428 scsi_u64to8b(addr, cdb->addr);
429 scsi_ulto4b(data_len, cdb->alloc_len);
430 cdb->control = control;
431
432 io->io_hdr.io_type = CTL_IO_SCSI;
433 io->io_hdr.flags = CTL_FLAG_DATA_IN;
434 io->scsiio.tag_type = tag_type;
435 io->scsiio.ext_data_ptr = data_ptr;
436 io->scsiio.ext_data_len = data_len;
437 io->scsiio.ext_sg_entries = 0;
438 io->scsiio.ext_data_filled = 0;
439 io->scsiio.sense_len = SSD_FULL_SIZE;
440 }
441
442 void
ctl_scsi_mode_sense(union ctl_io * io,uint8_t * data_ptr,uint32_t data_len,int dbd,int llbaa,uint8_t page_code,uint8_t pc,uint8_t subpage,int minimum_cdb_size,ctl_tag_type tag_type,uint8_t control)443 ctl_scsi_mode_sense(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
444 int dbd, int llbaa, uint8_t page_code, uint8_t pc,
445 uint8_t subpage, int minimum_cdb_size,
446 ctl_tag_type tag_type, uint8_t control)
447 {
448 ctl_scsi_zero_io(io);
449
450 if ((minimum_cdb_size < 10)
451 && (llbaa == 0)
452 && (data_len < 256)) {
453 struct scsi_mode_sense_6 *cdb;
454
455 cdb = (struct scsi_mode_sense_6 *)io->scsiio.cdb;
456
457 cdb->opcode = MODE_SENSE_6;
458 if (dbd)
459 cdb->byte2 |= SMS_DBD;
460 cdb->page = page_code | pc;
461 cdb->subpage = subpage;
462 cdb->length = data_len;
463 cdb->control = control;
464 } else {
465 struct scsi_mode_sense_10 *cdb;
466
467 cdb = (struct scsi_mode_sense_10 *)io->scsiio.cdb;
468
469 cdb->opcode = MODE_SENSE_10;
470 if (dbd)
471 cdb->byte2 |= SMS_DBD;
472 if (llbaa)
473 cdb->byte2 |= SMS10_LLBAA;
474 cdb->page = page_code | pc;
475 cdb->subpage = subpage;
476 scsi_ulto2b(data_len, cdb->length);
477 cdb->control = control;
478 }
479
480 io->io_hdr.io_type = CTL_IO_SCSI;
481 io->io_hdr.flags = CTL_FLAG_DATA_IN;
482 io->scsiio.tag_type = tag_type;
483 io->scsiio.ext_data_ptr = data_ptr;
484 io->scsiio.ext_data_len = data_len;
485 io->scsiio.ext_sg_entries = 0;
486 io->scsiio.ext_data_filled = 0;
487 io->scsiio.sense_len = SSD_FULL_SIZE;
488 }
489
490 void
ctl_scsi_start_stop(union ctl_io * io,int start,int load_eject,int immediate,int power_conditions,ctl_tag_type tag_type,uint8_t control)491 ctl_scsi_start_stop(union ctl_io *io, int start, int load_eject, int immediate,
492 int power_conditions, ctl_tag_type tag_type, uint8_t control)
493 {
494 struct scsi_start_stop_unit *cdb;
495
496 cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb;
497
498 ctl_scsi_zero_io(io);
499
500 cdb->opcode = START_STOP_UNIT;
501 if (immediate)
502 cdb->byte2 |= SSS_IMMED;
503 cdb->how = power_conditions;
504 if (load_eject)
505 cdb->how |= SSS_LOEJ;
506 if (start)
507 cdb->how |= SSS_START;
508 cdb->control = control;
509 io->io_hdr.io_type = CTL_IO_SCSI;
510 io->io_hdr.flags = CTL_FLAG_DATA_NONE;
511 io->scsiio.tag_type = tag_type;
512 io->scsiio.ext_data_ptr = NULL;
513 io->scsiio.ext_data_len = 0;
514 io->scsiio.ext_sg_entries = 0;
515 io->scsiio.ext_data_filled = 0;
516 io->scsiio.sense_len = SSD_FULL_SIZE;
517 }
518
519 void
ctl_scsi_sync_cache(union ctl_io * io,int immed,int reladr,int minimum_cdb_size,uint64_t starting_lba,uint32_t block_count,ctl_tag_type tag_type,uint8_t control)520 ctl_scsi_sync_cache(union ctl_io *io, int immed, int reladr,
521 int minimum_cdb_size, uint64_t starting_lba,
522 uint32_t block_count, ctl_tag_type tag_type,
523 uint8_t control)
524 {
525 ctl_scsi_zero_io(io);
526
527 if ((minimum_cdb_size < 16)
528 && ((block_count & 0xffff) == block_count)
529 && ((starting_lba & 0xffffffff) == starting_lba)) {
530 struct scsi_sync_cache *cdb;
531
532 cdb = (struct scsi_sync_cache *)io->scsiio.cdb;
533
534 cdb->opcode = SYNCHRONIZE_CACHE;
535 if (reladr)
536 cdb->byte2 |= SSC_RELADR;
537
538 if (immed)
539 cdb->byte2 |= SSC_IMMED;
540
541 scsi_ulto4b(starting_lba, cdb->begin_lba);
542 scsi_ulto2b(block_count, cdb->lb_count);
543 cdb->control = control;
544 } else {
545 struct scsi_sync_cache_16 *cdb;
546
547 cdb = (struct scsi_sync_cache_16 *)io->scsiio.cdb;
548
549 cdb->opcode = SYNCHRONIZE_CACHE_16;
550 if (reladr)
551 cdb->byte2 |= SSC_RELADR;
552
553 if (immed)
554 cdb->byte2 |= SSC_IMMED;
555
556 scsi_u64to8b(starting_lba, cdb->begin_lba);
557 scsi_ulto4b(block_count, cdb->lb_count);
558 cdb->control = control;
559 }
560 io->io_hdr.io_type = CTL_IO_SCSI;
561 io->io_hdr.flags = CTL_FLAG_DATA_NONE;
562 io->scsiio.tag_type = tag_type;
563 io->scsiio.ext_data_ptr = NULL;
564 io->scsiio.ext_data_len = 0;
565 io->scsiio.ext_sg_entries = 0;
566 io->scsiio.ext_data_filled = 0;
567 io->scsiio.sense_len = SSD_FULL_SIZE;
568 }
569
570 void
ctl_scsi_persistent_res_in(union ctl_io * io,uint8_t * data_ptr,uint32_t data_len,int action,ctl_tag_type tag_type,uint8_t control)571 ctl_scsi_persistent_res_in(union ctl_io *io, uint8_t *data_ptr,
572 uint32_t data_len, int action,
573 ctl_tag_type tag_type, uint8_t control)
574 {
575
576 struct scsi_per_res_in *cdb;
577
578 ctl_scsi_zero_io(io);
579
580 cdb = (struct scsi_per_res_in *)io->scsiio.cdb;
581 cdb->opcode = PERSISTENT_RES_IN;
582 cdb->action = action;
583 scsi_ulto2b(data_len, cdb->length);
584 cdb->control = control;
585
586 io->io_hdr.io_type = CTL_IO_SCSI;
587 io->io_hdr.flags = CTL_FLAG_DATA_IN;
588 io->scsiio.tag_type = tag_type;
589 io->scsiio.ext_data_ptr = data_ptr;
590 io->scsiio.ext_data_len = data_len;
591 io->scsiio.ext_sg_entries = 0;
592 io->scsiio.ext_data_filled = 0;
593 io->scsiio.sense_len = SSD_FULL_SIZE;
594 }
595
596 void
ctl_scsi_persistent_res_out(union ctl_io * io,uint8_t * data_ptr,uint32_t data_len,int action,int type,uint64_t key,uint64_t sa_key,ctl_tag_type tag_type,uint8_t control)597 ctl_scsi_persistent_res_out(union ctl_io *io, uint8_t *data_ptr,
598 uint32_t data_len, int action, int type,
599 uint64_t key, uint64_t sa_key,
600 ctl_tag_type tag_type, uint8_t control)
601 {
602
603 struct scsi_per_res_out *cdb;
604 struct scsi_per_res_out_parms *params;
605
606 ctl_scsi_zero_io(io);
607
608 cdb = (struct scsi_per_res_out *)io->scsiio.cdb;
609 params = (struct scsi_per_res_out_parms *)data_ptr;
610
611 cdb->opcode = PERSISTENT_RES_OUT;
612 if (action == 5)
613 cdb->action = 6;
614 else
615 cdb->action = action;
616 switch(type)
617 {
618 case 0:
619 cdb->scope_type = 1;
620 break;
621 case 1:
622 cdb->scope_type = 3;
623 break;
624 case 2:
625 cdb->scope_type = 5;
626 break;
627 case 3:
628 cdb->scope_type = 6;
629 break;
630 case 4:
631 cdb->scope_type = 7;
632 break;
633 case 5:
634 cdb->scope_type = 8;
635 break;
636 }
637 scsi_ulto4b(data_len, cdb->length);
638 cdb->control = control;
639
640 scsi_u64to8b(key, params->res_key.key);
641 scsi_u64to8b(sa_key, params->serv_act_res_key);
642
643 io->io_hdr.io_type = CTL_IO_SCSI;
644 io->io_hdr.flags = CTL_FLAG_DATA_OUT;
645 io->scsiio.tag_type = tag_type;
646 io->scsiio.ext_data_ptr = data_ptr;
647 io->scsiio.ext_data_len = data_len;
648 io->scsiio.ext_sg_entries = 0;
649 io->scsiio.ext_data_filled = 0;
650 io->scsiio.sense_len = SSD_FULL_SIZE;
651
652 }
653
654 void
ctl_scsi_maintenance_in(union ctl_io * io,uint8_t * data_ptr,uint32_t data_len,uint8_t action,ctl_tag_type tag_type,uint8_t control)655 ctl_scsi_maintenance_in(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
656 uint8_t action, ctl_tag_type tag_type, uint8_t control)
657 {
658 struct scsi_maintenance_in *cdb;
659
660 ctl_scsi_zero_io(io);
661
662 cdb = (struct scsi_maintenance_in *)io->scsiio.cdb;
663 cdb->opcode = MAINTENANCE_IN;
664 cdb->byte2 = action;
665 scsi_ulto4b(data_len, cdb->length);
666 cdb->control = control;
667
668 io->io_hdr.io_type = CTL_IO_SCSI;
669 io->io_hdr.flags = CTL_FLAG_DATA_IN;
670 io->scsiio.tag_type = tag_type;
671 io->scsiio.ext_data_ptr = data_ptr;
672 io->scsiio.ext_data_len = data_len;
673 io->scsiio.ext_sg_entries = 0;
674 io->scsiio.ext_data_filled = 0;
675 io->scsiio.sense_len = SSD_FULL_SIZE;
676 }
677
678 #ifndef _KERNEL
679 union ctl_io *
ctl_scsi_alloc_io(uint32_t initid)680 ctl_scsi_alloc_io(uint32_t initid)
681 {
682 union ctl_io *io;
683
684 io = (union ctl_io *)malloc(sizeof(*io));
685 if (io == NULL)
686 goto bailout;
687
688 io->io_hdr.nexus.initid = initid;
689
690 bailout:
691 return (io);
692 }
693
694 void
ctl_scsi_free_io(union ctl_io * io)695 ctl_scsi_free_io(union ctl_io *io)
696 {
697 free(io);
698 }
699
700 void
ctl_scsi_zero_io(union ctl_io * io)701 ctl_scsi_zero_io(union ctl_io *io)
702 {
703 void *pool_ref;
704
705 if (io == NULL)
706 return;
707
708 pool_ref = io->io_hdr.pool;
709 memset(io, 0, sizeof(*io));
710 io->io_hdr.pool = pool_ref;
711 }
712 #endif /* !_KERNEL */
713
714 const char *
ctl_scsi_task_string(struct ctl_taskio * taskio)715 ctl_scsi_task_string(struct ctl_taskio *taskio)
716 {
717 unsigned int i;
718
719 for (i = 0; i < (sizeof(ctl_task_table)/sizeof(ctl_task_table[0]));
720 i++) {
721 if (taskio->task_action == ctl_task_table[i].task_action) {
722 return (ctl_task_table[i].description);
723 }
724 }
725
726 return (NULL);
727 }
728
729 void
ctl_io_sbuf(union ctl_io * io,struct sbuf * sb)730 ctl_io_sbuf(union ctl_io *io, struct sbuf *sb)
731 {
732 const char *task_desc;
733 char path_str[64];
734
735 ctl_scsi_path_string(&io->io_hdr, path_str, sizeof(path_str));
736
737 switch (io->io_hdr.io_type) {
738 case CTL_IO_SCSI:
739 sbuf_cat(sb, path_str);
740 ctl_scsi_command_string(&io->scsiio, NULL, sb);
741 sbuf_printf(sb, " Tag: %#jx/%d, Prio: %d\n",
742 io->scsiio.tag_num, io->scsiio.tag_type,
743 io->scsiio.priority);
744 break;
745 case CTL_IO_TASK:
746 sbuf_cat(sb, path_str);
747 task_desc = ctl_scsi_task_string(&io->taskio);
748 if (task_desc == NULL)
749 sbuf_printf(sb, "Unknown Task Action %d (%#x)",
750 io->taskio.task_action, io->taskio.task_action);
751 else
752 sbuf_printf(sb, "Task Action: %s", task_desc);
753 switch (io->taskio.task_action) {
754 case CTL_TASK_ABORT_TASK:
755 sbuf_printf(sb, " Tag: %#jx/%d\n",
756 io->taskio.tag_num, io->taskio.tag_type);
757 break;
758 default:
759 sbuf_putc(sb, '\n');
760 break;
761 }
762 break;
763 case CTL_IO_NVME:
764 case CTL_IO_NVME_ADMIN:
765 sbuf_cat(sb, path_str);
766 ctl_nvme_command_string(&io->nvmeio, sb);
767 sbuf_printf(sb, " CID: 0x%x\n", le16toh(io->nvmeio.cmd.cid));
768 break;
769 default:
770 break;
771 }
772 }
773
774 void
ctl_io_error_sbuf(union ctl_io * io,struct scsi_inquiry_data * inq_data,struct sbuf * sb)775 ctl_io_error_sbuf(union ctl_io *io, struct scsi_inquiry_data *inq_data,
776 struct sbuf *sb)
777 {
778 struct ctl_status_desc *status_desc;
779 char path_str[64];
780 unsigned int i;
781
782 ctl_io_sbuf(io, sb);
783
784 status_desc = NULL;
785 for (i = 0; i < (sizeof(ctl_status_table)/sizeof(ctl_status_table[0]));
786 i++) {
787 if ((io->io_hdr.status & CTL_STATUS_MASK) ==
788 ctl_status_table[i].status) {
789 status_desc = &ctl_status_table[i];
790 break;
791 }
792 }
793
794 ctl_scsi_path_string(&io->io_hdr, path_str, sizeof(path_str));
795
796 sbuf_cat(sb, path_str);
797 if (status_desc == NULL)
798 sbuf_printf(sb, "CTL Status: Unknown status %#x\n",
799 io->io_hdr.status);
800 else
801 sbuf_printf(sb, "CTL Status: %s\n", status_desc->description);
802
803 switch (io->io_hdr.io_type) {
804 case CTL_IO_SCSI:
805 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SCSI_ERROR) {
806 sbuf_cat(sb, path_str);
807 sbuf_printf(sb, "SCSI Status: %s\n",
808 ctl_scsi_status_string(&io->scsiio));
809
810 if (io->scsiio.scsi_status == SCSI_STATUS_CHECK_COND)
811 ctl_scsi_sense_sbuf(&io->scsiio, inq_data,
812 sb, SSS_FLAG_NONE);
813 }
814 break;
815 case CTL_IO_NVME:
816 case CTL_IO_NVME_ADMIN:
817 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_NVME_ERROR) {
818 sbuf_cat(sb, path_str);
819 sbuf_printf(sb, "NVMe Status: ");
820 ctl_nvme_status_string(&io->nvmeio, sb);
821 sbuf_printf(sb, "\n");
822 }
823 break;
824 default:
825 break;
826 }
827 }
828
829 char *
ctl_io_string(union ctl_io * io,char * str,int str_len)830 ctl_io_string(union ctl_io *io, char *str, int str_len)
831 {
832 struct sbuf sb;
833
834 sbuf_new(&sb, str, str_len, SBUF_FIXEDLEN);
835 ctl_io_sbuf(io, &sb);
836 sbuf_finish(&sb);
837 return (sbuf_data(&sb));
838 }
839
840 char *
ctl_io_error_string(union ctl_io * io,struct scsi_inquiry_data * inq_data,char * str,int str_len)841 ctl_io_error_string(union ctl_io *io, struct scsi_inquiry_data *inq_data,
842 char *str, int str_len)
843 {
844 struct sbuf sb;
845
846 sbuf_new(&sb, str, str_len, SBUF_FIXEDLEN);
847 ctl_io_error_sbuf(io, inq_data, &sb);
848 sbuf_finish(&sb);
849 return (sbuf_data(&sb));
850 }
851
852 #ifdef _KERNEL
853
854 void
ctl_io_print(union ctl_io * io)855 ctl_io_print(union ctl_io *io)
856 {
857 char str[512];
858
859 printf("%s", ctl_io_string(io, str, sizeof(str)));
860 }
861
862 void
ctl_io_error_print(union ctl_io * io,struct scsi_inquiry_data * inq_data)863 ctl_io_error_print(union ctl_io *io, struct scsi_inquiry_data *inq_data)
864 {
865 char str[512];
866
867 printf("%s", ctl_io_error_string(io, inq_data, str, sizeof(str)));
868
869 }
870
871 void
ctl_data_print(union ctl_io * io)872 ctl_data_print(union ctl_io *io)
873 {
874 char str[128];
875 char path_str[64];
876 struct sbuf sb;
877 uintmax_t tag_num;
878 int i, j, len;
879
880 switch (io->io_hdr.io_type) {
881 case CTL_IO_SCSI:
882 tag_num = io->scsiio.tag_num;
883 break;
884 case CTL_IO_NVME:
885 case CTL_IO_NVME_ADMIN:
886 tag_num = le16toh(io->nvmeio.cmd.cid);
887 break;
888 default:
889 return;
890 }
891 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
892 return;
893 if (ctl_kern_sg_entries(io) > 0) /* XXX: Implement */
894 return;
895 ctl_scsi_path_string(&io->io_hdr, path_str, sizeof(path_str));
896 len = min(ctl_kern_data_len(io), 4096);
897 for (i = 0; i < len; ) {
898 sbuf_new(&sb, str, sizeof(str), SBUF_FIXEDLEN);
899 sbuf_cat(&sb, path_str);
900 sbuf_printf(&sb, " %#jx:%04x:", tag_num, i);
901 for (j = 0; j < 16 && i < len; i++, j++) {
902 if (j == 8)
903 sbuf_cat(&sb, " ");
904 sbuf_printf(&sb, " %02x", ctl_kern_data_ptr(io)[i]);
905 }
906 sbuf_cat(&sb, "\n");
907 sbuf_finish(&sb);
908 printf("%s", sbuf_data(&sb));
909 }
910 }
911
912 #else /* _KERNEL */
913
914 void
ctl_io_error_print(union ctl_io * io,struct scsi_inquiry_data * inq_data,FILE * ofile)915 ctl_io_error_print(union ctl_io *io, struct scsi_inquiry_data *inq_data,
916 FILE *ofile)
917 {
918 char str[512];
919
920 fprintf(ofile, "%s", ctl_io_error_string(io, inq_data, str,
921 sizeof(str)));
922 }
923
924 #endif /* _KERNEL */
925
926 /*
927 * vim: ts=8
928 */
929