From 6e69f5077da3f7c660dae7b52f7773baeef26f36 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Wed, 28 Oct 2020 03:28:32 +0000 Subject: [PATCH] Implement SCSI types in FreeBSD. --- freebsd/scsi.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/freebsd/scsi.c b/freebsd/scsi.c index c011fb9..1ae91d6 100644 --- a/freebsd/scsi.c +++ b/freebsd/scsi.c @@ -15,7 +15,11 @@ * along with this program. If not, see . */ +#include +#include #include +#include +#include #include "../aaruremote.h" #include "freebsd.h" @@ -32,5 +36,92 @@ int32_t SendScsiCommand(void* device_ctx, uint32_t* buf_len, uint32_t* sense_len) { - return -1; + DeviceContext* ctx = device_ctx; + *sense_len = 0; + *sense_buffer = NULL; + *duration = 0; + union ccb* camccb; + u_int32_t flags; + int error; + + switch(direction) + { + case AARUREMOTE_SCSI_DIRECTION_NONE: + flags = CAM_DIR_NONE; + break; + case AARUREMOTE_SCSI_DIRECTION_OUT: + flags = CAM_DIR_OUT; + break; + case AARUREMOTE_SCSI_DIRECTION_IN: + flags = CAM_DIR_IN; + break; + case AARUREMOTE_SCSI_DIRECTION_INOUT: + flags = CAM_DIR_BOTH; + break; + } + + if(!ctx) return -1; + if(!ctx->device) return -1; + + *sense_buffer = malloc(32); + + if(!*sense_buffer) return -1; + + camccb = cam_getccb(ctx->device); + + if(!camccb) return -1; + + camccb->ccb_h.func_code = XPT_SCSI_IO; + camccb->ccb_h.flags = flags; + camccb->ccb_h.xflags = 0; + camccb->ccb_h.retry_count = 1; + camccb->ccb_h.cbfcnp = NULL; + camccb->ccb_h.timeout = timeout; + camccb->csio.data_ptr = (u_int8_t *)buffer; + camccb->csio.dxfer_len = *buf_len; + camccb->csio.sense_len = 32; + camccb->csio.cdb_len = cdb_len; + camccb->csio.tag_action = 0x20; + + if(cdb_len <= CAM_MAX_CDBLEN) + memcpy(camccb->csio.cdb_io.cdb_bytes, cdb, cdb_len); + else + { + camccb->csio.cdb_io.cdb_ptr = (u_int8_t *)cdb; + camccb->ccb_h.flags |= CAM_CDB_POINTER; + } + + camccb->ccb_h.flags |= CAM_DEV_QFRZDIS; + + // TODO: Measure duration + error = cam_send_ccb(ctx->device, camccb); + + if(error < 0) + error = errno; + + if((camccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP && + (camccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR) + { + error = errno; + *sense = true; + } + + if((camccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) + { + *sense = true; + *sense_buffer = malloc(1); + (*sense_buffer)[0] = camccb->csio.scsi_status; + } + + if((camccb->ccb_h.status & CAM_AUTOSNS_VALID) && camccb->csio.sense_len - camccb->csio.sense_resid > 0) + { + *sense = (camccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR; + *sense_buffer = malloc(camccb->csio.sense_len - camccb->csio.sense_resid); + (*sense_buffer)[0] = camccb->csio.sense_data.error_code; + memcpy((*sense_buffer)+1, camccb->csio.sense_data.sense_buf, (camccb->csio.sense_len - camccb->csio.sense_resid) - 1); + } + + *buf_len = camccb->csio.dxfer_len; + + return error; } \ No newline at end of file