Files
aaruremote/freebsd/scsi.c

140 lines
4.2 KiB
C
Raw Normal View History

2020-10-26 01:11:00 +00:00
/*
* This file is part of the Aaru Remote Server.
2020-12-31 23:12:05 +00:00
* Copyright (c) 2019-2021 Natalia Portillo.
2020-10-26 01:11:00 +00:00
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2020-10-28 03:28:32 +00:00
#include <errno.h>
#include <stdbool.h>
2020-10-26 01:11:00 +00:00
#include <stdint.h>
2020-10-28 03:28:32 +00:00
#include <stdlib.h>
#include <string.h>
#include <time.h>
2020-10-26 01:11:00 +00:00
#include "../aaruremote.h"
#include "freebsd.h"
2024-04-30 15:42:08 +01:00
int32_t SendScsiCommand(void *device_ctx, char *cdb, char *buffer, char **sense_buffer, uint32_t timeout,
int32_t direction, uint32_t *duration, uint32_t *sense, uint32_t cdb_len, uint32_t *buf_len,
uint32_t *sense_len)
2020-10-26 01:11:00 +00:00
{
2024-04-30 15:42:08 +01:00
DeviceContext *ctx = device_ctx;
2020-10-31 02:28:50 +00:00
*sense_len = 0;
*sense_buffer = NULL;
*duration = 0;
*sense = false;
2024-04-30 15:42:08 +01:00
union ccb *camccb;
2020-10-31 02:28:50 +00:00
u_int32_t flags;
int error;
int clock_error;
struct timespec start_tp;
struct timespec end_tp;
2020-10-31 02:28:50 +00:00
double start, end;
2020-10-28 03:28:32 +00:00
switch(direction)
{
2024-04-30 15:42:08 +01:00
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;
2020-10-28 03:28:32 +00:00
}
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;
2020-10-31 02:28:50 +00:00
camccb->ccb_h.func_code = XPT_SCSI_IO;
camccb->ccb_h.flags = flags;
camccb->ccb_h.xflags = 0;
2020-10-28 03:28:32 +00:00
camccb->ccb_h.retry_count = 1;
2020-10-31 02:28:50 +00:00
camccb->ccb_h.cbfcnp = NULL;
camccb->ccb_h.timeout = timeout;
2024-04-30 15:42:08 +01:00
camccb->csio.data_ptr = (u_int8_t *)buffer;
2020-10-31 02:28:50 +00:00
camccb->csio.dxfer_len = *buf_len;
camccb->csio.sense_len = 32;
camccb->csio.cdb_len = cdb_len;
camccb->csio.tag_action = 0x20;
2024-04-30 15:42:08 +01:00
if(cdb_len <= CAM_MAX_CDBLEN)
memcpy(camccb->csio.cdb_io.cdb_bytes, cdb, cdb_len);
2020-10-28 03:28:32 +00:00
else
{
2024-04-30 15:42:08 +01:00
camccb->csio.cdb_io.cdb_ptr = (u_int8_t *)cdb;
2020-10-28 03:28:32 +00:00
camccb->ccb_h.flags |= CAM_CDB_POINTER;
}
camccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
clock_error = clock_gettime(CLOCK_REALTIME_PRECISE, &start_tp);
2020-10-28 03:28:32 +00:00
error = cam_send_ccb(ctx->device, camccb);
2020-10-31 02:28:50 +00:00
if(!clock_error) clock_error = clock_gettime(CLOCK_REALTIME_PRECISE, &end_tp);
if(!clock_error)
{
start = (double)start_tp.tv_sec * 1000.0;
start += (double)start_tp.tv_nsec / 1000000.0;
end = (double)end_tp.tv_sec * 1000.0;
end += (double)end_tp.tv_nsec / 1000000.0;
2020-10-31 02:28:50 +00:00
*duration = (uint32_t)(end - start);
}
2020-10-31 02:28:50 +00:00
if(error < 0) error = errno;
2020-10-28 03:28:32 +00:00
if((camccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP &&
2020-10-31 02:28:50 +00:00
(camccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR)
2020-10-28 03:28:32 +00:00
{
2020-10-31 02:28:50 +00:00
error = errno;
2020-10-28 03:28:32 +00:00
*sense = true;
}
if((camccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
{
2020-10-31 02:28:50 +00:00
*sense = true;
*sense_buffer = malloc(1);
2020-10-28 03:28:32 +00:00
(*sense_buffer)[0] = camccb->csio.scsi_status;
}
if((camccb->ccb_h.status & CAM_AUTOSNS_VALID) && camccb->csio.sense_len - camccb->csio.sense_resid > 0)
{
2020-10-31 02:28:50 +00:00
*sense = (camccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR;
*sense_buffer = malloc(camccb->csio.sense_len - camccb->csio.sense_resid);
2020-10-28 03:28:32 +00:00
(*sense_buffer)[0] = camccb->csio.sense_data.error_code;
2024-04-30 15:42:08 +01:00
memcpy((*sense_buffer) + 1, camccb->csio.sense_data.sense_buf,
2020-10-31 02:28:50 +00:00
(camccb->csio.sense_len - camccb->csio.sense_resid) - 1);
2020-10-28 03:28:32 +00:00
}
2020-10-31 02:11:53 +00:00
cam_freeccb(camccb);
2020-10-28 03:28:32 +00:00
*buf_len = camccb->csio.dxfer_len;
return error;
2020-10-26 01:11:00 +00:00
}