1 /*
2  * SCSI Disk Emulator
3  *
4  * Copyright (c) 2002 Nate Lawson.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions, and the following disclaimer,
12  *    without modification, 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.
15  *
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
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 #include <stdio.h>
32 #include <stddef.h>
33 #include <stdarg.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <err.h>
37 #include <aio.h>
38 #include <assert.h>
39 #include <sys/types.h>
40 
41 #include <cam/cam.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"
46 
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 *,
49 			      io_ops);
50 
51 struct targ_cdb_handlers {
52 	u_int8_t	  cmd;
53 	targ_start_func  *start;
54 	targ_done_func	 *done;
55 #define ILLEGAL_CDB	  0xFF
56 };
57 
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, ...);
72 
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 }
87 };
88 
89 static struct scsi_inquiry_data inq_data;
90 static struct initiator_state istates[MAX_INITIATORS];
91 extern int		debug;
92 extern u_int32_t	volume_size;
93 extern size_t		sector_size;
94 extern size_t		buf_size;
95 
96 cam_status
97 tcmd_init(u_int16_t req_inq_flags, u_int16_t sim_inq_flags)
98 {
99 	struct initiator_state *istate;
100 	int i, ret;
101 
102 	/* Initialize our inquiry data */
103 	ret = init_inquiry(req_inq_flags, sim_inq_flags);
104 	if (ret != 0)
105         	return (ret);
106 
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;
112 	}
113 
114 	return (0);
115 }
116 
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 */
120 int
121 tcmd_handle(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio, io_ops event)
122 {
123 	static struct targ_cdb_handlers *last_cmd;
124 	struct initiator_state *istate;
125 	struct atio_descr *a_descr;
126 	int ret;
127 
128 	warnx("tcmd_handle atio %p ctio %p atioflags %#x", atio, ctio,
129 		atio->ccb_h.flags);
130 	ret = 0;
131 	a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
132 
133 	/* Do a full lookup if one-behind cache failed */
134 	if (last_cmd == NULL || last_cmd->cmd != a_descr->cdb[0]) {
135 		struct targ_cdb_handlers *h;
136 
137 		for (h = cdb_handlers; h->cmd != ILLEGAL_CDB; h++) {
138 			if (a_descr->cdb[0] == h->cmd)
139 				break;
140 		}
141 		last_cmd = h;
142 	}
143 	if (last_cmd->cmd == ILLEGAL_CDB) {
144 		if (event != ATIO_WORK) {
145 			warnx("no done func for %#x???", a_descr->cdb[0]);
146 			abort();
147 		}
148 		/* Not found, return illegal request */
149 		warnx("cdb %#x not handled", a_descr->cdb[0]);
150 		tcmd_illegal_req(atio, ctio);
151 		send_ccb((union ccb *)ctio, /*priority*/1);
152 		return (0);
153 	}
154 
155 	/* call completion and exit */
156 	if (event != ATIO_WORK) {
157 		if (last_cmd->done != NULL)
158 			last_cmd->done(atio, ctio, event);
159 		else
160 			free_ccb((union ccb *)ctio);
161 		return (1);
162 	}
163 
164 	istate = tcmd_get_istate(ctio->init_id);
165 	if (istate == NULL) {
166 		tcmd_illegal_req(atio, ctio);
167 		send_ccb((union ccb *)ctio, /*priority*/1);
168 		return (0);
169 	}
170 
171 	if (istate->pending_ca == 0 && istate->pending_ua != 0 &&
172 	    a_descr->cdb[0] != INQUIRY) {
173 		tcmd_sense(ctio->init_id, ctio, SSD_KEY_UNIT_ATTENTION,
174 			   0x29, istate->pending_ua == UA_POWER_ON ? 1 : 2);
175 		istate->pending_ca = CA_UNIT_ATTN;
176 		if (debug) {
177 			cdb_debug(a_descr->cdb, "UA active for %u: ",
178 				  atio->init_id);
179 		}
180 		send_ccb((union ccb *)ctio, /*priority*/1);
181 		return (0);
182 	}
183 
184 	/* Store current CA and UA for later */
185 	istate->orig_ua = istate->pending_ua;
186 	istate->orig_ca = istate->pending_ca;
187 
188 	/*
189 	 * As per SAM2, any command that occurs
190 	 * after a CA is reported, clears the CA.  We must
191 	 * also clear the UA condition, if any, that caused
192 	 * the CA to occur assuming the UA is not for a
193 	 * persistent condition.
194 	 */
195 	istate->pending_ca = CA_NONE;
196 	if (istate->orig_ca == CA_UNIT_ATTN)
197 		istate->pending_ua = UA_NONE;
198 
199 	/* If we have a valid handler, call start or completion function */
200 	if (last_cmd->cmd != ILLEGAL_CDB) {
201 		ret = last_cmd->start(atio, ctio);
202 		/* XXX hack */
203 		if (last_cmd->start != tcmd_rdwr) {
204 			a_descr->init_req += ctio->dxfer_len;
205 			send_ccb((union ccb *)ctio, /*priority*/1);
206 		}
207 	}
208 
209 	return (ret);
210 }
211 
212 static struct initiator_state *
213 tcmd_get_istate(u_int init_id)
214 {
215 	if (init_id >= MAX_INITIATORS) {
216 		warnx("illegal init_id %d, max %d", init_id, MAX_INITIATORS - 1);
217 		return (NULL);
218 	} else {
219 		return (&istates[init_id]);
220 	}
221 }
222 
223 void
224 tcmd_sense(u_int init_id, struct ccb_scsiio *ctio, u_int8_t flags,
225 	       u_int8_t asc, u_int8_t ascq)
226 {
227 	struct initiator_state *istate;
228 	struct scsi_sense_data *sense;
229 
230 	/* Set our initiator's istate */
231 	istate = tcmd_get_istate(init_id);
232 	if (istate == NULL)
233 		return;
234 	istate->pending_ca |= CA_CMD_SENSE; /* XXX set instead of or? */
235 	sense = &istate->sense_data;
236 	bzero(sense, sizeof(*sense));
237 	sense->error_code = SSD_CURRENT_ERROR;
238 	sense->flags = flags;
239 	sense->add_sense_code = asc;
240 	sense->add_sense_code_qual = ascq;
241 	sense->extra_len =
242 		offsetof(struct scsi_sense_data, sense_key_spec[2]) -
243 		offsetof(struct scsi_sense_data, extra_len);
244 
245 	/* Fill out the supplied CTIO */
246 	if (ctio != NULL) {
247 		/* No autosense yet
248 		bcopy(sense, &ctio->sense_data, sizeof(*sense));
249 		ctio->sense_len = sizeof(*sense);  XXX
250 		*/
251 		ctio->ccb_h.flags &= ~CAM_DIR_MASK;
252 		ctio->ccb_h.flags |= CAM_DIR_NONE | /* CAM_SEND_SENSE | */
253 				     CAM_SEND_STATUS;
254 		ctio->dxfer_len = 0;
255 		ctio->scsi_status = SCSI_STATUS_CHECK_COND;
256 	}
257 }
258 
259 void
260 tcmd_ua(u_int init_id, ua_types new_ua)
261 {
262 	struct initiator_state *istate;
263 	u_int start, end;
264 
265 	if (init_id == CAM_TARGET_WILDCARD) {
266 		start = 0;
267 		end = MAX_INITIATORS - 1;
268 	} else {
269 		start = end = init_id;
270 	}
271 
272 	for (; start <= end; start++) {
273 		istate = tcmd_get_istate(start);
274 		if (istate == NULL)
275 			break;
276 		istate->pending_ua = new_ua;
277 	}
278 }
279 
280 static int
281 tcmd_inquiry(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
282 {
283 	struct scsi_inquiry *inq;
284 	struct atio_descr *a_descr;
285 	struct initiator_state *istate;
286 	struct scsi_sense_data *sense;
287 
288 	a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
289 	inq = (struct scsi_inquiry *)a_descr->cdb;
290 
291 	if (debug)
292 		cdb_debug(a_descr->cdb, "INQUIRY from %u: ", atio->init_id);
293 	/*
294 	 * Validate the command.  We don't support any VPD pages, so
295 	 * complain if EVPD or CMDDT is set.
296 	 */
297 	istate = tcmd_get_istate(ctio->init_id);
298 	sense = &istate->sense_data;
299 	if ((inq->byte2 & SI_EVPD) != 0) {
300 		tcmd_illegal_req(atio, ctio);
301 		sense->sense_key_spec[0] = SSD_SCS_VALID | SSD_FIELDPTR_CMD |
302 			SSD_BITPTR_VALID | /*bit value*/1;
303 		sense->sense_key_spec[1] = 0;
304 		sense->sense_key_spec[2] =
305 			offsetof(struct scsi_inquiry, byte2);
306 	} else if (inq->page_code != 0) {
307 		tcmd_illegal_req(atio, ctio);
308 		sense->sense_key_spec[0] = SSD_SCS_VALID | SSD_FIELDPTR_CMD;
309 		sense->sense_key_spec[1] = 0;
310 		sense->sense_key_spec[2] =
311 			offsetof(struct scsi_inquiry, page_code);
312 	} else {
313 		bcopy(&inq_data, ctio->data_ptr, sizeof(inq_data));
314 		ctio->dxfer_len = inq_data.additional_length + 4;
315 		ctio->dxfer_len = min(ctio->dxfer_len,
316 				      SCSI_CDB6_LEN(inq->length));
317 		ctio->ccb_h.flags |= CAM_DIR_IN | CAM_SEND_STATUS;
318 		ctio->scsi_status = SCSI_STATUS_OK;
319 	}
320 	return (0);
321 }
322 
323 /* Initialize the inquiry response structure with the requested flags */
324 static int
325 init_inquiry(u_int16_t req_flags, u_int16_t sim_flags)
326 {
327 	struct scsi_inquiry_data *inq;
328 
329 	inq = &inq_data;
330 	bzero(inq, sizeof(*inq));
331 	inq->device = T_DIRECT | (SID_QUAL_LU_CONNECTED << 5);
332 	inq->version = SCSI_REV_SPC; /* was 2 */
333 
334 	/*
335 	 * XXX cpi.hba_inquiry doesn't support Addr16 so we give the
336 	 * user what they want if they ask for it.
337 	 */
338 	if ((req_flags & SID_Addr16) != 0) {
339 		sim_flags |= SID_Addr16;
340 		warnx("Not sure SIM supports Addr16 but enabling it anyway");
341 	}
342 
343 	/* Advertise only what the SIM can actually support */
344 	req_flags &= sim_flags;
345 	scsi_ulto2b(req_flags, &inq->reserved[1]);
346 
347 	inq->response_format = 2; /* SCSI2 Inquiry Format */
348 	inq->additional_length = SHORT_INQUIRY_LENGTH -
349 		offsetof(struct scsi_inquiry_data, additional_length);
350 	bcopy("FreeBSD ", inq->vendor, SID_VENDOR_SIZE);
351 	bcopy("Emulated Disk   ", inq->product, SID_PRODUCT_SIZE);
352 	bcopy("0.1 ", inq->revision, SID_REVISION_SIZE);
353 	return (0);
354 }
355 
356 static int
357 tcmd_req_sense(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
358 {
359 	struct scsi_request_sense *rsense;
360 	struct scsi_sense_data *sense;
361 	struct initiator_state *istate;
362 	size_t dlen;
363 	struct atio_descr *a_descr;
364 
365 	a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
366 	rsense = (struct scsi_request_sense *)a_descr->cdb;
367 
368 	istate = tcmd_get_istate(ctio->init_id);
369 	sense = &istate->sense_data;
370 
371 	if (debug) {
372 		cdb_debug(a_descr->cdb, "REQ SENSE from %u: ", atio->init_id);
373 		warnx("Sending sense: %#x %#x %#x", sense->flags,
374 		      sense->add_sense_code, sense->add_sense_code_qual);
375 	}
376 
377 	if (istate->orig_ca == 0) {
378 		tcmd_sense(ctio->init_id, NULL, SSD_KEY_NO_SENSE, 0, 0);
379 		warnx("REQUEST SENSE from %u but no pending CA!",
380 		      ctio->init_id);
381 	}
382 
383 	bcopy(sense, ctio->data_ptr, sizeof(struct scsi_sense_data));
384 	dlen = offsetof(struct scsi_sense_data, extra_len) +
385 			sense->extra_len + 1;
386 	ctio->dxfer_len = min(dlen, SCSI_CDB6_LEN(rsense->length));
387 	ctio->ccb_h.flags |= CAM_DIR_IN | CAM_SEND_STATUS;
388 	ctio->scsi_status = SCSI_STATUS_OK;
389 	return (0);
390 }
391 
392 static int
393 tcmd_rd_cap(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
394 {
395 	struct scsi_read_capacity_data *srp;
396 	struct atio_descr *a_descr;
397 
398 	a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
399 	srp = (struct scsi_read_capacity_data *)ctio->data_ptr;
400 
401 	if (debug) {
402 		cdb_debug(a_descr->cdb, "READ CAP from %u (%u, %u): ",
403 			  atio->init_id, volume_size - 1, sector_size);
404 	}
405 
406 	bzero(srp, sizeof(*srp));
407 	scsi_ulto4b(volume_size - 1, srp->addr);
408 	scsi_ulto4b(sector_size, srp->length);
409 
410 	ctio->dxfer_len = sizeof(*srp);
411 	ctio->ccb_h.flags |= CAM_DIR_IN | CAM_SEND_STATUS;
412 	ctio->scsi_status = SCSI_STATUS_OK;
413 	return (0);
414 }
415 
416 static int
417 tcmd_rdwr(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
418 {
419 	struct atio_descr *a_descr;
420 	struct ctio_descr *c_descr;
421 	int ret;
422 
423 	a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
424 	c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr;
425 
426 	/* Command needs to be decoded */
427 	if ((a_descr->flags & CAM_DIR_MASK) == CAM_DIR_RESV) {
428 		if (debug)
429 			warnx("Calling rdwr_decode");
430 		ret = tcmd_rdwr_decode(atio, ctio);
431 		if (ret == 0) {
432 			send_ccb((union ccb *)ctio, /*priority*/1);
433 			return (0);
434 		}
435 	}
436 	ctio->ccb_h.flags |= a_descr->flags;
437 
438 	/* Call appropriate work function */
439 	if ((a_descr->flags & CAM_DIR_IN) != 0) {
440 		ret = start_io(atio, ctio, CAM_DIR_IN);
441 		if (debug)
442 			warnx("Starting DIR_IN @%lld:%u", c_descr->offset,
443 			      a_descr->targ_req);
444 	} else {
445 		ret = start_io(atio, ctio, CAM_DIR_OUT);
446 		if (debug)
447 			warnx("Starting DIR_OUT @%lld:%u", c_descr->offset,
448 			      a_descr->init_req);
449 	}
450 
451 	return (ret);
452 }
453 
454 static int
455 tcmd_rdwr_decode(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
456 {
457 	u_int32_t blkno, count;
458 	struct atio_descr *a_descr;
459 	u_int8_t *cdb;
460 
461 	a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
462 	cdb = a_descr->cdb;
463 	if (debug)
464 		cdb_debug(cdb, "R/W from %u: ", atio->init_id);
465 
466 	if (cdb[0] == READ_6 || cdb[0] == WRITE_6) {
467 		struct scsi_rw_6 *rw_6 = (struct scsi_rw_6 *)cdb;
468 		blkno = scsi_3btoul(rw_6->addr);
469 		count = rw_6->length;
470 	} else {
471 		struct scsi_rw_10 *rw_10 = (struct scsi_rw_10 *)cdb;
472 		blkno = scsi_4btoul(rw_10->addr);
473 		count = scsi_2btoul(rw_10->length);
474 	}
475 	if (blkno + count > volume_size) {
476 		warnx("Attempt to access past end of volume");
477 		tcmd_sense(ctio->init_id, ctio,
478 			   SSD_KEY_ILLEGAL_REQUEST, 0x21, 0);
479 		return (0);
480 	}
481 
482 	/* Get an (overall) data length and set direction */
483 	a_descr->base_off = ((off_t)blkno) * sector_size;
484 	a_descr->total_len = count * sector_size;
485 	if (a_descr->total_len == 0) {
486 		if (debug)
487 			warnx("r/w 0 blocks @ blkno %u", blkno);
488 		tcmd_null_ok(atio, ctio);
489 		return (0);
490 	} else if (cdb[0] == WRITE_6 || cdb[0] == WRITE_10) {
491 		a_descr->flags |= CAM_DIR_OUT;
492 		if (debug)
493 			warnx("write %u blocks @ blkno %u", count, blkno);
494 	} else {
495 		a_descr->flags |= CAM_DIR_IN;
496 		if (debug)
497 			warnx("read %u blocks @ blkno %u", count, blkno);
498 	}
499 	return (1);
500 }
501 
502 static int
503 start_io(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio, int dir)
504 {
505 	struct atio_descr *a_descr;
506 	struct ctio_descr *c_descr;
507 	int ret;
508 
509 	/* Set up common structures */
510 	a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
511 	c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr;
512 
513 	if (dir == CAM_DIR_IN) {
514 		c_descr->offset = a_descr->base_off + a_descr->targ_req;
515 		ctio->dxfer_len = a_descr->total_len - a_descr->targ_req;
516 	} else {
517 		c_descr->offset = a_descr->base_off + a_descr->init_req;
518 		ctio->dxfer_len = a_descr->total_len - a_descr->init_req;
519 	}
520 	ctio->dxfer_len = min(ctio->dxfer_len, buf_size);
521 	assert(ctio->dxfer_len >= 0);
522 
523 	c_descr->aiocb.aio_offset = c_descr->offset;
524 	c_descr->aiocb.aio_nbytes = ctio->dxfer_len;
525 
526 	/* If DIR_IN, start read from target, otherwise begin CTIO xfer. */
527 	ret = 1;
528 	if (dir == CAM_DIR_IN) {
529 		if (aio_read(&c_descr->aiocb) < 0)
530 			err(1, "aio_read"); /* XXX */
531 		a_descr->targ_req += ctio->dxfer_len;
532 		if (a_descr->targ_req == a_descr->total_len) {
533 			ctio->ccb_h.flags |= CAM_SEND_STATUS;
534 			ctio->scsi_status = SCSI_STATUS_OK;
535 			ret = 0;
536 		}
537 	} else {
538 		if (a_descr->targ_ack == a_descr->total_len)
539 			tcmd_null_ok(atio, ctio);
540 		a_descr->init_req += ctio->dxfer_len;
541 		if (a_descr->init_req == a_descr->total_len &&
542 		    ctio->dxfer_len > 0) {
543 			/*
544 			 * If data phase done, remove atio from workq.
545 			 * The completion handler will call work_atio to
546 			 * send the final status.
547 			 */
548 			ret = 0;
549 		}
550 		send_ccb((union ccb *)ctio, /*priority*/1);
551 	}
552 
553 	return (ret);
554 }
555 
556 static void
557 tcmd_rdwr_done(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio,
558 	       io_ops event)
559 {
560 	struct atio_descr *a_descr;
561 	struct ctio_descr *c_descr;
562 
563 	a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
564 	c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr;
565 
566 	switch (event) {
567 	case AIO_DONE:
568 		if (aio_return(&c_descr->aiocb) < 0) {
569 			warn("aio_return error");
570 			/* XXX */
571 			tcmd_sense(ctio->init_id, ctio,
572 				   SSD_KEY_MEDIUM_ERROR, 0, 0);
573 			send_ccb((union ccb *)ctio, /*priority*/1);
574 			break;
575 		}
576 		a_descr->targ_ack += ctio->dxfer_len;
577 		if ((a_descr->flags & CAM_DIR_IN) != 0) {
578 			if (debug)
579 				warnx("sending CTIO for AIO read");
580 			a_descr->init_req += ctio->dxfer_len;
581 			send_ccb((union ccb *)ctio, /*priority*/1);
582 		} else {
583 			/* Use work function to send final status */
584 			if (a_descr->init_req == a_descr->total_len)
585 				work_atio(atio);
586 			if (debug)
587 				warnx("AIO done freeing CTIO");
588 			free_ccb((union ccb *)ctio);
589 		}
590 		break;
591 	case CTIO_DONE:
592 		if (ctio->ccb_h.status != CAM_REQ_CMP) {
593 			/* XXX */
594 			errx(1, "CTIO failed, status %#x", ctio->ccb_h.status);
595 		}
596 		a_descr->init_ack += ctio->dxfer_len;
597 		if ((a_descr->flags & CAM_DIR_MASK) == CAM_DIR_OUT &&
598 		    ctio->dxfer_len > 0) {
599 			if (debug)
600 				warnx("sending AIO for CTIO write");
601 			a_descr->targ_req += ctio->dxfer_len;
602 			if (aio_write(&c_descr->aiocb) < 0)
603 				err(1, "aio_write"); /* XXX */
604 		} else {
605 			if (debug)
606 				warnx("CTIO done freeing CTIO");
607 			free_ccb((union ccb *)ctio);
608 		}
609 		break;
610 	default:
611 		warnx("Unknown completion code %d", event);
612 		abort();
613 		/* NOTREACHED */
614 	}
615 }
616 
617 /* Simple ok message used by TUR, SYNC_CACHE, etc. */
618 static int
619 tcmd_null_ok(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
620 {
621 	if (debug) {
622 		struct atio_descr *a_descr;
623 
624 		a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
625 		cdb_debug(a_descr->cdb, "Sending null ok to %u : ", atio->init_id);
626 	}
627 
628 	ctio->dxfer_len = 0;
629 	ctio->ccb_h.flags &= ~CAM_DIR_MASK;
630 	ctio->ccb_h.flags |= CAM_DIR_NONE | CAM_SEND_STATUS;
631 	ctio->scsi_status = SCSI_STATUS_OK;
632 	return (0);
633 }
634 
635 /* Simple illegal request message used by MODE SENSE, etc. */
636 static int
637 tcmd_illegal_req(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
638 {
639 	if (debug) {
640 		struct atio_descr *a_descr;
641 
642 		a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
643 		cdb_debug(a_descr->cdb, "Sending ill req to %u: ", atio->init_id);
644 	}
645 
646 	tcmd_sense(atio->init_id, ctio, SSD_KEY_ILLEGAL_REQUEST,
647 		   /*asc*/0x24, /*ascq*/0);
648 	return (0);
649 }
650 
651 static void
652 cdb_debug(u_int8_t *cdb, const char *msg, ...)
653 {
654 	char msg_buf[512];
655 	int len;
656 	va_list ap;
657 
658 	va_start(ap, msg);
659 	vsnprintf(msg_buf, sizeof(msg_buf), msg, ap);
660 	va_end(ap);
661 	len = strlen(msg_buf);
662 	scsi_cdb_string(cdb, msg_buf + len, sizeof(msg_buf) - len);
663 	warnx("%s", msg_buf);
664 }
665