Page MenuHomeFreeBSD

D7373.diff
No OneTemporary

D7373.diff

Index: usr.sbin/camdd/camdd.c
===================================================================
--- usr.sbin/camdd/camdd.c
+++ usr.sbin/camdd/camdd.c
@@ -84,6 +84,8 @@
#include <camlib.h>
#include <mtlib.h>
#include <zlib.h>
+#include <cam/ata/ata_all.h>
+#include <cam/cam_ccb.h>
typedef enum {
CAMDD_CMD_NONE = 0x00000000,
@@ -105,6 +107,25 @@
CAMDD_ARG_RETRIES = 0x00000100
} camdd_argmask;
+
+typedef enum {
+ ADA_FLAG_CAN_48BIT = 0x0002,
+ ADA_FLAG_CAN_FLUSHCACHE = 0x0004,
+ ADA_FLAG_CAN_NCQ = 0x0008,
+ ADA_FLAG_CAN_DMA = 0x0010,
+ ADA_FLAG_NEED_OTAG = 0x0020,
+ ADA_FLAG_WAS_OTAG = 0x0040,
+ ADA_FLAG_CAN_TRIM = 0x0080,
+ ADA_FLAG_OPEN = 0x0100,
+ ADA_FLAG_SCTX_INIT = 0x0200,
+ ADA_FLAG_CAN_CFA = 0x0400,
+ ADA_FLAG_CAN_POWERMGT = 0x0800,
+ ADA_FLAG_CAN_DMA48 = 0x1000,
+ ADA_FLAG_DIRTY = 0x2000,
+ ADA_FLAG_CAN_NCQ_TRIM = 0x4000, /* CAN_TRIM also set */
+ ADA_FLAG_PIM_CAN_NCQ_TRIM = 0x8000
+} ada_flags;
+
typedef enum {
CAMDD_DEV_NONE = 0x00,
CAMDD_DEV_PASS = 0x01,
@@ -259,7 +280,9 @@
#define NUM_DEV_TYPES 2
struct camdd_dev_pass {
- int scsi_dev_type;
+ int scsi_dev_type;
+ int protocol;
+ ada_flags ada_flags;
struct cam_device *dev;
uint64_t max_sector;
uint32_t block_len;
@@ -467,7 +490,7 @@
struct kevent *new_ke, int num_ke,
int retry_count, int timeout);
static struct camdd_buf *camdd_alloc_buf(struct camdd_dev *dev,
- camdd_buf_type buf_type);
+ camdd_buf_type buf_type);
void camdd_release_buf(struct camdd_buf *buf);
struct camdd_buf *camdd_get_buf(struct camdd_dev *dev, camdd_buf_type buf_type);
int camdd_buf_sg_create(struct camdd_buf *buf, int iovec,
@@ -477,6 +500,20 @@
void camdd_buf_add_child(struct camdd_buf *buf, struct camdd_buf *child_buf);
int camdd_probe_tape(int fd, char *filename, uint64_t *max_iosize,
uint64_t *max_blk, uint64_t *min_blk, uint64_t *blk_gran);
+uint64_t max_sector(int is48bit, struct ata_params *parm);
+int camdd_probe_pass_scsi(struct cam_device *cam_dev, union ccb *ccb,
+ int probe_retry_count, camdd_argmask arglist,
+ int probe_timeout, uint64_t *maxsector, uint32_t *block_len);
+int camdd_probe_pass_ata(struct cam_device *cam_dev, union ccb *ccb,
+ camdd_argmask arglist, int probe_retry_count,
+ int probe_timeout, uint8_t command, ada_flags ada_flags,
+ uint64_t *maxsector, uint32_t *block_len);
+void set_flags(ada_flags *flags, struct ccb_getdev *cgd);
+int ata_do_cmd(union ccb *ccb, int retries,
+ u_int32_t flags, u_int8_t tag_action,
+ u_int8_t command, u_int8_t features, u_int32_t lba,
+ u_int16_t sector_count, u_int8_t *data_ptr, size_t dxfer_len,
+ int timeout, ada_flags ada_flags);
struct camdd_dev *camdd_probe_file(int fd, struct camdd_io_opts *io_opts,
int retry_count, int timeout);
struct camdd_dev *camdd_probe_pass(struct cam_device *cam_dev,
@@ -485,7 +522,8 @@
int probe_timeout, int io_retry_count,
int io_timeout);
void *camdd_file_worker(void *arg);
-camdd_buf_status camdd_ccb_status(union ccb *ccb);
+camdd_buf_status camdd_ccb_status(union ccb *ccb, int protocol);
+int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
int camdd_queue_peer_buf(struct camdd_dev *dev, struct camdd_buf *buf);
int camdd_complete_peer_buf(struct camdd_dev *dev, struct camdd_buf *peer_buf);
void camdd_peer_done(struct camdd_buf *buf);
@@ -1252,59 +1290,125 @@
return (NULL);
}
+
/*
- * Need to implement this. Do a basic probe:
- * - Check the inquiry data, make sure we're talking to a device that we
- * can reasonably expect to talk to -- direct, RBC, CD, WORM.
- * - Send a test unit ready, make sure the device is available.
- * - Get the capacity and block size.
- */
-struct camdd_dev *
-camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts,
- camdd_argmask arglist, int probe_retry_count,
- int probe_timeout, int io_retry_count, int io_timeout)
+ * * Get a get device CCB for the specified device.
+ * */
+int
+get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
{
union ccb *ccb;
- uint64_t maxsector;
- uint32_t cpi_maxio, max_iosize, pass_numblocks;
- uint32_t block_len;
- struct scsi_read_capacity_data rcap;
- struct scsi_read_capacity_data_long rcaplong;
- struct camdd_dev *dev;
- struct camdd_dev_pass *pass_dev;
- struct kevent ke;
- int scsi_dev_type;
+ int retval = 0;
- dev = NULL;
+ ccb = cam_getccb(device);
- scsi_dev_type = SID_TYPE(&cam_dev->inq_data);
- maxsector = 0;
- block_len = 0;
+ if (ccb == NULL) {
+ warnx("get_cgd: couldn't allocate CCB");
+ return 1;
+ }
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
+ ccb->ccb_h.func_code = XPT_GDEV_TYPE;
- /*
- * For devices that support READ CAPACITY, we'll attempt to get the
- * capacity. Otherwise, we really don't support tape or other
- * devices via SCSI passthrough, so just return an error in that case.
- */
- switch (scsi_dev_type) {
- case T_DIRECT:
- case T_WORM:
- case T_CDROM:
- case T_OPTICAL:
- case T_RBC:
- case T_ZBC_HM:
- break;
- default:
- errx(1, "Unsupported SCSI device type %d", scsi_dev_type);
- break; /*NOTREACHED*/
+ if (cam_send_ccb(device, ccb) < 0) {
+ warn("get_cgd: error sending Path Inquiry CCB");
+ cam_error_print(device, ccb, CAM_ESF_ALL,
+ CAM_EPF_ALL, stderr);
+ retval = 1;
+ goto get_cgd_bailout;
}
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ cam_error_print(device, ccb, CAM_ESF_ALL,
+ CAM_EPF_ALL, stderr);
+ retval = 1;
+ goto get_cgd_bailout;
+ }
+ bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
+get_cgd_bailout:
- ccb = cam_getccb(cam_dev);
+ cam_freeccb(ccb);
- if (ccb == NULL) {
- warnx("%s: error allocating ccb", __func__);
- goto bailout;
+ return retval;
+}
+
+void
+set_flags(ada_flags *flags, struct ccb_getdev *cgd)
+{
+ if ((cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA) &&
+ (cgd->inq_flags & SID_DMA))
+ *flags |= ADA_FLAG_CAN_DMA;
+ else
+ *flags &= ~ADA_FLAG_CAN_DMA;
+
+ if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) {
+ *flags |= ADA_FLAG_CAN_48BIT;
+ if (cgd->inq_flags & SID_DMA48)
+ *flags |= ADA_FLAG_CAN_DMA48;
+ else
+ *flags &= ~ADA_FLAG_CAN_DMA48;
+ } else
+ *flags &= ~(ADA_FLAG_CAN_48BIT | ADA_FLAG_CAN_DMA48);
+
+ if ((cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ) &&
+ (cgd->inq_flags & SID_DMA) && (cgd->inq_flags & SID_CmdQue))
+ *flags |= ADA_FLAG_CAN_NCQ;
+ else
+ *flags &= ~ADA_FLAG_CAN_NCQ;
+}
+
+int
+ata_do_cmd(union ccb *ccb, int retries,
+ u_int32_t flags, u_int8_t tag_action,
+ u_int8_t command, u_int8_t features, u_int32_t lba,
+ u_int16_t sector_count, u_int8_t *data_ptr, size_t dxfer_len,
+ int timeout, ada_flags ada_flags)
+{
+
+ cam_fill_ataio(&ccb->ataio,
+ /*retries*/ retries,
+ /*cbfcnp*/ NULL,
+ /*flags*/ flags,
+ /*tag_action*/ tag_action,
+ /*data_ptr*/ data_ptr,
+ /*dxfer_len*/ dxfer_len,
+ /*timeout*/ timeout);
+
+ if (ada_flags & ADA_FLAG_CAN_48BIT && lba + sector_count >= ATA_MAX_28BIT_LBA) {
+ ata_48bit_cmd(&ccb->ataio, command, features, lba,
+ sector_count);
+
+ }
+ else if (ada_flags & ATA_SUPPORT_NCQ) {
+ ata_ncq_cmd(&ccb->ataio, command, lba,
+ sector_count);
}
+ else {
+ ata_28bit_cmd(&ccb->ataio, command, features, lba,
+ sector_count);
+ }
+ return 0;
+}
+
+uint64_t
+max_sector(int is48bit, struct ata_params *parm)
+{
+ if (is48bit)
+ return ((u_int64_t)parm->lba_size48_1 |
+ ((u_int64_t)parm->lba_size48_2 << 16) |
+ ((u_int64_t)parm->lba_size48_3 << 32) |
+ ((u_int64_t)parm->lba_size48_4 << 48));
+ else
+ return ((u_int32_t)parm->lba_size_1 |
+ ((u_int32_t)parm->lba_size_2 << 16));
+}
+
+int
+camdd_probe_pass_scsi(struct cam_device *cam_dev, union ccb *ccb, int probe_retry_count,
+ camdd_argmask arglist, int probe_timeout,
+ uint64_t *maxsector, uint32_t *block_len)
+{
+ struct scsi_read_capacity_data rcap;
+ struct scsi_read_capacity_data_long rcaplong;
CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
@@ -1327,7 +1431,6 @@
cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
-
goto bailout;
}
@@ -1336,28 +1439,28 @@
goto bailout;
}
- maxsector = scsi_4btoul(rcap.addr);
- block_len = scsi_4btoul(rcap.length);
+ *maxsector = scsi_4btoul(rcap.addr);
+ *block_len = scsi_4btoul(rcap.length);
/*
* A last block of 2^32-1 means that the true capacity is over 2TB,
* and we need to issue the long READ CAPACITY to get the real
* capacity. Otherwise, we're all set.
*/
- if (maxsector != 0xffffffff)
- goto rcap_done;
+ if (*maxsector != 0xffffffff)
+ return 0;
scsi_read_capacity_16(&ccb->csio,
- /*retries*/ probe_retry_count,
- /*cbfcnp*/ NULL,
- /*tag_action*/ MSG_SIMPLE_Q_TAG,
- /*lba*/ 0,
- /*reladdr*/ 0,
- /*pmi*/ 0,
- (uint8_t *)&rcaplong,
- sizeof(rcaplong),
- /*sense_len*/ SSD_FULL_SIZE,
- /*timeout*/ probe_timeout ? probe_timeout : 5000);
+ /*retries*/ probe_retry_count,
+ /*cbfcnp*/ NULL,
+ /*tag_action*/ MSG_SIMPLE_Q_TAG,
+ /*lba*/ 0,
+ /*reladdr*/ 0,
+ /*pmi*/ 0,
+ (uint8_t *)&rcaplong,
+ sizeof(rcaplong),
+ /*sense_len*/ SSD_FULL_SIZE,
+ /*timeout*/ probe_timeout ? probe_timeout : 5000);
/* Disable freezing the device queue */
ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
@@ -1377,14 +1480,156 @@
goto bailout;
}
- maxsector = scsi_8btou64(rcaplong.addr);
- block_len = scsi_4btoul(rcaplong.length);
+ *maxsector = scsi_8btou64(rcaplong.addr);
+ *block_len = scsi_4btoul(rcaplong.length);
+ return 0;
+bailout:
+ return -1;
+}
+
+int
+camdd_probe_pass_ata(struct cam_device *cam_dev, union ccb *ccb,
+ camdd_argmask arglist, int probe_retry_count,
+ int probe_timeout, uint8_t command, ada_flags ada_flags,
+ uint64_t *maxsector, uint32_t *block_len)
+{
+ int16_t *ptr = NULL;
+ size_t dxfer_len = 0;
+ int retval;
+ struct ata_params *parm;
+
+ dxfer_len = sizeof(struct ata_params);
+ ptr = (uint16_t *)malloc(dxfer_len);
+ if (ptr == NULL) {
+ warnx("can't malloc memory for identify");
+ retval = -1;
+ goto bailout;
+ }
+ bzero(ptr, dxfer_len);
+
+ /* Use the ATA CMDS directly instead of ATA_SCSI Passthrough.*/
+ bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
+ sizeof(struct ccb_hdr));
+ ata_do_cmd(ccb,
+ /*retries*/probe_retry_count,
+ /*flags*/CAM_DIR_IN,
+ /*tag_action*/MSG_SIMPLE_Q_TAG,
+ /*command*/command,
+ /*features*/0,
+ /*lba*/0,
+ /*sector_count*/sizeof(struct ata_params),
+ /*data_ptr*/(u_int8_t *)ptr,
+ /*dxfer_len*/dxfer_len,
+ /*timeout*/probe_timeout ? probe_timeout : 5000,
+ /*ada_flags*/ada_flags);
+
+ if (arglist & CAMDD_ARG_ERR_RECOVER)
+ ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
+
+ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+ retval = cam_send_ccb(cam_dev, ccb);
+
+ if (retval != 0) {
+ warn("error sending ATA_IDENTIFY CCB");
+ retval = -1;
+ goto bailout;
+ }
+
+ parm = (struct ata_params *)(ptr);
+ *block_len = (unsigned long)ata_physical_sector_size(parm);
+ *maxsector = max_sector(ada_flags & ADA_FLAG_CAN_48BIT, parm);
+ retval = 0;
+bailout:
+ return retval;
+}
+
+
+/*
+ * Need to implement this. Do a basic probe:
+ * - Check the inquiry data, make sure we're talking to a device that we
+ * can reasonably expect to talk to -- direct, RBC, CD, WORM.
+ * - Send a test unit ready, make sure the device is available.
+ * - Get the capacity and block size.
+ */
+struct camdd_dev *
+camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts,
+ camdd_argmask arglist, int probe_retry_count,
+ int probe_timeout, int io_retry_count, int io_timeout)
+{
+ union ccb *ccb;
+ uint64_t maxsector = 0;
+ uint32_t cpi_maxio, max_iosize, pass_numblocks;
+ uint32_t block_len = 0;
+ struct camdd_dev *dev = NULL;
+ struct camdd_dev_pass *pass_dev;
+ struct kevent ke;
+ struct ccb_getdev cgd;
+ int retval;
+ ada_flags ada_flags = 0;
+ uint8_t command;
+ int scsi_dev_type;
+
+ if ((retval = get_cgd(cam_dev, &cgd)) != 0) {
+ warnx("couldn't get CGD");
+ return (NULL);
+ }
+
+ if ((ccb = cam_getccb(cam_dev)) == NULL) {
+ warnx("Could not allocate CCB");
+ retval = -1;
+ goto bailout_error;
+ }
+
+ switch(cgd.protocol) {
+ case PROTO_SCSI:
+ scsi_dev_type = SID_TYPE(&cam_dev->inq_data);
+
+ /*
+ * For devices that support READ CAPACITY, we'll attempt to get the
+ * capacity. Otherwise, we really don't support tape or other
+ * devices via SCSI passthrough, so just return an error in that case.
+ */
+ switch (scsi_dev_type) {
+ case T_DIRECT:
+ case T_WORM:
+ case T_CDROM:
+ case T_OPTICAL:
+ case T_RBC:
+ break;
+
+ default:
+ errx(1, "Unsupported SCSI device type %d", scsi_dev_type);
+ break; /*NOTREACHED*/
+ } /*SWitch scsi_dev_type*/
+
+
+ if ((retval = camdd_probe_pass_scsi(cam_dev, ccb, probe_retry_count,
+ arglist, probe_timeout, &maxsector, &block_len))) {
+ goto bailout;
+ }
+ break;
+ case PROTO_ATA:
+ case PROTO_ATAPI:
+
+ command = (cgd.protocol == PROTO_ATA) ?
+ ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY;
+
+ set_flags(&ada_flags, &cgd);
+
+ if ((retval = camdd_probe_pass_ata(cam_dev, ccb, arglist, probe_retry_count,
+ probe_timeout, command, ada_flags, &maxsector, &block_len))) {
+ goto bailout;
+ }
+ break; /* switch ATA */
+ default:
+ errx(1, "Unsupported PROTO type %d", cgd.protocol);
+ break; /*NOTREACHED*/
+ } /*switch cgd.protocol */
-rcap_done:
if (block_len == 0) {
warnx("Sector size for %s%u is 0, cannot continue",
- cam_dev->device_name, cam_dev->dev_unit_num);
- goto bailout_error;
+ cam_dev->device_name, cam_dev->dev_unit_num);
+ goto bailout;
}
CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
@@ -1392,7 +1637,7 @@
ccb->ccb_h.func_code = XPT_PATH_INQ;
ccb->ccb_h.flags = CAM_DIR_NONE;
ccb->ccb_h.retry_count = 1;
-
+
if (cam_send_ccb(cam_dev, ccb) < 0) {
warn("error sending XPT_PATH_INQ CCB");
@@ -1410,12 +1655,14 @@
pass_dev = &dev->dev_spec.pass;
pass_dev->scsi_dev_type = scsi_dev_type;
+ pass_dev->protocol = cgd.protocol;
+ pass_dev->ada_flags = ada_flags;
pass_dev->dev = cam_dev;
pass_dev->max_sector = maxsector;
pass_dev->block_len = block_len;
pass_dev->cpi_maxio = ccb->cpi.maxio;
snprintf(dev->device_name, sizeof(dev->device_name), "%s%u",
- pass_dev->dev->device_name, pass_dev->dev->dev_unit_num);
+ pass_dev->dev->device_name, pass_dev->dev->dev_unit_num);
dev->sector_size = block_len;
dev->max_sector = maxsector;
@@ -1720,46 +1967,68 @@
* Simplistic translation of CCB status to our local status.
*/
camdd_buf_status
-camdd_ccb_status(union ccb *ccb)
+camdd_ccb_status(union ccb *ccb, int protocol)
{
camdd_buf_status status = CAMDD_STATUS_NONE;
cam_status ccb_status;
ccb_status = ccb->ccb_h.status & CAM_STATUS_MASK;
- switch (ccb_status) {
- case CAM_REQ_CMP: {
- if (ccb->csio.resid == 0) {
- status = CAMDD_STATUS_OK;
- } else if (ccb->csio.dxfer_len > ccb->csio.resid) {
- status = CAMDD_STATUS_SHORT_IO;
- } else {
- status = CAMDD_STATUS_EOF;
+ if (protocol == PROTO_SCSI) {
+ switch (ccb_status) {
+ case CAM_REQ_CMP: {
+
+ if (ccb->csio.resid == 0) {
+ status = CAMDD_STATUS_OK;
+ } else if (ccb->csio.dxfer_len > ccb->csio.resid) {
+ status = CAMDD_STATUS_SHORT_IO;
+ } else {
+ status = CAMDD_STATUS_EOF;
+ }
+ break;
+ }
+ case CAM_SCSI_STATUS_ERROR: {
+ switch (ccb->csio.scsi_status) {
+ case SCSI_STATUS_OK:
+ case SCSI_STATUS_COND_MET:
+ case SCSI_STATUS_INTERMED:
+ case SCSI_STATUS_INTERMED_COND_MET:
+ status = CAMDD_STATUS_OK;
+ break;
+ case SCSI_STATUS_CMD_TERMINATED:
+ case SCSI_STATUS_CHECK_COND:
+ case SCSI_STATUS_QUEUE_FULL:
+ case SCSI_STATUS_BUSY:
+ case SCSI_STATUS_RESERV_CONFLICT:
+ default:
+ status = CAMDD_STATUS_ERROR;
+ break;
+ }
+ break;
+ }
+ default:
+ status = CAMDD_STATUS_ERROR;
+ break;
}
- break;
}
- case CAM_SCSI_STATUS_ERROR: {
- switch (ccb->csio.scsi_status) {
- case SCSI_STATUS_OK:
- case SCSI_STATUS_COND_MET:
- case SCSI_STATUS_INTERMED:
- case SCSI_STATUS_INTERMED_COND_MET:
- status = CAMDD_STATUS_OK;
- break;
- case SCSI_STATUS_CMD_TERMINATED:
- case SCSI_STATUS_CHECK_COND:
- case SCSI_STATUS_QUEUE_FULL:
- case SCSI_STATUS_BUSY:
- case SCSI_STATUS_RESERV_CONFLICT:
- default:
- status = CAMDD_STATUS_ERROR;
- break;
+ else {
+
+ switch(ccb_status) {
+ case CAM_REQ_CMP: {
+
+ if (ccb->ataio.resid == 0) {
+ status = CAMDD_STATUS_OK;
+ } else if (ccb->ataio.dxfer_len > ccb->ataio.resid) {
+ status = CAMDD_STATUS_SHORT_IO;
+ } else {
+ status = CAMDD_STATUS_EOF;
+ }
+ break;
+ }
+ default:
+ status = CAMDD_STATUS_ERROR;
+ break;
}
- break;
- }
- default:
- status = CAMDD_STATUS_ERROR;
- break;
}
return (status);
@@ -2154,11 +2423,17 @@
CAM_EPF_ALL, stderr);
}
- data->resid = ccb.csio.resid;
- dev->bytes_transferred += (ccb.csio.dxfer_len - ccb.csio.resid);
+ if (pass_dev->protocol == PROTO_SCSI) {
+ data->resid = ccb.csio.resid;
+ dev->bytes_transferred += (ccb.csio.dxfer_len - ccb.csio.resid);
+ }
+ else {
+ data->resid = ccb.ataio.resid;
+ dev->bytes_transferred += (ccb.ataio.dxfer_len - ccb.ataio.resid);
+ }
if (buf->status == CAMDD_STATUS_NONE)
- buf->status = camdd_ccb_status(&ccb);
+ buf->status = camdd_ccb_status(&ccb, pass_dev->protocol);
if (buf->status == CAMDD_STATUS_ERROR)
error_count++;
else if (buf->status == CAMDD_STATUS_EOF) {
@@ -2220,7 +2495,7 @@
*/
if (write_dev != 0) {
retval = camdd_buf_sg_create(buf, /*iovec*/ 1,
- dev->sector_size, &num_sectors, &double_buf_needed);
+ dev->sector_size, &num_sectors, &double_buf_needed);
if (retval != 0) {
no_resources = 1;
goto bailout;
@@ -2412,6 +2687,7 @@
union ccb *ccb;
int retval = 0, is_write = dev->write_dev;
int double_buf_needed = 0;
+ uint8_t command;
buf = STAILQ_FIRST(&dev->run_queue);
if (buf == NULL) {
@@ -2438,7 +2714,6 @@
data = &buf->buf_type_spec.data;
ccb = &data->ccb;
- CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
/*
* In almost every case the number of blocks should be the device
@@ -2450,33 +2725,100 @@
else
num_blocks = data->fill_len / pass_dev->block_len;
- scsi_read_write(&ccb->csio,
+ if(data->fill_len == 0 ) {
+ retval = -1;
+ goto bailout;
+ }
+
+ if (pass_dev->protocol == PROTO_SCSI) {
+ CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
+
+ scsi_read_write(&ccb->csio,
/*retries*/ dev->retry_count,
/*cbfcnp*/ NULL,
/*tag_action*/ MSG_SIMPLE_Q_TAG,
/*readop*/ (dev->write_dev == 0) ? SCSI_RW_READ :
- SCSI_RW_WRITE,
+ SCSI_RW_WRITE,
/*byte2*/ 0,
/*minimum_cmd_size*/ dev->min_cmd_size,
/*lba*/ buf->lba,
/*block_count*/ num_blocks,
/*data_ptr*/ (data->sg_count != 0) ?
- (uint8_t *)data->segs : data->buf,
+ (uint8_t *)data->segs : data->buf,
/*dxfer_len*/ (num_blocks * pass_dev->block_len),
/*sense_len*/ SSD_FULL_SIZE,
/*timeout*/ dev->io_timeout);
+ if (data->sg_count != 0) {
+ ccb->ccb_h.flags |= CAM_DATA_SG;
+ ccb->csio.sglist_cnt = data->sg_count;
+ }
+ }
+ else {
+
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
+
+ if (pass_dev->ada_flags & ATA_SUPPORT_NCQ) {
+ if (is_write == 0) {
+ command = ATA_READ_FPDMA_QUEUED;
+ } else {
+ command = ATA_WRITE_FPDMA_QUEUED;
+ }
+ } else if ((pass_dev->ada_flags & ADA_FLAG_CAN_48BIT) &&
+ (buf->lba + num_blocks >= ATA_MAX_28BIT_LBA ||
+ num_blocks > 256)) {
+ if (pass_dev->ada_flags & ADA_FLAG_CAN_DMA48) {
+ if (is_write == 0) {
+ command = ATA_READ_DMA48;
+ } else {
+ command = ATA_WRITE_DMA48;
+ }
+ } else {
+ if (is_write == 0) {
+ command = ATA_READ_MUL48;
+ } else {
+ command = ATA_WRITE_MUL48;
+ }
+ }
+ }
+ else {
+ if (pass_dev->ada_flags & ADA_FLAG_CAN_DMA) {
+ if (is_write == 0) {
+ command = ATA_READ_DMA;
+ } else {
+ command = ATA_WRITE_DMA;
+ }
+ } else {
+ if (is_write == 0) {
+ command = ATA_READ_MUL;
+ } else {
+ command = ATA_WRITE_MUL;
+ }
+ }
+ }
+
+ ata_do_cmd(ccb,
+ /*retries*/dev->retry_count,
+ /*flags*/(is_write == 0) ? CAM_DIR_IN : CAM_DIR_OUT,
+ /*tag_action*/CAM_TAG_ACTION_NONE,
+ /*command*/command,
+ /*features*/0,
+ /*lba*/buf->lba,
+ /*sector_count*/num_blocks,
+ /*data_ptr*/(data->sg_count != 0) ?
+ (uint8_t *)data->segs : data->buf,
+ /*dxfer_len*/num_blocks * pass_dev->block_len,
+ /*timeout*/dev->io_timeout,
+ /*adaflags*/pass_dev->ada_flags);
+ }
+
/* Disable freezing the device queue */
ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
if (dev->retry_count != 0)
ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
- if (data->sg_count != 0) {
- ccb->csio.sglist_cnt = data->sg_count;
- ccb->ccb_h.flags |= CAM_DATA_SG;
- }
-
/*
* Store a pointer to the buffer in the CCB. The kernel will
* restore this when we get it back, and we'll use it to identify
@@ -2495,7 +2837,7 @@
pthread_mutex_lock(&dev->mutex);
warn("%s: error sending CAMIOQUEUE ioctl to %s%u", __func__,
- pass_dev->dev->device_name, pass_dev->dev->dev_unit_num);
+ pass_dev->dev->device_name, pass_dev->dev->dev_unit_num);
warn("%s: CCB address is %p", __func__, ccb);
retval = -1;
@@ -3049,12 +3391,12 @@
}
devs[i] = camdd_probe_pass(new_cam_dev,
- /*io_opts*/ &io_opts[i],
- CAMDD_ARG_ERR_RECOVER,
- /*probe_retry_count*/ 3,
- /*probe_timeout*/ 5000,
- /*io_retry_count*/ retry_count,
- /*io_timeout*/ timeout);
+ /*io_opts*/ &io_opts[i],
+ CAMDD_ARG_ERR_RECOVER,
+ /*probe_retry_count*/ 3,
+ /*probe_timeout*/ 5000,
+ /*io_retry_count*/ retry_count,
+ /*io_timeout*/ timeout);
if (devs[i] == NULL) {
warn("Unable to probe device %s%u",
new_cam_dev->device_name,
@@ -3089,7 +3431,7 @@
}
devs[i] = camdd_probe_file(fd, &io_opts[i],
- retry_count, timeout);
+ retry_count, timeout);
if (devs[i] == NULL) {
error = 1;
goto bailout;
@@ -3114,10 +3456,6 @@
(devs[i]->start_offset_bytes /
devs[i]->sector_size) +
(max_io / devs[i]->sector_size) - 1;
- devs[i]->sector_io_limit =
- (devs[i]->start_offset_bytes /
- devs[i]->sector_size) +
- (max_io / devs[i]->sector_size) - 1;
}
devs[i]->next_io_pos_bytes = devs[i]->start_offset_bytes;

File Metadata

Mime Type
text/plain
Expires
Sat, Feb 22, 1:49 PM (1 h, 30 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16772622
Default Alt Text
D7373.diff (28 KB)

Event Timeline