]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/cam/ctl/ctl_util.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / cam / ctl / ctl_util.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
697 ctl_scsi_free_io(union ctl_io *io)
698 {
699         free(io);
700 }
701
702 #endif /* !_KERNEL */
703 void
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 *
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
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
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 *
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 *
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
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
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
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
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  */