Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153127317
D11230.id29687.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D11230.id29687.diff
View Options
Index: usr.sbin/camdd/camdd.c
===================================================================
--- usr.sbin/camdd/camdd.c
+++ usr.sbin/camdd/camdd.c
@@ -260,6 +260,7 @@
struct camdd_dev_pass {
int scsi_dev_type;
+ int protocol;
struct cam_device *dev;
uint64_t max_sector;
uint32_t block_len;
@@ -477,6 +478,9 @@
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);
+int camdd_probe_pass_scsi(struct cam_device *cam_dev, union ccb *ccb,
+ camdd_argmask arglist, int probe_retry_count,
+ int probe_timeout, uint64_t *maxsector, uint32_t *block_len);
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 +489,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);
@@ -1248,57 +1253,59 @@
}
/*
- * 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.
+ * Get a get device CCB for the specified device.
*/
-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)
+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;
+ union ccb *ccb;
+ int retval = 0;
- dev = NULL;
+ ccb = cam_getccb(device);
+
+ if (ccb == NULL) {
+ warnx("get_cgd: couldn't allocate CCB");
+ return 1;
+ }
- scsi_dev_type = SID_TYPE(&cam_dev->inq_data);
- maxsector = 0;
- block_len = 0;
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
+ ccb->ccb_h.func_code = XPT_GDEV_TYPE;
+
+ 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;
+ }
- /*
- * 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 ((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;
}
- ccb = cam_getccb(cam_dev);
+ bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
+
+get_cgd_bailout:
+ cam_freeccb(ccb);
+
+ return retval;
+}
+
+int
+camdd_probe_pass_scsi(struct cam_device *cam_dev, union ccb *ccb,
+ camdd_argmask arglist, int probe_retry_count,
+ int probe_timeout, uint64_t *maxsector, uint32_t *block_len)
+{
+ struct scsi_read_capacity_data rcap;
+ struct scsi_read_capacity_data_long rcaplong;
if (ccb == NULL) {
- warnx("%s: error allocating ccb", __func__);
- goto bailout;
+ warnx("%s: error passed ccb is NULL", __func__);
+ return -1;
}
CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
@@ -1323,59 +1330,130 @@
cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
- goto bailout;
+ return -1;
}
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
- goto bailout;
+ return -1;
}
- 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;
-
- 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);
+ if (*maxsector == 0xffffffff) {
+ 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);
+
+ /* Disable freezing the device queue */
+ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+
+ if (arglist & CAMDD_ARG_ERR_RECOVER)
+ ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
+
+ if (cam_send_ccb(cam_dev, ccb) < 0) {
+ warn("error sending READ CAPACITY (16) command");
+ cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
+ CAM_EPF_ALL, stderr);
+ return -1;
+ }
- /* Disable freezing the device queue */
- ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL,
+ stderr);
+ return -1;
+ }
- if (arglist & CAMDD_ARG_ERR_RECOVER)
- ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
+ *maxsector = scsi_8btou64(rcaplong.addr);
+ *block_len = scsi_4btoul(rcaplong.length);
+ }
- if (cam_send_ccb(cam_dev, ccb) < 0) {
- warn("error sending READ CAPACITY (16) command");
- cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
- CAM_EPF_ALL, stderr);
- goto bailout;
+ return 0;
+}
+
+/*
+ * 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;
+ int scsi_dev_type;
+
+ if ((retval = get_cgd(cam_dev, &cgd)) != 0) {
+ warnx("%s: error retrieving CGD", __func__);
+ return NULL;
}
- if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
+ ccb = cam_getccb(cam_dev);
+
+ if (ccb == NULL) {
+ warnx("%s: error allocating ccb", __func__);
goto bailout;
}
- maxsector = scsi_8btou64(rcaplong.addr);
- block_len = scsi_4btoul(rcaplong.length);
+ 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:
+ case T_ZBC_HM:
+ break;
+ default:
+ errx(1, "Unsupported SCSI device type %d", scsi_dev_type);
+ break; /*NOTREACHED*/
+ }
+
+ if ((retval = camdd_probe_pass_scsi(cam_dev, ccb, probe_retry_count,
+ arglist, probe_timeout, &maxsector,
+ &block_len))) {
+ goto bailout;
+ }
+ break;
+ default:
+ errx(1, "Unsupported PROTO type %d", cgd.protocol);
+ break; /*NOTREACHED*/
+ }
-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);
@@ -1405,6 +1483,7 @@
pass_dev = &dev->dev_spec.pass;
pass_dev->scsi_dev_type = scsi_dev_type;
+ pass_dev->protocol = cgd.protocol;
pass_dev->dev = cam_dev;
pass_dev->max_sector = maxsector;
pass_dev->block_len = block_len;
@@ -1715,43 +1794,50 @@
* 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;
+ switch (protocol) {
+ case 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;
}
- 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;
+ 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;
- 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;
@@ -2149,11 +2235,18 @@
CAM_EPF_ALL, stderr);
}
- data->resid = ccb.csio.resid;
- dev->bytes_transferred += (ccb.csio.dxfer_len - ccb.csio.resid);
+ switch (pass_dev->protocol) {
+ case PROTO_SCSI:
+ data->resid = ccb.csio.resid;
+ dev->bytes_transferred += (ccb.csio.dxfer_len - ccb.csio.resid);
+ break;
+ default:
+ return -1;
+ break;
+ }
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) {
@@ -2433,9 +2526,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
* block size. The exception may be at the end of an I/O stream
@@ -2446,21 +2536,36 @@
else
num_blocks = data->fill_len / pass_dev->block_len;
- 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,
- /*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,
- /*dxfer_len*/ (num_blocks * pass_dev->block_len),
- /*sense_len*/ SSD_FULL_SIZE,
- /*timeout*/ dev->io_timeout);
+ ccb = &data->ccb;
+
+ switch (pass_dev->protocol) {
+ case 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,
+ /*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,
+ /*dxfer_len*/ (num_blocks * pass_dev->block_len),
+ /*sense_len*/ SSD_FULL_SIZE,
+ /*timeout*/ dev->io_timeout);
+
+ if (data->sg_count != 0) {
+ ccb->csio.sglist_cnt = data->sg_count;
+ }
+ break;
+ default:
+ retval = -1;
+ goto bailout;
+ }
/* Disable freezing the device queue */
ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
@@ -2469,7 +2574,6 @@
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;
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 20, 8:39 AM (21 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31828587
Default Alt Text
D11230.id29687.diff (13 KB)
Attached To
Mode
D11230: Make camdd(8) protocol aware
Attached
Detach File
Event Timeline
Log In to Comment