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