]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/cam/ctl/ctl_util.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.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_LUN_RESET, "LUN Reset"},
88         {CTL_TASK_TARGET_RESET, "Target Reset"},
89         {CTL_TASK_BUS_RESET, "Bus Reset"},
90         {CTL_TASK_PORT_LOGIN, "Port Login"},
91         {CTL_TASK_PORT_LOGOUT, "Port Logout"}
92 };
93
94 void
95 ctl_scsi_tur(union ctl_io *io, ctl_tag_type tag_type, uint8_t control)
96 {
97         struct ctl_scsiio *ctsio;
98         struct scsi_test_unit_ready *cdb;
99
100         ctl_scsi_zero_io(io);
101
102         io->io_hdr.io_type = CTL_IO_SCSI;
103         ctsio = &io->scsiio;
104         cdb = (struct scsi_test_unit_ready *)ctsio->cdb;
105
106         cdb->opcode = TEST_UNIT_READY;
107         cdb->control = control;
108         io->io_hdr.flags = CTL_FLAG_DATA_NONE;
109         ctsio->tag_type = tag_type;
110         ctsio->cdb_len = sizeof(*cdb);
111         ctsio->ext_data_len = 0;
112         ctsio->ext_data_ptr = NULL;
113         ctsio->ext_sg_entries = 0;
114         ctsio->ext_data_filled = 0;
115         ctsio->sense_len = SSD_FULL_SIZE;
116 }
117
118 void
119 ctl_scsi_inquiry(union ctl_io *io, uint8_t *data_ptr, int32_t data_len,
120                  uint8_t byte2, uint8_t page_code, ctl_tag_type tag_type,
121                  uint8_t control)
122 {
123         struct ctl_scsiio *ctsio;
124         struct scsi_inquiry *cdb;
125
126         ctl_scsi_zero_io(io);
127
128         io->io_hdr.io_type = CTL_IO_SCSI;
129         ctsio = &io->scsiio;
130         cdb = (struct scsi_inquiry *)ctsio->cdb;
131
132         cdb->opcode = INQUIRY;
133         cdb->byte2 = byte2;
134         cdb->page_code = page_code;
135         cdb->control = control;
136         scsi_ulto2b(data_len, cdb->length);
137         io->io_hdr.io_type = CTL_IO_SCSI;
138         io->io_hdr.flags = CTL_FLAG_DATA_IN;
139         ctsio->tag_type = tag_type;
140         ctsio->cdb_len = sizeof(*cdb);
141         ctsio->ext_data_len = data_len;
142         ctsio->ext_data_ptr = data_ptr;
143         ctsio->ext_sg_entries = 0;
144         ctsio->ext_data_filled = 0;
145         ctsio->sense_len = SSD_FULL_SIZE;
146 }
147
148 void
149 ctl_scsi_request_sense(union ctl_io *io, uint8_t *data_ptr,
150                        int32_t data_len, uint8_t byte2, ctl_tag_type tag_type,
151                        uint8_t control)
152 {
153         struct ctl_scsiio *ctsio;
154         struct scsi_request_sense *cdb;
155
156         ctl_scsi_zero_io(io);
157
158         io->io_hdr.io_type = CTL_IO_SCSI;
159         ctsio = &io->scsiio;
160         cdb = (struct scsi_request_sense *)ctsio->cdb;
161
162         cdb->opcode = REQUEST_SENSE;
163         cdb->byte2 = byte2;
164         cdb->control = control;
165         cdb->length = data_len;
166         io->io_hdr.io_type = CTL_IO_SCSI;
167         io->io_hdr.flags = CTL_FLAG_DATA_IN;
168         ctsio->tag_type = tag_type;
169         ctsio->cdb_len = sizeof(*cdb);
170         ctsio->ext_data_ptr = data_ptr;
171         ctsio->ext_data_len = data_len;
172         ctsio->ext_sg_entries = 0;
173         ctsio->ext_data_filled = 0;
174         ctsio->sense_len = SSD_FULL_SIZE;
175 }
176
177 void
178 ctl_scsi_report_luns(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
179                      uint8_t select_report, ctl_tag_type tag_type,
180                      uint8_t control)
181 {
182         struct ctl_scsiio *ctsio;
183         struct scsi_report_luns *cdb;
184
185         ctl_scsi_zero_io(io);
186
187         io->io_hdr.io_type = CTL_IO_SCSI;
188         ctsio = &io->scsiio;
189         cdb = (struct scsi_report_luns *)ctsio->cdb;
190
191         cdb->opcode = REPORT_LUNS;
192         cdb->select_report = select_report;
193         scsi_ulto4b(data_len, cdb->length);
194         cdb->control = control;
195         io->io_hdr.io_type = CTL_IO_SCSI;
196         io->io_hdr.flags = CTL_FLAG_DATA_IN;
197         ctsio->tag_type = tag_type;
198         ctsio->cdb_len = sizeof(*cdb);
199         ctsio->ext_data_ptr = data_ptr;
200         ctsio->ext_data_len = data_len;
201         ctsio->ext_sg_entries = 0;
202         ctsio->ext_data_filled = 0;
203         ctsio->sense_len = SSD_FULL_SIZE;
204 }
205
206 void
207 ctl_scsi_read_write_buffer(union ctl_io *io, uint8_t *data_ptr,
208                            uint32_t data_len, int read_buffer, uint8_t mode,
209                            uint8_t buffer_id, uint32_t buffer_offset,
210                            ctl_tag_type tag_type, uint8_t control)
211 {
212         struct ctl_scsiio *ctsio;
213         struct scsi_write_buffer *cdb;
214
215         ctl_scsi_zero_io(io);
216
217         io->io_hdr.io_type = CTL_IO_SCSI;
218         ctsio = &io->scsiio;
219         cdb = (struct scsi_write_buffer *)ctsio->cdb;
220
221         if (read_buffer != 0)
222                 cdb->opcode = READ_BUFFER;
223         else
224                 cdb->opcode = WRITE_BUFFER;
225
226         cdb->byte2 = mode & RWB_MODE;
227         cdb->buffer_id = buffer_id;
228         scsi_ulto3b(buffer_offset, cdb->offset);
229         scsi_ulto3b(data_len, cdb->length);
230         cdb->control = control;
231         io->io_hdr.io_type = CTL_IO_SCSI;
232         if (read_buffer != 0)
233                 io->io_hdr.flags = CTL_FLAG_DATA_IN;
234         else
235                 io->io_hdr.flags = CTL_FLAG_DATA_OUT;
236         ctsio->tag_type = tag_type;
237         ctsio->cdb_len = sizeof(*cdb);
238         ctsio->ext_data_ptr = data_ptr;
239         ctsio->ext_data_len = data_len;
240         ctsio->ext_sg_entries = 0;
241         ctsio->ext_data_filled = 0;
242         ctsio->sense_len = SSD_FULL_SIZE;
243 }
244
245 void
246 ctl_scsi_read_write(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
247                     int read_op, uint8_t byte2, int minimum_cdb_size,
248                     uint64_t lba, uint32_t num_blocks, ctl_tag_type tag_type,
249                     uint8_t control)
250 {
251         struct ctl_scsiio *ctsio;
252
253         ctl_scsi_zero_io(io);
254
255         io->io_hdr.io_type = CTL_IO_SCSI;
256         ctsio = &io->scsiio;
257
258         /*
259          * Pick out the smallest CDB that will hold the user's request.
260          * minimum_cdb_size allows cranking the CDB size up, even for
261          * requests that would not normally need a large CDB.  This can be
262          * useful for testing (e.g. to make sure READ_16 support works without
263          * having an array larger than 2TB) and for compatibility -- e.g.
264          * if your device doesn't support READ_6.  (ATAPI drives don't.)
265          */
266         if ((minimum_cdb_size < 10)
267          && ((lba & 0x1fffff) == lba)
268          && ((num_blocks & 0xff) == num_blocks)
269          && (byte2 == 0)) {
270                 struct scsi_rw_6 *cdb;
271
272                 /*
273                  * Note that according to SBC-2, the target should return 256
274                  * blocks if the transfer length in a READ(6) or WRITE(6) CDB
275                  * is set to 0.  Since it's possible that some targets
276                  * won't do the right thing, we only send a READ(6) or
277                  * WRITE(6) for transfer sizes up to and including 255 blocks.
278                  */
279                 cdb = (struct scsi_rw_6 *)ctsio->cdb;
280
281                 cdb->opcode = (read_op) ? READ_6 : WRITE_6;
282                 scsi_ulto3b(lba, cdb->addr);
283                 cdb->length = num_blocks & 0xff;
284                 cdb->control = control;
285
286                 ctsio->cdb_len = sizeof(*cdb);
287
288         } else if ((minimum_cdb_size < 12)
289                 && ((num_blocks & 0xffff) == num_blocks)
290                 && ((lba & 0xffffffff) == lba)) {
291                 struct scsi_rw_10 *cdb;
292
293                 cdb = (struct scsi_rw_10 *)ctsio->cdb;
294
295                 cdb->opcode = (read_op) ? READ_10 : WRITE_10;
296                 cdb->byte2 = byte2;
297                 scsi_ulto4b(lba, cdb->addr);
298                 cdb->reserved = 0;
299                 scsi_ulto2b(num_blocks, cdb->length);
300                 cdb->control = control;
301
302                 ctsio->cdb_len = sizeof(*cdb);
303         } else if ((minimum_cdb_size < 16)
304                 && ((num_blocks & 0xffffffff) == num_blocks)
305                 && ((lba & 0xffffffff) == lba)) {
306                 struct scsi_rw_12 *cdb;
307
308                 cdb = (struct scsi_rw_12 *)ctsio->cdb;
309
310                 cdb->opcode = (read_op) ? READ_12 : WRITE_12;
311                 cdb->byte2 = byte2;
312                 scsi_ulto4b(lba, cdb->addr);
313                 scsi_ulto4b(num_blocks, cdb->length);
314                 cdb->reserved = 0;
315                 cdb->control = control;
316
317                 ctsio->cdb_len = sizeof(*cdb);
318         } else {
319                 struct scsi_rw_16 *cdb;
320
321                 cdb = (struct scsi_rw_16 *)ctsio->cdb;
322
323                 cdb->opcode = (read_op) ? READ_16 : WRITE_16;
324                 cdb->byte2 = byte2;
325                 scsi_u64to8b(lba, cdb->addr);
326                 scsi_ulto4b(num_blocks, cdb->length);
327                 cdb->reserved = 0;
328                 cdb->control = control;
329
330                 ctsio->cdb_len = sizeof(*cdb);
331         }
332
333         io->io_hdr.io_type = CTL_IO_SCSI;
334         if (read_op != 0)
335                 io->io_hdr.flags = CTL_FLAG_DATA_IN;
336         else
337                 io->io_hdr.flags = CTL_FLAG_DATA_OUT;
338         ctsio->tag_type = tag_type;
339         ctsio->ext_data_ptr = data_ptr;
340         ctsio->ext_data_len = data_len;
341         ctsio->ext_sg_entries = 0;
342         ctsio->ext_data_filled = 0;
343         ctsio->sense_len = SSD_FULL_SIZE;
344 }
345
346 void
347 ctl_scsi_read_capacity(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len,
348                        uint32_t addr, int reladr, int pmi,
349                        ctl_tag_type tag_type, uint8_t control)
350 {
351         struct scsi_read_capacity *cdb;
352
353         ctl_scsi_zero_io(io);
354
355         io->io_hdr.io_type = CTL_IO_SCSI;
356         cdb = (struct scsi_read_capacity *)io->scsiio.cdb;
357
358         cdb->opcode = READ_CAPACITY;
359         if (reladr)
360                 cdb->byte2 = SRC_RELADR;
361         if (pmi)
362                 cdb->pmi = SRC_PMI;
363         scsi_ulto4b(addr, cdb->addr);
364         cdb->control = control;
365         io->io_hdr.io_type = CTL_IO_SCSI;
366         io->io_hdr.flags = CTL_FLAG_DATA_IN;
367         io->scsiio.tag_type = tag_type;
368         io->scsiio.ext_data_ptr = data_ptr;
369         io->scsiio.ext_data_len = data_len;
370         io->scsiio.ext_sg_entries = 0;
371         io->scsiio.ext_data_filled = 0;
372         io->scsiio.sense_len = SSD_FULL_SIZE;
373 }
374
375 void
376 ctl_scsi_read_capacity_16(union ctl_io *io, uint8_t *data_ptr,
377                           uint32_t data_len, uint64_t addr, int reladr,
378                           int pmi, ctl_tag_type tag_type, uint8_t control)
379 {
380         struct scsi_read_capacity_16 *cdb;
381
382         ctl_scsi_zero_io(io);
383
384         io->io_hdr.io_type = CTL_IO_SCSI;
385         cdb = (struct scsi_read_capacity_16 *)io->scsiio.cdb;
386
387         cdb->opcode = SERVICE_ACTION_IN;
388         cdb->service_action = SRC16_SERVICE_ACTION;
389         if (reladr)
390                 cdb->reladr |= SRC16_RELADR;
391         if (pmi)
392                 cdb->reladr |= SRC16_PMI;
393         scsi_u64to8b(addr, cdb->addr);
394         scsi_ulto4b(data_len, cdb->alloc_len);
395         cdb->control = control;
396
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_mode_sense(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len, 
409                     int dbd, int llbaa, uint8_t page_code, uint8_t pc,
410                     uint8_t subpage, int minimum_cdb_size,
411                     ctl_tag_type tag_type, uint8_t control)
412 {
413         ctl_scsi_zero_io(io);
414
415         if ((minimum_cdb_size < 10)
416          && (llbaa == 0)
417          && (data_len < 256)) {
418                 struct scsi_mode_sense_6 *cdb;
419
420                 cdb = (struct scsi_mode_sense_6 *)io->scsiio.cdb;
421
422                 cdb->opcode = MODE_SENSE_6;
423                 if (dbd)
424                         cdb->byte2 |= SMS_DBD;
425                 cdb->page = page_code | pc;
426                 cdb->subpage = subpage;
427                 cdb->length = data_len;
428                 cdb->control = control;
429         } else {
430                 struct scsi_mode_sense_10 *cdb;
431
432                 cdb = (struct scsi_mode_sense_10 *)io->scsiio.cdb;
433
434                 cdb->opcode = MODE_SENSE_10;
435                 if (dbd)
436                         cdb->byte2 |= SMS_DBD;
437                 if (llbaa)
438                         cdb->byte2 |= SMS10_LLBAA;
439                 cdb->page = page_code | pc;
440                 cdb->subpage = subpage;
441                 scsi_ulto2b(data_len, cdb->length);
442                 cdb->control = control;
443         }
444
445         io->io_hdr.io_type = CTL_IO_SCSI;
446         io->io_hdr.flags = CTL_FLAG_DATA_IN;
447         io->scsiio.tag_type = tag_type;
448         io->scsiio.ext_data_ptr = data_ptr;
449         io->scsiio.ext_data_len = data_len;
450         io->scsiio.ext_sg_entries = 0;
451         io->scsiio.ext_data_filled = 0;
452         io->scsiio.sense_len = SSD_FULL_SIZE;
453 }
454
455 void
456 ctl_scsi_start_stop(union ctl_io *io, int start, int load_eject, int immediate,
457                     int power_conditions, int onoffline __unused,
458                     ctl_tag_type tag_type, uint8_t control)
459 {
460         struct scsi_start_stop_unit *cdb;
461
462         cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb;
463
464         ctl_scsi_zero_io(io);
465
466         cdb->opcode = START_STOP_UNIT;
467         if (immediate)
468                 cdb->byte2 |= SSS_IMMED;
469 #ifdef NEEDTOPORT
470         if (onoffline)
471                 cdb->byte2 |= SSS_ONOFFLINE;
472 #endif
473         cdb->how = power_conditions;
474         if (load_eject)
475                 cdb->how |= SSS_LOEJ;
476         if (start)
477                 cdb->how |= SSS_START;
478         cdb->control = control;
479         io->io_hdr.io_type = CTL_IO_SCSI;
480         io->io_hdr.flags = CTL_FLAG_DATA_NONE;
481         io->scsiio.tag_type = tag_type;
482         io->scsiio.ext_data_ptr = NULL;
483         io->scsiio.ext_data_len = 0;
484         io->scsiio.ext_sg_entries = 0;
485         io->scsiio.ext_data_filled = 0;
486         io->scsiio.sense_len = SSD_FULL_SIZE;
487 }
488
489 void
490 ctl_scsi_sync_cache(union ctl_io *io, int immed, int reladr,
491                     int minimum_cdb_size, uint64_t starting_lba,
492                     uint32_t block_count, ctl_tag_type tag_type,
493                     uint8_t control)
494 {
495         ctl_scsi_zero_io(io);
496
497         if ((minimum_cdb_size < 16)
498          && ((block_count & 0xffff) == block_count)
499          && ((starting_lba & 0xffffffff) == starting_lba)) {
500                 struct scsi_sync_cache *cdb;
501
502                 cdb = (struct scsi_sync_cache *)io->scsiio.cdb;
503
504                 cdb->opcode = SYNCHRONIZE_CACHE;
505                 if (reladr)
506                         cdb->byte2 |= SSC_RELADR;
507
508                 if (immed)
509                         cdb->byte2 |= SSC_IMMED;
510
511                 scsi_ulto4b(starting_lba, cdb->begin_lba);
512                 scsi_ulto2b(block_count, cdb->lb_count);
513                 cdb->control = control;
514         } else {
515                 struct scsi_sync_cache_16 *cdb;
516
517                 cdb = (struct scsi_sync_cache_16 *)io->scsiio.cdb;
518
519                 cdb->opcode = SYNCHRONIZE_CACHE_16;
520                 if (reladr)
521                         cdb->byte2 |= SSC_RELADR;
522
523                 if (immed)
524                         cdb->byte2 |= SSC_IMMED;
525
526                 scsi_u64to8b(starting_lba, cdb->begin_lba);
527                 scsi_ulto4b(block_count, cdb->lb_count);
528                 cdb->control = control;
529         }
530         io->io_hdr.io_type = CTL_IO_SCSI;
531         io->io_hdr.flags = CTL_FLAG_DATA_NONE;
532         io->scsiio.tag_type = tag_type;
533         io->scsiio.ext_data_ptr = NULL;
534         io->scsiio.ext_data_len = 0;
535         io->scsiio.ext_sg_entries = 0;
536         io->scsiio.ext_data_filled = 0;
537         io->scsiio.sense_len = SSD_FULL_SIZE;
538 }
539
540 void
541 ctl_scsi_persistent_res_in(union ctl_io *io, uint8_t *data_ptr,
542                            uint32_t data_len, int action,
543                            ctl_tag_type tag_type, uint8_t control)
544 {
545
546         struct scsi_per_res_in *cdb;
547
548         ctl_scsi_zero_io(io);
549
550         cdb = (struct scsi_per_res_in *)io->scsiio.cdb;
551         cdb->opcode = PERSISTENT_RES_IN;
552         cdb->action = action;
553         scsi_ulto2b(data_len, cdb->length);
554         cdb->control = control;
555
556         io->io_hdr.io_type = CTL_IO_SCSI;
557         io->io_hdr.flags = CTL_FLAG_DATA_IN;
558         io->scsiio.tag_type = tag_type;
559         io->scsiio.ext_data_ptr = data_ptr;
560         io->scsiio.ext_data_len = data_len;
561         io->scsiio.ext_sg_entries = 0;
562         io->scsiio.ext_data_filled = 0;
563         io->scsiio.sense_len = SSD_FULL_SIZE;
564 }
565
566 void
567 ctl_scsi_persistent_res_out(union ctl_io *io, uint8_t *data_ptr,
568                             uint32_t data_len, int action, int type,
569                             uint64_t key, uint64_t sa_key,
570                             ctl_tag_type tag_type, uint8_t control)
571 {
572
573         struct scsi_per_res_out *cdb;
574         struct scsi_per_res_out_parms *params;
575
576         ctl_scsi_zero_io(io);
577
578         cdb = (struct scsi_per_res_out *)io->scsiio.cdb;
579         params = (struct scsi_per_res_out_parms *)data_ptr;
580
581         cdb->opcode = PERSISTENT_RES_OUT;
582         if (action == 5)
583             cdb->action = 6;
584         else
585             cdb->action = action;
586         switch(type)
587         {
588             case 0:
589                     cdb->scope_type = 1;
590                         break;
591             case 1:
592                     cdb->scope_type = 3;
593                         break;
594             case 2:
595                     cdb->scope_type = 5;
596                         break;
597             case 3:
598                     cdb->scope_type = 6;
599                         break;
600             case 4:
601                     cdb->scope_type = 7;
602                         break;
603             case 5:
604                     cdb->scope_type = 8;
605                         break;
606         }
607         scsi_ulto4b(data_len, cdb->length);
608         cdb->control = control;
609
610         scsi_u64to8b(key, params->res_key.key);
611         scsi_u64to8b(sa_key, params->serv_act_res_key);
612
613         io->io_hdr.io_type = CTL_IO_SCSI;
614         io->io_hdr.flags = CTL_FLAG_DATA_OUT;
615         io->scsiio.tag_type = tag_type;
616         io->scsiio.ext_data_ptr = data_ptr;
617         io->scsiio.ext_data_len = data_len;
618         io->scsiio.ext_sg_entries = 0;
619         io->scsiio.ext_data_filled = 0;
620         io->scsiio.sense_len = SSD_FULL_SIZE;
621
622 }
623
624 void
625 ctl_scsi_maintenance_in(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len, 
626                         uint8_t action, ctl_tag_type tag_type, uint8_t control)
627 {
628         struct scsi_maintenance_in *cdb;
629
630         ctl_scsi_zero_io(io);
631
632         cdb = (struct scsi_maintenance_in *)io->scsiio.cdb;
633         cdb->opcode = MAINTENANCE_IN;
634         cdb->byte2 = action;
635         scsi_ulto4b(data_len, cdb->length);
636         cdb->control = control;
637
638         io->io_hdr.io_type = CTL_IO_SCSI;
639         io->io_hdr.flags = CTL_FLAG_DATA_IN;
640         io->scsiio.tag_type = tag_type;
641         io->scsiio.ext_data_ptr = data_ptr;
642         io->scsiio.ext_data_len = data_len;
643         io->scsiio.ext_sg_entries = 0;
644         io->scsiio.ext_data_filled = 0;
645         io->scsiio.sense_len = SSD_FULL_SIZE;
646 }
647
648 #ifndef _KERNEL
649 union ctl_io *
650 ctl_scsi_alloc_io(struct ctl_id initid)
651 {
652         union ctl_io *io;
653
654         io = (union ctl_io *)malloc(sizeof(*io));
655         if (io == NULL)
656                 goto bailout;
657
658         io->io_hdr.nexus.initid = initid;
659
660 bailout:
661         return (io);
662 }
663
664 void
665 ctl_scsi_free_io(union ctl_io *io)
666 {
667         free(io);
668 }
669
670 #endif /* !_KERNEL */
671 void
672 ctl_scsi_zero_io(union ctl_io *io)
673 {
674         void *pool_ref;
675
676         if (io == NULL)
677                 return;
678
679         pool_ref = io->io_hdr.pool;
680
681         memset(io, 0, sizeof(*io));
682
683         io->io_hdr.pool = pool_ref;
684 }
685
686 const char *
687 ctl_scsi_task_string(struct ctl_taskio *taskio)
688 {
689         unsigned int i;
690
691         for (i = 0; i < (sizeof(ctl_task_table)/sizeof(ctl_task_table[0]));
692              i++) {
693                 if (taskio->task_action == ctl_task_table[i].task_action) {
694                         return (ctl_task_table[i].description);
695                 }
696         }
697
698         return (NULL);
699 }
700
701 void
702 ctl_io_error_sbuf(union ctl_io *io, struct scsi_inquiry_data *inq_data,
703                   struct sbuf *sb)
704 {
705         struct ctl_status_desc *status_desc;
706         char path_str[64];
707         unsigned int i;
708
709         status_desc = NULL;
710
711         for (i = 0; i < (sizeof(ctl_status_table)/sizeof(ctl_status_table[0]));
712              i++) {
713                 if ((io->io_hdr.status & CTL_STATUS_MASK) ==
714                      ctl_status_table[i].status) {
715                         status_desc = &ctl_status_table[i];
716                         break;
717                 }
718         }
719
720         ctl_scsi_path_string(io, path_str, sizeof(path_str));
721
722         switch (io->io_hdr.io_type) {
723         case CTL_IO_SCSI:
724                 sbuf_cat(sb, path_str);
725
726                 ctl_scsi_command_string(&io->scsiio, NULL, sb);
727
728                 sbuf_printf(sb, "\n");
729
730                 sbuf_printf(sb, "%sTag: 0x%04x, Type: %d\n", path_str,
731                             io->scsiio.tag_num, io->scsiio.tag_type);
732                 break;
733         case CTL_IO_TASK: {
734                 const char *task_desc;
735
736                 sbuf_cat(sb, path_str);
737
738                 task_desc = ctl_scsi_task_string(&io->taskio);
739
740                 if (task_desc == NULL)
741                         sbuf_printf(sb, "Unknown Task Action %d (%#x)",
742                                     io->taskio.task_action,
743                                     io->taskio.task_action);
744                 else
745                         sbuf_printf(sb, "Task Action: %s", task_desc);
746
747                 sbuf_printf(sb, "\n");
748
749                 switch (io->taskio.task_action) {
750                 case CTL_TASK_ABORT_TASK:
751                 case CTL_TASK_ABORT_TASK_SET:
752                 case CTL_TASK_CLEAR_TASK_SET:
753                         sbuf_printf(sb, "%sTag: 0x%04x, Type: %d\n", path_str,
754                                     io->taskio.tag_num,
755                                     io->taskio.tag_type);
756                         break;
757                 default:
758                         break;
759                 }
760                 break;
761         }
762         default:
763                 break;
764         }
765
766         sbuf_cat(sb, path_str);
767         if (status_desc == NULL)
768                 sbuf_printf(sb, "CTL Status: Unknown status %#x\n",
769                             io->io_hdr.status);
770         else
771                 sbuf_printf(sb, "CTL Status: %s\n", status_desc->description);
772
773         if ((io->io_hdr.io_type == CTL_IO_SCSI)
774          && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SCSI_ERROR)) {
775                 sbuf_cat(sb, path_str);
776                 sbuf_printf(sb, "SCSI Status: %s\n",
777                             ctl_scsi_status_string(&io->scsiio));
778
779                 if (io->scsiio.scsi_status == SCSI_STATUS_CHECK_COND)
780                         ctl_scsi_sense_sbuf(&io->scsiio, inq_data,
781                                             sb, SSS_FLAG_NONE);
782         }
783 }
784
785 char *
786 ctl_io_error_string(union ctl_io *io, struct scsi_inquiry_data *inq_data,
787                     char *str, int str_len)
788 {
789         struct sbuf sb;
790
791         sbuf_new(&sb, str, str_len, SBUF_FIXEDLEN);
792
793         ctl_io_error_sbuf(io, inq_data, &sb);
794
795         sbuf_finish(&sb);
796
797         return (sbuf_data(&sb));
798 }
799
800 #ifdef _KERNEL
801
802 void
803 ctl_io_error_print(union ctl_io *io, struct scsi_inquiry_data *inq_data)
804 {
805         char str[512];
806 #ifdef NEEDTOPORT
807         char *message;
808         char *line;
809
810         message = io_error_string(io, inq_data, str, sizeof(str));
811
812         for (line = strsep(&message, "\n"); line != NULL;
813              line = strsep(&message, "\n")) {
814                 csevent_log(CSC_CTL | CSC_SHELF_SW | CTL_ERROR_REPORT,
815                             csevent_LogType_Trace,
816                             csevent_Severity_Information,
817                             csevent_AlertLevel_Green,
818                             csevent_FRU_Firmware,
819                             csevent_FRU_Unknown, "%s", line);
820         }
821 #else
822         printf("%s", ctl_io_error_string(io, inq_data, str, sizeof(str)));
823 #endif
824
825 }
826
827 #else /* _KERNEL */
828
829 void
830 ctl_io_error_print(union ctl_io *io, struct scsi_inquiry_data *inq_data,
831                    FILE *ofile)
832 {
833         char str[512];
834
835         fprintf(ofile, "%s", ctl_io_error_string(io, inq_data, str,
836                 sizeof(str)));
837 }
838
839 #endif /* _KERNEL */
840
841 /*
842  * vim: ts=8
843  */