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
40 #include <sys/param.h>
41 #include <sys/types.h>
44 #include <cam/cam_ccb.h>
45 #include <cam/scsi/scsi_all.h>
46 #include <cam/scsi/scsi_targetio.h>
47 #include "scsi_target.h"
49 typedef int targ_start_func(struct ccb_accept_tio
*, struct ccb_scsiio
*);
50 typedef void targ_done_func(struct ccb_accept_tio
*, struct ccb_scsiio
*,
53 #define REPORT_LUNS 0xa0
56 struct targ_cdb_handlers
{
58 targ_start_func
*start
;
60 #define ILLEGAL_CDB 0xFF
63 static targ_start_func tcmd_inquiry
;
64 static targ_start_func tcmd_req_sense
;
65 static targ_start_func tcmd_rd_cap
;
67 static targ_start_func tcmd_rd_cap16
;
69 static targ_start_func tcmd_rdwr
;
70 static targ_start_func tcmd_rdwr_decode
;
71 static targ_done_func tcmd_rdwr_done
;
72 static targ_start_func tcmd_null_ok
;
73 static targ_start_func tcmd_illegal_req
;
74 static int start_io(struct ccb_accept_tio
*atio
,
75 struct ccb_scsiio
*ctio
, int dir
);
76 static int init_inquiry(u_int16_t req_flags
, u_int16_t sim_flags
);
77 static struct initiator_state
*
78 tcmd_get_istate(u_int init_id
);
79 static void cdb_debug(u_int8_t
*cdb
, const char *msg
, ...);
81 static struct targ_cdb_handlers cdb_handlers
[] = {
82 { READ_10
, tcmd_rdwr
, tcmd_rdwr_done
},
83 { WRITE_10
, tcmd_rdwr
, tcmd_rdwr_done
},
84 { READ_6
, tcmd_rdwr
, tcmd_rdwr_done
},
85 { WRITE_6
, tcmd_rdwr
, tcmd_rdwr_done
},
86 { INQUIRY
, tcmd_inquiry
, NULL
},
87 { REQUEST_SENSE
, tcmd_req_sense
, NULL
},
88 { READ_CAPACITY
, tcmd_rd_cap
, NULL
},
89 { TEST_UNIT_READY
, tcmd_null_ok
, NULL
},
90 { START_STOP_UNIT
, tcmd_null_ok
, NULL
},
91 { SYNCHRONIZE_CACHE
, tcmd_null_ok
, NULL
},
92 { MODE_SENSE_6
, tcmd_illegal_req
, NULL
},
93 { MODE_SELECT_6
, tcmd_illegal_req
, NULL
},
94 { REPORT_LUNS
, tcmd_illegal_req
, NULL
},
96 { READ_16
, tcmd_rdwr
, tcmd_rdwr_done
},
97 { WRITE_16
, tcmd_rdwr
, tcmd_rdwr_done
},
98 { SERVICE_ACTION_IN
, tcmd_rd_cap16
, NULL
},
100 { ILLEGAL_CDB
, NULL
, NULL
}
103 static struct scsi_inquiry_data inq_data
;
104 static struct initiator_state istates
[MAX_INITIATORS
];
106 extern uint64_t volume_size
;
107 extern size_t sector_size
;
108 extern size_t buf_size
;
111 tcmd_init(u_int16_t req_inq_flags
, u_int16_t sim_inq_flags
)
113 struct initiator_state
*istate
;
116 /* Initialize our inquiry data */
117 ret
= init_inquiry(req_inq_flags
, sim_inq_flags
);
121 /* We start out life with a UA to indicate power-on/reset. */
122 for (i
= 0; i
< MAX_INITIATORS
; i
++) {
123 istate
= tcmd_get_istate(i
);
124 bzero(istate
, sizeof(*istate
));
125 istate
->pending_ua
= UA_POWER_ON
;
131 /* Caller allocates CTIO, sets its init_id
132 return 0 if done, 1 if more processing needed
133 on 0, caller sets SEND_STATUS */
135 tcmd_handle(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
, io_ops event
)
137 static struct targ_cdb_handlers
*last_cmd
;
138 struct initiator_state
*istate
;
139 struct atio_descr
*a_descr
;
143 warnx("tcmd_handle atio %p ctio %p atioflags %#x", atio
, ctio
,
147 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
149 /* Do a full lookup if one-behind cache failed */
150 if (last_cmd
== NULL
|| last_cmd
->cmd
!= a_descr
->cdb
[0]) {
151 struct targ_cdb_handlers
*h
;
153 for (h
= cdb_handlers
; h
->cmd
!= ILLEGAL_CDB
; h
++) {
154 if (a_descr
->cdb
[0] == h
->cmd
)
160 /* call completion and exit */
161 if (event
!= ATIO_WORK
) {
162 if (last_cmd
->done
!= NULL
)
163 last_cmd
->done(atio
, ctio
, event
);
165 free_ccb((union ccb
*)ctio
);
169 if (last_cmd
->cmd
== ILLEGAL_CDB
) {
170 if (event
!= ATIO_WORK
) {
171 warnx("no done func for %#x???", a_descr
->cdb
[0]);
174 /* Not found, return illegal request */
175 warnx("cdb %#x not handled", a_descr
->cdb
[0]);
176 tcmd_illegal_req(atio
, ctio
);
177 send_ccb((union ccb
*)ctio
, /*priority*/1);
181 istate
= tcmd_get_istate(ctio
->init_id
);
182 if (istate
== NULL
) {
183 tcmd_illegal_req(atio
, ctio
);
184 send_ccb((union ccb
*)ctio
, /*priority*/1);
188 if (istate
->pending_ca
== 0 && istate
->pending_ua
!= 0 &&
189 a_descr
->cdb
[0] != INQUIRY
) {
190 tcmd_sense(ctio
->init_id
, ctio
, SSD_KEY_UNIT_ATTENTION
,
191 0x29, istate
->pending_ua
== UA_POWER_ON
? 1 : 2);
192 istate
->pending_ca
= CA_UNIT_ATTN
;
194 cdb_debug(a_descr
->cdb
, "UA active for %u: ",
197 send_ccb((union ccb
*)ctio
, /*priority*/1);
201 /* Store current CA and UA for later */
202 istate
->orig_ua
= istate
->pending_ua
;
203 istate
->orig_ca
= istate
->pending_ca
;
206 * As per SAM2, any command that occurs
207 * after a CA is reported, clears the CA. We must
208 * also clear the UA condition, if any, that caused
209 * the CA to occur assuming the UA is not for a
210 * persistent condition.
212 istate
->pending_ca
= CA_NONE
;
213 if (istate
->orig_ca
== CA_UNIT_ATTN
)
214 istate
->pending_ua
= UA_NONE
;
216 /* If we have a valid handler, call start or completion function */
217 if (last_cmd
->cmd
!= ILLEGAL_CDB
) {
218 ret
= last_cmd
->start(atio
, ctio
);
220 if (last_cmd
->start
!= tcmd_rdwr
) {
221 a_descr
->init_req
+= ctio
->dxfer_len
;
222 send_ccb((union ccb
*)ctio
, /*priority*/1);
229 static struct initiator_state
*
230 tcmd_get_istate(u_int init_id
)
232 if (init_id
>= MAX_INITIATORS
) {
233 warnx("illegal init_id %d, max %d", init_id
, MAX_INITIATORS
- 1);
236 return (&istates
[init_id
]);
241 tcmd_sense(u_int init_id
, struct ccb_scsiio
*ctio
, u_int8_t flags
,
242 u_int8_t asc
, u_int8_t ascq
)
244 struct initiator_state
*istate
;
245 struct scsi_sense_data
*sense
;
247 /* Set our initiator's istate */
248 istate
= tcmd_get_istate(init_id
);
251 istate
->pending_ca
|= CA_CMD_SENSE
; /* XXX set instead of or? */
252 sense
= &istate
->sense_data
;
253 bzero(sense
, sizeof(*sense
));
254 sense
->error_code
= SSD_CURRENT_ERROR
;
255 sense
->flags
= flags
;
256 sense
->add_sense_code
= asc
;
257 sense
->add_sense_code_qual
= ascq
;
259 offsetof(struct scsi_sense_data
, sense_key_spec
[2]) -
260 offsetof(struct scsi_sense_data
, extra_len
);
262 /* Fill out the supplied CTIO */
264 bcopy(sense
, &ctio
->sense_data
, sizeof(*sense
));
265 ctio
->sense_len
= sizeof(*sense
); /* XXX */
266 ctio
->ccb_h
.flags
&= ~CAM_DIR_MASK
;
267 ctio
->ccb_h
.flags
|= CAM_DIR_NONE
| CAM_SEND_SENSE
|
270 ctio
->scsi_status
= SCSI_STATUS_CHECK_COND
;
275 tcmd_ua(u_int init_id
, ua_types new_ua
)
277 struct initiator_state
*istate
;
280 if (init_id
== CAM_TARGET_WILDCARD
) {
282 end
= MAX_INITIATORS
- 1;
284 start
= end
= init_id
;
287 for (; start
<= end
; start
++) {
288 istate
= tcmd_get_istate(start
);
291 istate
->pending_ua
= new_ua
;
296 tcmd_inquiry(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
298 struct scsi_inquiry
*inq
;
299 struct atio_descr
*a_descr
;
300 struct initiator_state
*istate
;
301 struct scsi_sense_data
*sense
;
303 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
304 inq
= (struct scsi_inquiry
*)a_descr
->cdb
;
307 cdb_debug(a_descr
->cdb
, "INQUIRY from %u: ", atio
->init_id
);
309 * Validate the command. We don't support any VPD pages, so
310 * complain if EVPD or CMDDT is set.
312 istate
= tcmd_get_istate(ctio
->init_id
);
313 sense
= &istate
->sense_data
;
314 if ((inq
->byte2
& SI_EVPD
) != 0) {
315 tcmd_illegal_req(atio
, ctio
);
316 sense
->sense_key_spec
[0] = SSD_SCS_VALID
| SSD_FIELDPTR_CMD
|
317 SSD_BITPTR_VALID
| /*bit value*/1;
318 sense
->sense_key_spec
[1] = 0;
319 sense
->sense_key_spec
[2] =
320 offsetof(struct scsi_inquiry
, byte2
);
321 } else if (inq
->page_code
!= 0) {
322 tcmd_illegal_req(atio
, ctio
);
323 sense
->sense_key_spec
[0] = SSD_SCS_VALID
| SSD_FIELDPTR_CMD
;
324 sense
->sense_key_spec
[1] = 0;
325 sense
->sense_key_spec
[2] =
326 offsetof(struct scsi_inquiry
, page_code
);
328 bcopy(&inq_data
, ctio
->data_ptr
, sizeof(inq_data
));
329 ctio
->dxfer_len
= inq_data
.additional_length
+ 4;
330 ctio
->dxfer_len
= min(ctio
->dxfer_len
,
331 SCSI_CDB6_LEN(inq
->length
));
332 ctio
->ccb_h
.flags
|= CAM_DIR_IN
| CAM_SEND_STATUS
;
333 ctio
->scsi_status
= SCSI_STATUS_OK
;
338 /* Initialize the inquiry response structure with the requested flags */
340 init_inquiry(u_int16_t req_flags
, u_int16_t sim_flags
)
342 struct scsi_inquiry_data
*inq
;
345 bzero(inq
, sizeof(*inq
));
346 inq
->device
= T_DIRECT
| (SID_QUAL_LU_CONNECTED
<< 5);
348 inq
->version
= SCSI_REV_SPC
; /* was 2 */
350 inq
->version
= SCSI_REV_3
; /* was 2 */
354 * XXX cpi.hba_inquiry doesn't support Addr16 so we give the
355 * user what they want if they ask for it.
357 if ((req_flags
& SID_Addr16
) != 0) {
358 sim_flags
|= SID_Addr16
;
359 warnx("Not sure SIM supports Addr16 but enabling it anyway");
362 /* Advertise only what the SIM can actually support */
363 req_flags
&= sim_flags
;
364 scsi_ulto2b(req_flags
, &inq
->spc2_flags
);
366 inq
->response_format
= 2; /* SCSI2 Inquiry Format */
367 inq
->additional_length
= SHORT_INQUIRY_LENGTH
-
368 offsetof(struct scsi_inquiry_data
, additional_length
);
369 bcopy("FreeBSD ", inq
->vendor
, SID_VENDOR_SIZE
);
370 bcopy("Emulated Disk ", inq
->product
, SID_PRODUCT_SIZE
);
371 bcopy("0.1 ", inq
->revision
, SID_REVISION_SIZE
);
376 tcmd_req_sense(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
378 struct scsi_request_sense
*rsense
;
379 struct scsi_sense_data
*sense
;
380 struct initiator_state
*istate
;
382 struct atio_descr
*a_descr
;
384 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
385 rsense
= (struct scsi_request_sense
*)a_descr
->cdb
;
387 istate
= tcmd_get_istate(ctio
->init_id
);
388 sense
= &istate
->sense_data
;
391 cdb_debug(a_descr
->cdb
, "REQ SENSE from %u: ", atio
->init_id
);
392 warnx("Sending sense: %#x %#x %#x", sense
->flags
,
393 sense
->add_sense_code
, sense
->add_sense_code_qual
);
396 if (istate
->orig_ca
== 0) {
397 tcmd_sense(ctio
->init_id
, NULL
, SSD_KEY_NO_SENSE
, 0, 0);
398 warnx("REQUEST SENSE from %u but no pending CA!",
402 bcopy(sense
, ctio
->data_ptr
, sizeof(struct scsi_sense_data
));
403 dlen
= offsetof(struct scsi_sense_data
, extra_len
) +
404 sense
->extra_len
+ 1;
405 ctio
->dxfer_len
= min(dlen
, SCSI_CDB6_LEN(rsense
->length
));
406 ctio
->ccb_h
.flags
|= CAM_DIR_IN
| CAM_SEND_STATUS
;
407 ctio
->scsi_status
= SCSI_STATUS_OK
;
412 tcmd_rd_cap(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
414 struct scsi_read_capacity_data
*srp
;
415 struct atio_descr
*a_descr
;
418 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
419 srp
= (struct scsi_read_capacity_data
*)ctio
->data_ptr
;
421 if (volume_size
> 0xffffffff)
424 vsize
= (uint32_t)(volume_size
- 1);
427 cdb_debug(a_descr
->cdb
, "READ CAP from %u (%u, %u): ",
428 atio
->init_id
, vsize
, sector_size
);
431 bzero(srp
, sizeof(*srp
));
432 scsi_ulto4b(vsize
, srp
->addr
);
433 scsi_ulto4b(sector_size
, srp
->length
);
435 ctio
->dxfer_len
= sizeof(*srp
);
436 ctio
->ccb_h
.flags
|= CAM_DIR_IN
| CAM_SEND_STATUS
;
437 ctio
->scsi_status
= SCSI_STATUS_OK
;
443 tcmd_rd_cap16(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
445 struct scsi_read_capacity_16
*scsi_cmd
;
446 struct scsi_read_capacity_data_long
*srp
;
447 struct atio_descr
*a_descr
;
449 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
450 scsi_cmd
= (struct scsi_read_capacity_16
*)a_descr
->cdb
;
451 srp
= (struct scsi_read_capacity_data_long
*)ctio
->data_ptr
;
453 if (scsi_cmd
->service_action
!= SRC16_SERVICE_ACTION
) {
454 tcmd_illegal_req(atio
, ctio
);
459 cdb_debug(a_descr
->cdb
, "READ CAP16 from %u (%u, %u): ",
460 atio
->init_id
, volume_size
- 1, sector_size
);
463 bzero(srp
, sizeof(*srp
));
464 scsi_u64to8b(volume_size
- 1, srp
->addr
);
465 scsi_ulto4b(sector_size
, srp
->length
);
467 ctio
->dxfer_len
= sizeof(*srp
);
468 ctio
->ccb_h
.flags
|= CAM_DIR_IN
| CAM_SEND_STATUS
;
469 ctio
->scsi_status
= SCSI_STATUS_OK
;
475 tcmd_rdwr(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
477 struct atio_descr
*a_descr
;
478 struct ctio_descr
*c_descr
;
481 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
482 c_descr
= (struct ctio_descr
*)ctio
->ccb_h
.targ_descr
;
484 /* Command needs to be decoded */
485 if ((a_descr
->flags
& CAM_DIR_MASK
) == CAM_DIR_RESV
) {
487 warnx("Calling rdwr_decode");
488 ret
= tcmd_rdwr_decode(atio
, ctio
);
490 send_ccb((union ccb
*)ctio
, /*priority*/1);
494 ctio
->ccb_h
.flags
|= a_descr
->flags
;
496 /* Call appropriate work function */
497 if ((a_descr
->flags
& CAM_DIR_IN
) != 0) {
498 ret
= start_io(atio
, ctio
, CAM_DIR_IN
);
500 warnx("Starting %p DIR_IN @" OFF_FMT
":%u",
501 a_descr
, c_descr
->offset
, a_descr
->targ_req
);
503 ret
= start_io(atio
, ctio
, CAM_DIR_OUT
);
505 warnx("Starting %p DIR_OUT @" OFF_FMT
":%u",
506 a_descr
, c_descr
->offset
, a_descr
->init_req
);
513 tcmd_rdwr_decode(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
517 struct atio_descr
*a_descr
;
520 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
523 cdb_debug(cdb
, "R/W from %u: ", atio
->init_id
);
529 struct scsi_rw_6
*rw_6
= (struct scsi_rw_6
*)cdb
;
530 blkno
= scsi_3btoul(rw_6
->addr
);
531 count
= rw_6
->length
;
537 struct scsi_rw_10
*rw_10
= (struct scsi_rw_10
*)cdb
;
538 blkno
= scsi_4btoul(rw_10
->addr
);
539 count
= scsi_2btoul(rw_10
->length
);
546 struct scsi_rw_16
*rw_16
= (struct scsi_rw_16
*)cdb
;
547 blkno
= scsi_8btou64(rw_16
->addr
);
548 count
= scsi_4btoul(rw_16
->length
);
553 tcmd_illegal_req(atio
, ctio
);
556 if (blkno
+ count
> volume_size
) {
557 warnx("Attempt to access past end of volume");
558 tcmd_sense(ctio
->init_id
, ctio
,
559 SSD_KEY_ILLEGAL_REQUEST
, 0x21, 0);
563 /* Get an (overall) data length and set direction */
564 a_descr
->base_off
= ((off_t
)blkno
) * sector_size
;
565 a_descr
->total_len
= count
* sector_size
;
566 if (a_descr
->total_len
== 0) {
568 warnx("r/w 0 blocks @ blkno " OFF_FMT
, blkno
);
569 tcmd_null_ok(atio
, ctio
);
571 } else if (cdb
[0] == WRITE_6
|| cdb
[0] == WRITE_10
) {
572 a_descr
->flags
|= CAM_DIR_OUT
;
574 warnx("write %u blocks @ blkno " OFF_FMT
, count
, blkno
);
576 a_descr
->flags
|= CAM_DIR_IN
;
578 warnx("read %u blocks @ blkno " OFF_FMT
, count
, blkno
);
584 start_io(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
, int dir
)
586 struct atio_descr
*a_descr
;
587 struct ctio_descr
*c_descr
;
590 /* Set up common structures */
591 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
592 c_descr
= (struct ctio_descr
*)ctio
->ccb_h
.targ_descr
;
594 if (dir
== CAM_DIR_IN
) {
595 c_descr
->offset
= a_descr
->base_off
+ a_descr
->targ_req
;
596 ctio
->dxfer_len
= a_descr
->total_len
- a_descr
->targ_req
;
598 c_descr
->offset
= a_descr
->base_off
+ a_descr
->init_req
;
599 ctio
->dxfer_len
= a_descr
->total_len
- a_descr
->init_req
;
601 ctio
->dxfer_len
= min(ctio
->dxfer_len
, buf_size
);
602 assert(ctio
->dxfer_len
>= 0);
604 c_descr
->aiocb
.aio_offset
= c_descr
->offset
;
605 c_descr
->aiocb
.aio_nbytes
= ctio
->dxfer_len
;
607 /* If DIR_IN, start read from target, otherwise begin CTIO xfer. */
609 if (dir
== CAM_DIR_IN
) {
612 warnx("read sync %lud @ block " OFF_FMT
,
614 (ctio
->dxfer_len
/ sector_size
),
615 c_descr
->offset
/ sector_size
);
616 if (lseek(c_descr
->aiocb
.aio_fildes
,
617 c_descr
->aiocb
.aio_offset
, SEEK_SET
) < 0) {
621 if (read(c_descr
->aiocb
.aio_fildes
,
622 (void *)c_descr
->aiocb
.aio_buf
,
623 ctio
->dxfer_len
) != ctio
->dxfer_len
) {
628 warnx("read async %lud @ block " OFF_FMT
,
630 (ctio
->dxfer_len
/ sector_size
),
631 c_descr
->offset
/ sector_size
);
632 if (aio_read(&c_descr
->aiocb
) < 0) {
633 err(1, "aio_read"); /* XXX */
636 a_descr
->targ_req
+= ctio
->dxfer_len
;
637 /* if we're done, we can mark the CCB as to send status */
638 if (a_descr
->targ_req
== a_descr
->total_len
) {
639 ctio
->ccb_h
.flags
|= CAM_SEND_STATUS
;
640 ctio
->scsi_status
= SCSI_STATUS_OK
;
644 tcmd_rdwr_done(atio
, ctio
, AIO_DONE
);
646 if (a_descr
->targ_ack
== a_descr
->total_len
)
647 tcmd_null_ok(atio
, ctio
);
648 a_descr
->init_req
+= ctio
->dxfer_len
;
649 if (a_descr
->init_req
== a_descr
->total_len
&&
650 ctio
->dxfer_len
> 0) {
652 * If data phase done, remove atio from workq.
653 * The completion handler will call work_atio to
654 * send the final status.
658 send_ccb((union ccb
*)ctio
, /*priority*/1);
665 tcmd_rdwr_done(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
,
668 struct atio_descr
*a_descr
;
669 struct ctio_descr
*c_descr
;
671 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
672 c_descr
= (struct ctio_descr
*)ctio
->ccb_h
.targ_descr
;
676 if (!notaio
&& aio_return(&c_descr
->aiocb
) < 0) {
677 warn("aio_return error");
679 tcmd_sense(ctio
->init_id
, ctio
,
680 SSD_KEY_MEDIUM_ERROR
, 0, 0);
681 send_ccb((union ccb
*)ctio
, /*priority*/1);
684 a_descr
->targ_ack
+= ctio
->dxfer_len
;
685 if ((a_descr
->flags
& CAM_DIR_IN
) != 0) {
688 warnx("sending CTIO for AIO read");
690 warnx("sending CTIO for sync read");
692 a_descr
->init_req
+= ctio
->dxfer_len
;
693 send_ccb((union ccb
*)ctio
, /*priority*/1);
695 /* Use work function to send final status */
696 if (a_descr
->init_req
== a_descr
->total_len
)
699 warnx("AIO done freeing CTIO");
700 free_ccb((union ccb
*)ctio
);
704 switch (ctio
->ccb_h
.status
& CAM_STATUS_MASK
) {
707 case CAM_REQUEUE_REQ
:
708 warnx("requeueing request");
709 if ((a_descr
->flags
& CAM_DIR_MASK
) == CAM_DIR_OUT
) {
710 if (aio_write(&c_descr
->aiocb
) < 0) {
711 err(1, "aio_write"); /* XXX */
714 if (aio_read(&c_descr
->aiocb
) < 0) {
715 err(1, "aio_read"); /* XXX */
720 errx(1, "CTIO failed, status %#x", ctio
->ccb_h
.status
);
722 a_descr
->init_ack
+= ctio
->dxfer_len
;
723 if ((a_descr
->flags
& CAM_DIR_MASK
) == CAM_DIR_OUT
&&
724 ctio
->dxfer_len
> 0) {
725 a_descr
->targ_req
+= ctio
->dxfer_len
;
728 warnx("write sync %lud @ block "
729 OFF_FMT
, (unsigned long)
730 (ctio
->dxfer_len
/ sector_size
),
731 c_descr
->offset
/ sector_size
);
732 if (lseek(c_descr
->aiocb
.aio_fildes
,
733 c_descr
->aiocb
.aio_offset
, SEEK_SET
) < 0) {
737 if (write(c_descr
->aiocb
.aio_fildes
,
738 (void *) c_descr
->aiocb
.aio_buf
,
739 ctio
->dxfer_len
) != ctio
->dxfer_len
) {
742 tcmd_rdwr_done(atio
, ctio
, AIO_DONE
);
745 warnx("write async %lud @ block "
746 OFF_FMT
, (unsigned long)
747 (ctio
->dxfer_len
/ sector_size
),
748 c_descr
->offset
/ sector_size
);
749 if (aio_write(&c_descr
->aiocb
) < 0) {
750 err(1, "aio_write"); /* XXX */
755 warnx("CTIO done freeing CTIO");
756 free_ccb((union ccb
*)ctio
);
760 warnx("Unknown completion code %d", event
);
766 /* Simple ok message used by TUR, SYNC_CACHE, etc. */
768 tcmd_null_ok(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
771 struct atio_descr
*a_descr
;
773 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
774 cdb_debug(a_descr
->cdb
, "Sending null ok to %u : ", atio
->init_id
);
778 ctio
->ccb_h
.flags
&= ~CAM_DIR_MASK
;
779 ctio
->ccb_h
.flags
|= CAM_DIR_NONE
| CAM_SEND_STATUS
;
780 ctio
->scsi_status
= SCSI_STATUS_OK
;
784 /* Simple illegal request message used by MODE SENSE, etc. */
786 tcmd_illegal_req(struct ccb_accept_tio
*atio
, struct ccb_scsiio
*ctio
)
789 struct atio_descr
*a_descr
;
791 a_descr
= (struct atio_descr
*)atio
->ccb_h
.targ_descr
;
792 cdb_debug(a_descr
->cdb
, "Sending ill req to %u: ", atio
->init_id
);
795 tcmd_sense(atio
->init_id
, ctio
, SSD_KEY_ILLEGAL_REQUEST
,
796 /*asc*/0x24, /*ascq*/0);
801 cdb_debug(u_int8_t
*cdb
, const char *msg
, ...)
808 vsnprintf(msg_buf
, sizeof(msg_buf
), msg
, ap
);
810 len
= strlen(msg_buf
);
811 scsi_cdb_string(cdb
, msg_buf
+ len
, sizeof(msg_buf
) - len
);
812 warnx("%s", msg_buf
);