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