4 * Copyright (c) 2002 Nate Lawson.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification, immediately at the beginning of the file.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $FreeBSD: src/share/examples/scsi_target/scsi_cmds.c,v 1.2.2.1 2003/02/18 22:07:10 njl Exp $
29 * $DragonFly: src/share/examples/scsi_target/scsi_cmds.c,v 1.2 2003/06/17 04:36:57 dillon Exp $
39 #include <sys/types.h>
42 #include <cam/cam_ccb.h>
43 #include <cam/scsi/scsi_all.h>
44 #include <cam/scsi/scsi_targetio.h>
45 #include "scsi_target.h"
47 typedef int targ_start_func(struct ccb_accept_tio
*, struct ccb_scsiio
*);
48 typedef void targ_done_func(struct ccb_accept_tio
*, struct ccb_scsiio
*,
51 struct targ_cdb_handlers
{
53 targ_start_func
*start
;
55 #define ILLEGAL_CDB 0xFF
58 static targ_start_func tcmd_inquiry
;
59 static targ_start_func tcmd_req_sense
;
60 static targ_start_func tcmd_rd_cap
;
61 static targ_start_func tcmd_rdwr
;
62 static targ_start_func tcmd_rdwr_decode
;
63 static targ_done_func tcmd_rdwr_done
;
64 static targ_start_func tcmd_null_ok
;
65 static targ_start_func tcmd_illegal_req
;
66 static int start_io(struct ccb_accept_tio
*atio
,
67 struct ccb_scsiio
*ctio
, int dir
);
68 static int init_inquiry(u_int16_t req_flags
, u_int16_t sim_flags
);
69 static struct initiator_state
*
70 tcmd_get_istate(u_int init_id
);
71 static void cdb_debug(u_int8_t
*cdb
, const char *msg
, ...);
73 static struct targ_cdb_handlers cdb_handlers
[] = {
74 { READ_10
, tcmd_rdwr
, tcmd_rdwr_done
},
75 { WRITE_10
, tcmd_rdwr
, tcmd_rdwr_done
},
76 { READ_6
, tcmd_rdwr
, tcmd_rdwr_done
},
77 { WRITE_6
, tcmd_rdwr
, tcmd_rdwr_done
},
78 { INQUIRY
, tcmd_inquiry
, NULL
},
79 { REQUEST_SENSE
, tcmd_req_sense
, NULL
},
80 { READ_CAPACITY
, tcmd_rd_cap
, NULL
},
81 { TEST_UNIT_READY
, tcmd_null_ok
, NULL
},
82 { START_STOP_UNIT
, tcmd_null_ok
, NULL
},
83 { SYNCHRONIZE_CACHE
, tcmd_null_ok
, NULL
},
84 { MODE_SENSE_6
, tcmd_illegal_req
, NULL
},
85 { MODE_SELECT_6
, tcmd_illegal_req
, NULL
},
86 { ILLEGAL_CDB
, NULL
, NULL
}
89 static struct scsi_inquiry_data inq_data
;
90 static struct initiator_state istates
[MAX_INITIATORS
];
92 extern u_int32_t volume_size
;
93 extern size_t sector_size
;
94 extern size_t buf_size
;
97 tcmd_init(u_int16_t req_inq_flags
, u_int16_t sim_inq_flags
)
99 struct initiator_state
*istate
;
102 /* Initialize our inquiry data */
103 ret
= init_inquiry(req_inq_flags
, sim_inq_flags
);
107 /* We start out life with a UA to indicate power-on/reset. */
108 for (i
= 0; i
< MAX_INITIATORS
; i
++) {
109 istate
= tcmd_get_istate(i
);
110 bzero(istate
, sizeof(*istate
));
111 istate
->pending_ua
= UA_POWER_ON
;
117 /* Caller allocates CTIO, sets its init_id
118 return 0 if done, 1 if more processing needed
119 on 0, caller sets SEND_STATUS */
121 tcmd_handle(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
, io_ops event
)
123 static struct targ_cdb_handlers
*last_cmd
;
124 struct initiator_state
*istate
;
125 struct atio_descr
*a_descr
;
129 warnx("tcmd_handle atio %p ctio %p atioflags %#x", atio
, ctio
,
133 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
135 /* Do a full lookup if one-behind cache failed */
136 if (last_cmd
== NULL
|| last_cmd
->cmd
!= a_descr
->cdb
[0]) {
137 struct targ_cdb_handlers
*h
;
139 for (h
= cdb_handlers
; h
->cmd
!= ILLEGAL_CDB
; h
++) {
140 if (a_descr
->cdb
[0] == h
->cmd
)
145 if (last_cmd
->cmd
== ILLEGAL_CDB
) {
146 if (event
!= ATIO_WORK
) {
147 warnx("no done func for %#x???", a_descr
->cdb
[0]);
150 /* Not found, return illegal request */
151 warnx("cdb %#x not handled", a_descr
->cdb
[0]);
152 tcmd_illegal_req(atio
, ctio
);
153 send_ccb((union ccb
*)ctio
, /*priority*/1);
157 /* call completion and exit */
158 if (event
!= ATIO_WORK
) {
159 if (last_cmd
->done
!= NULL
)
160 last_cmd
->done(atio
, ctio
, event
);
162 free_ccb((union ccb
*)ctio
);
166 istate
= tcmd_get_istate(ctio
->init_id
);
167 if (istate
== NULL
) {
168 tcmd_illegal_req(atio
, ctio
);
169 send_ccb((union ccb
*)ctio
, /*priority*/1);
173 if (istate
->pending_ca
== 0 && istate
->pending_ua
!= 0 &&
174 a_descr
->cdb
[0] != INQUIRY
) {
175 tcmd_sense(ctio
->init_id
, ctio
, SSD_KEY_UNIT_ATTENTION
,
176 0x29, istate
->pending_ua
== UA_POWER_ON
? 1 : 2);
177 istate
->pending_ca
= CA_UNIT_ATTN
;
179 cdb_debug(a_descr
->cdb
, "UA active for %u: ",
182 send_ccb((union ccb
*)ctio
, /*priority*/1);
186 /* Store current CA and UA for later */
187 istate
->orig_ua
= istate
->pending_ua
;
188 istate
->orig_ca
= istate
->pending_ca
;
191 * As per SAM2, any command that occurs
192 * after a CA is reported, clears the CA. We must
193 * also clear the UA condition, if any, that caused
194 * the CA to occur assuming the UA is not for a
195 * persistent condition.
197 istate
->pending_ca
= CA_NONE
;
198 if (istate
->orig_ca
== CA_UNIT_ATTN
)
199 istate
->pending_ua
= UA_NONE
;
201 /* If we have a valid handler, call start or completion function */
202 if (last_cmd
->cmd
!= ILLEGAL_CDB
) {
203 ret
= last_cmd
->start(atio
, ctio
);
205 if (last_cmd
->start
!= tcmd_rdwr
) {
206 a_descr
->init_req
+= ctio
->dxfer_len
;
207 send_ccb((union ccb
*)ctio
, /*priority*/1);
214 static struct initiator_state
*
215 tcmd_get_istate(u_int init_id
)
217 if (init_id
>= MAX_INITIATORS
) {
218 warnx("illegal init_id %d, max %d", init_id
, MAX_INITIATORS
- 1);
221 return (&istates
[init_id
]);
226 tcmd_sense(u_int init_id
, struct ccb_scsiio
*ctio
, u_int8_t flags
,
227 u_int8_t asc
, u_int8_t ascq
)
229 struct initiator_state
*istate
;
230 struct scsi_sense_data
*sense
;
232 /* Set our initiator's istate */
233 istate
= tcmd_get_istate(init_id
);
236 istate
->pending_ca
|= CA_CMD_SENSE
; /* XXX set instead of or? */
237 sense
= &istate
->sense_data
;
238 bzero(sense
, sizeof(*sense
));
239 sense
->error_code
= SSD_CURRENT_ERROR
;
240 sense
->flags
= flags
;
241 sense
->add_sense_code
= asc
;
242 sense
->add_sense_code_qual
= ascq
;
244 offsetof(struct scsi_sense_data
, sense_key_spec
[2]) -
245 offsetof(struct scsi_sense_data
, extra_len
);
247 /* Fill out the supplied CTIO */
250 bcopy(sense, &ctio->sense_data, sizeof(*sense));
251 ctio->sense_len = sizeof(*sense); XXX
253 ctio
->ccb_h
.flags
&= ~CAM_DIR_MASK
;
254 ctio
->ccb_h
.flags
|= CAM_DIR_NONE
| /* CAM_SEND_SENSE | */
257 ctio
->scsi_status
= SCSI_STATUS_CHECK_COND
;
262 tcmd_ua(u_int init_id
, ua_types new_ua
)
264 struct initiator_state
*istate
;
267 if (init_id
== CAM_TARGET_WILDCARD
) {
269 end
= MAX_INITIATORS
- 1;
271 start
= end
= init_id
;
274 for (; start
<= end
; start
++) {
275 istate
= tcmd_get_istate(start
);
278 istate
->pending_ua
= new_ua
;
283 tcmd_inquiry(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
285 struct scsi_inquiry
*inq
;
286 struct atio_descr
*a_descr
;
287 struct initiator_state
*istate
;
288 struct scsi_sense_data
*sense
;
290 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
291 inq
= (struct scsi_inquiry
*)a_descr
->cdb
;
294 cdb_debug(a_descr
->cdb
, "INQUIRY from %u: ", atio
->init_id
);
296 * Validate the command. We don't support any VPD pages, so
297 * complain if EVPD or CMDDT is set.
299 istate
= tcmd_get_istate(ctio
->init_id
);
300 sense
= &istate
->sense_data
;
301 if ((inq
->byte2
& SI_EVPD
) != 0) {
302 tcmd_illegal_req(atio
, ctio
);
303 sense
->sense_key_spec
[0] = SSD_SCS_VALID
| SSD_FIELDPTR_CMD
|
304 SSD_BITPTR_VALID
| /*bit value*/1;
305 sense
->sense_key_spec
[1] = 0;
306 sense
->sense_key_spec
[2] =
307 offsetof(struct scsi_inquiry
, byte2
);
308 } else if (inq
->page_code
!= 0) {
309 tcmd_illegal_req(atio
, ctio
);
310 sense
->sense_key_spec
[0] = SSD_SCS_VALID
| SSD_FIELDPTR_CMD
;
311 sense
->sense_key_spec
[1] = 0;
312 sense
->sense_key_spec
[2] =
313 offsetof(struct scsi_inquiry
, page_code
);
315 bcopy(&inq_data
, ctio
->data_ptr
, sizeof(inq_data
));
316 ctio
->dxfer_len
= inq_data
.additional_length
+ 4;
317 ctio
->dxfer_len
= min(ctio
->dxfer_len
,
318 SCSI_CDB6_LEN(inq
->length
));
319 ctio
->ccb_h
.flags
|= CAM_DIR_IN
| CAM_SEND_STATUS
;
320 ctio
->scsi_status
= SCSI_STATUS_OK
;
325 /* Initialize the inquiry response structure with the requested flags */
327 init_inquiry(u_int16_t req_flags
, u_int16_t sim_flags
)
329 struct scsi_inquiry_data
*inq
;
332 bzero(inq
, sizeof(*inq
));
333 inq
->device
= T_DIRECT
| (SID_QUAL_LU_CONNECTED
<< 5);
334 inq
->version
= SCSI_REV_3
; /* was 2 */
337 * XXX cpi.hba_inquiry doesn't support Addr16 so we give the
338 * user what they want if they ask for it.
340 if ((req_flags
& SID_Addr16
) != 0) {
341 sim_flags
|= SID_Addr16
;
342 warnx("Not sure SIM supports Addr16 but enabling it anyway");
345 /* Advertise only what the SIM can actually support */
346 req_flags
&= sim_flags
;
347 scsi_ulto2b(req_flags
, &inq
->reserved
[1]);
349 inq
->response_format
= 2; /* SCSI2 Inquiry Format */
350 inq
->additional_length
= SHORT_INQUIRY_LENGTH
-
351 offsetof(struct scsi_inquiry_data
, additional_length
);
352 bcopy("FreeBSD ", inq
->vendor
, SID_VENDOR_SIZE
);
353 bcopy("Emulated Disk ", inq
->product
, SID_PRODUCT_SIZE
);
354 bcopy("0.1 ", inq
->revision
, SID_REVISION_SIZE
);
359 tcmd_req_sense(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
361 struct scsi_request_sense
*rsense
;
362 struct scsi_sense_data
*sense
;
363 struct initiator_state
*istate
;
365 struct atio_descr
*a_descr
;
367 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
368 rsense
= (struct scsi_request_sense
*)a_descr
->cdb
;
370 istate
= tcmd_get_istate(ctio
->init_id
);
371 sense
= &istate
->sense_data
;
374 cdb_debug(a_descr
->cdb
, "REQ SENSE from %u: ", atio
->init_id
);
375 warnx("Sending sense: %#x %#x %#x", sense
->flags
,
376 sense
->add_sense_code
, sense
->add_sense_code_qual
);
379 if (istate
->orig_ca
== 0) {
380 tcmd_sense(ctio
->init_id
, NULL
, SSD_KEY_NO_SENSE
, 0, 0);
381 warnx("REQUEST SENSE from %u but no pending CA!",
385 bcopy(sense
, ctio
->data_ptr
, sizeof(struct scsi_sense_data
));
386 dlen
= offsetof(struct scsi_sense_data
, extra_len
) +
387 sense
->extra_len
+ 1;
388 ctio
->dxfer_len
= min(dlen
, SCSI_CDB6_LEN(rsense
->length
));
389 ctio
->ccb_h
.flags
|= CAM_DIR_IN
| CAM_SEND_STATUS
;
390 ctio
->scsi_status
= SCSI_STATUS_OK
;
395 tcmd_rd_cap(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
397 struct scsi_read_capacity_data
*srp
;
398 struct atio_descr
*a_descr
;
400 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
401 srp
= (struct scsi_read_capacity_data
*)ctio
->data_ptr
;
404 cdb_debug(a_descr
->cdb
, "READ CAP from %u (%u, %u): ",
405 atio
->init_id
, volume_size
- 1, sector_size
);
408 bzero(srp
, sizeof(*srp
));
409 scsi_ulto4b(volume_size
- 1, srp
->addr
);
410 scsi_ulto4b(sector_size
, srp
->length
);
412 ctio
->dxfer_len
= sizeof(*srp
);
413 ctio
->ccb_h
.flags
|= CAM_DIR_IN
| CAM_SEND_STATUS
;
414 ctio
->scsi_status
= SCSI_STATUS_OK
;
419 tcmd_rdwr(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
421 struct atio_descr
*a_descr
;
422 struct ctio_descr
*c_descr
;
425 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
426 c_descr
= (struct ctio_descr
*)ctio
->ccb_h
.targ_descr
;
428 /* Command needs to be decoded */
429 if ((a_descr
->flags
& CAM_DIR_MASK
) == CAM_DIR_RESV
) {
431 warnx("Calling rdwr_decode");
432 ret
= tcmd_rdwr_decode(atio
, ctio
);
434 send_ccb((union ccb
*)ctio
, /*priority*/1);
438 ctio
->ccb_h
.flags
|= a_descr
->flags
;
440 /* Call appropriate work function */
441 if ((a_descr
->flags
& CAM_DIR_IN
) != 0) {
442 ret
= start_io(atio
, ctio
, CAM_DIR_IN
);
444 warnx("Starting DIR_IN @%lld:%u", c_descr
->offset
,
447 ret
= start_io(atio
, ctio
, CAM_DIR_OUT
);
449 warnx("Starting DIR_OUT @%lld:%u", c_descr
->offset
,
457 tcmd_rdwr_decode(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
459 u_int32_t blkno
, count
;
460 struct atio_descr
*a_descr
;
463 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
466 cdb_debug(cdb
, "R/W from %u: ", atio
->init_id
);
468 if (cdb
[0] == READ_6
|| cdb
[0] == WRITE_6
) {
469 struct scsi_rw_6
*rw_6
= (struct scsi_rw_6
*)cdb
;
470 blkno
= scsi_3btoul(rw_6
->addr
);
471 count
= rw_6
->length
;
473 struct scsi_rw_10
*rw_10
= (struct scsi_rw_10
*)cdb
;
474 blkno
= scsi_4btoul(rw_10
->addr
);
475 count
= scsi_2btoul(rw_10
->length
);
477 if (blkno
+ count
> volume_size
) {
478 warnx("Attempt to access past end of volume");
479 tcmd_sense(ctio
->init_id
, ctio
,
480 SSD_KEY_ILLEGAL_REQUEST
, 0x21, 0);
484 /* Get an (overall) data length and set direction */
485 a_descr
->base_off
= ((off_t
)blkno
) * sector_size
;
486 a_descr
->total_len
= count
* sector_size
;
487 if (a_descr
->total_len
== 0) {
489 warnx("r/w 0 blocks @ blkno %u", blkno
);
490 tcmd_null_ok(atio
, ctio
);
492 } else if (cdb
[0] == WRITE_6
|| cdb
[0] == WRITE_10
) {
493 a_descr
->flags
|= CAM_DIR_OUT
;
495 warnx("write %u blocks @ blkno %u", count
, blkno
);
497 a_descr
->flags
|= CAM_DIR_IN
;
499 warnx("read %u blocks @ blkno %u", count
, blkno
);
505 start_io(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
, int dir
)
507 struct atio_descr
*a_descr
;
508 struct ctio_descr
*c_descr
;
511 /* Set up common structures */
512 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
513 c_descr
= (struct ctio_descr
*)ctio
->ccb_h
.targ_descr
;
515 if (dir
== CAM_DIR_IN
) {
516 c_descr
->offset
= a_descr
->base_off
+ a_descr
->targ_req
;
517 ctio
->dxfer_len
= a_descr
->total_len
- a_descr
->targ_req
;
519 c_descr
->offset
= a_descr
->base_off
+ a_descr
->init_req
;
520 ctio
->dxfer_len
= a_descr
->total_len
- a_descr
->init_req
;
522 ctio
->dxfer_len
= min(ctio
->dxfer_len
, buf_size
);
523 assert(ctio
->dxfer_len
>= 0);
525 c_descr
->aiocb
.aio_offset
= c_descr
->offset
;
526 c_descr
->aiocb
.aio_nbytes
= ctio
->dxfer_len
;
528 /* If DIR_IN, start read from target, otherwise begin CTIO xfer. */
530 if (dir
== CAM_DIR_IN
) {
531 if (aio_read(&c_descr
->aiocb
) < 0)
532 err(1, "aio_read"); /* XXX */
533 a_descr
->targ_req
+= ctio
->dxfer_len
;
534 if (a_descr
->targ_req
== a_descr
->total_len
) {
535 ctio
->ccb_h
.flags
|= CAM_SEND_STATUS
;
536 ctio
->scsi_status
= SCSI_STATUS_OK
;
540 if (a_descr
->targ_ack
== a_descr
->total_len
)
541 tcmd_null_ok(atio
, ctio
);
542 a_descr
->init_req
+= ctio
->dxfer_len
;
543 if (a_descr
->init_req
== a_descr
->total_len
&&
544 ctio
->dxfer_len
> 0) {
546 * If data phase done, remove atio from workq.
547 * The completion handler will call work_atio to
548 * send the final status.
552 send_ccb((union ccb
*)ctio
, /*priority*/1);
559 tcmd_rdwr_done(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
,
562 struct atio_descr
*a_descr
;
563 struct ctio_descr
*c_descr
;
565 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
566 c_descr
= (struct ctio_descr
*)ctio
->ccb_h
.targ_descr
;
570 if (aio_return(&c_descr
->aiocb
) < 0) {
571 warn("aio_return error");
573 tcmd_sense(ctio
->init_id
, ctio
,
574 SSD_KEY_MEDIUM_ERROR
, 0, 0);
575 send_ccb((union ccb
*)ctio
, /*priority*/1);
578 a_descr
->targ_ack
+= ctio
->dxfer_len
;
579 if ((a_descr
->flags
& CAM_DIR_IN
) != 0) {
581 warnx("sending CTIO for AIO read");
582 a_descr
->init_req
+= ctio
->dxfer_len
;
583 send_ccb((union ccb
*)ctio
, /*priority*/1);
585 /* Use work function to send final status */
586 if (a_descr
->init_req
== a_descr
->total_len
)
589 warnx("AIO done freeing CTIO");
590 free_ccb((union ccb
*)ctio
);
594 if (ctio
->ccb_h
.status
!= CAM_REQ_CMP
) {
596 errx(1, "CTIO failed, status %#x", ctio
->ccb_h
.status
);
598 a_descr
->init_ack
+= ctio
->dxfer_len
;
599 if ((a_descr
->flags
& CAM_DIR_MASK
) == CAM_DIR_OUT
&&
600 ctio
->dxfer_len
> 0) {
602 warnx("sending AIO for CTIO write");
603 a_descr
->targ_req
+= ctio
->dxfer_len
;
604 if (aio_write(&c_descr
->aiocb
) < 0)
605 err(1, "aio_write"); /* XXX */
608 warnx("CTIO done freeing CTIO");
609 free_ccb((union ccb
*)ctio
);
613 warnx("Unknown completion code %d", event
);
619 /* Simple ok message used by TUR, SYNC_CACHE, etc. */
621 tcmd_null_ok(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
624 struct atio_descr
*a_descr
;
626 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
627 cdb_debug(a_descr
->cdb
, "Sending null ok to %u : ", atio
->init_id
);
631 ctio
->ccb_h
.flags
&= ~CAM_DIR_MASK
;
632 ctio
->ccb_h
.flags
|= CAM_DIR_NONE
| CAM_SEND_STATUS
;
633 ctio
->scsi_status
= SCSI_STATUS_OK
;
637 /* Simple illegal request message used by MODE SENSE, etc. */
639 tcmd_illegal_req(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
642 struct atio_descr
*a_descr
;
644 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
645 cdb_debug(a_descr
->cdb
, "Sending ill req to %u: ", atio
->init_id
);
648 tcmd_sense(atio
->init_id
, ctio
, SSD_KEY_ILLEGAL_REQUEST
,
649 /*asc*/0x24, /*ascq*/0);
654 cdb_debug(u_int8_t
*cdb
, const char *msg
, ...)
661 vsnprintf(msg_buf
, sizeof(msg_buf
), msg
, ap
);
663 len
= strlen(msg_buf
);
664 scsi_cdb_string(cdb
, msg_buf
+ len
, sizeof(msg_buf
) - len
);
665 warnx("%s", msg_buf
);