summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-02-12 16:57:20 +0000
committerkib <kib@FreeBSD.org>2013-02-12 16:57:20 +0000
commitbd7f0fa0bb4b7b0f87227e0c4d49a4bd9b113cf0 (patch)
treee550f2c754f1edf951a8b93963ebcfc4fa0d20ce /sys/cam
parente0a463e76c719f11788ec107b5aa3e2da4e57c0b (diff)
downloadFreeBSD-src-bd7f0fa0bb4b7b0f87227e0c4d49a4bd9b113cf0.zip
FreeBSD-src-bd7f0fa0bb4b7b0f87227e0c4d49a4bd9b113cf0.tar.gz
Reform the busdma API so that new types may be added without modifying
every architecture's busdma_machdep.c. It is done by unifying the bus_dmamap_load_buffer() routines so that they may be called from MI code. The MD busdma is then given a chance to do any final processing in the complete() callback. The cam changes unify the bus_dmamap_load* handling in cam drivers. The arm and mips implementations are updated to track virtual addresses for sync(). Previously this was done in a type specific way. Now it is done in a generic way by recording the list of virtuals in the map. Submitted by: jeff (sponsored by EMC/Isilon) Reviewed by: kan (previous version), scottl, mjacob (isp(4), no objections for target mode changes) Discussed with: ian (arm changes) Tested by: marius (sparc64), mips (jmallet), isci(4) on x86 (jharris), amd64 (Fabian Keil <freebsd-listen@fabiankeil.de>)
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/cam_ccb.h10
-rw-r--r--sys/cam/cam_xpt.c3
-rw-r--r--sys/cam/ctl/ctl_frontend_cam_sim.c47
-rw-r--r--sys/cam/ctl/scsi_ctl.c10
-rw-r--r--sys/cam/scsi/scsi_pass.c5
-rw-r--r--sys/cam/scsi/scsi_target.c2
6 files changed, 43 insertions, 34 deletions
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 1f12d91..a80880a 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -64,13 +64,19 @@ typedef enum {
* Perform transport negotiation
* with this command.
*/
- CAM_SCATTER_VALID = 0x00000010,/* Scatter/gather list is valid */
+ CAM_DATA_ISPHYS = 0x00000010,/* Data type with physical addrs */
CAM_DIS_AUTOSENSE = 0x00000020,/* Disable autosense feature */
CAM_DIR_BOTH = 0x00000000,/* Data direction (00:IN/OUT) */
CAM_DIR_IN = 0x00000040,/* Data direction (01:DATA IN) */
CAM_DIR_OUT = 0x00000080,/* Data direction (10:DATA OUT) */
CAM_DIR_NONE = 0x000000C0,/* Data direction (11:no data) */
CAM_DIR_MASK = 0x000000C0,/* Data direction Mask */
+ CAM_DATA_VADDR = 0x00000000,/* Data type (000:Virtual) */
+ CAM_DATA_PADDR = 0x00000010,/* Data type (001:Physical) */
+ CAM_DATA_SG = 0x00040000,/* Data type (010:sglist) */
+ CAM_DATA_SG_PADDR = 0x00040010,/* Data type (011:sglist phys) */
+ CAM_DATA_BIO = 0x00200000,/* Data type (100:bio) */
+ CAM_DATA_MASK = 0x00240010,/* Data type mask */
CAM_SOFT_RST_OP = 0x00000100,/* Use Soft reset alternative */
CAM_ENG_SYNC = 0x00000200,/* Flush resid bytes on complete */
CAM_DEV_QFRZDIS = 0x00000400,/* Disable DEV Q freezing */
@@ -81,10 +87,8 @@ typedef enum {
CAM_TAG_ACTION_VALID = 0x00008000,/* Use the tag action in this ccb*/
CAM_PASS_ERR_RECOVER = 0x00010000,/* Pass driver does err. recovery*/
CAM_DIS_DISCONNECT = 0x00020000,/* Disable disconnect */
- CAM_SG_LIST_PHYS = 0x00040000,/* SG list has physical addrs. */
CAM_MSG_BUF_PHYS = 0x00080000,/* Message buffer ptr is physical*/
CAM_SNS_BUF_PHYS = 0x00100000,/* Autosense data ptr is physical*/
- CAM_DATA_PHYS = 0x00200000,/* SG/Buffer data ptrs are phys. */
CAM_CDB_PHYS = 0x00400000,/* CDB poiner is physical */
CAM_ENG_SGLIST = 0x00800000,/* SG list is for the HBA engine */
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 304d8c7..6bda94d 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -547,7 +547,8 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
* We can't deal with physical addresses for this
* type of transaction.
*/
- if (inccb->ccb_h.flags & CAM_DATA_PHYS) {
+ if ((inccb->ccb_h.flags & CAM_DATA_MASK) !=
+ CAM_DATA_VADDR) {
error = EINVAL;
break;
}
diff --git a/sys/cam/ctl/ctl_frontend_cam_sim.c b/sys/cam/ctl/ctl_frontend_cam_sim.c
index 43e4d61d..b885cbf 100644
--- a/sys/cam/ctl/ctl_frontend_cam_sim.c
+++ b/sys/cam/ctl/ctl_frontend_cam_sim.c
@@ -93,8 +93,8 @@ struct cfcs_softc {
* handle physical addresses yet. That would require mapping things in
* order to do the copy.
*/
-#define CFCS_BAD_CCB_FLAGS (CAM_DATA_PHYS | CAM_SG_LIST_PHYS | \
- CAM_MSG_BUF_PHYS | CAM_SNS_BUF_PHYS | CAM_CDB_PHYS | CAM_SENSE_PTR |\
+#define CFCS_BAD_CCB_FLAGS (CAM_DATA_ISPHYS | CAM_MSG_BUF_PHYS | \
+ CAM_SNS_BUF_PHYS | CAM_CDB_PHYS | CAM_SENSE_PTR | \
CAM_SENSE_PHYS)
int cfcs_init(void);
@@ -379,36 +379,35 @@ cfcs_datamove(union ctl_io *io)
* Simplify things on both sides by putting single buffers into a
* single entry S/G list.
*/
- if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
- if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) {
- /* We should filter this out on entry */
- panic("%s: physical S/G list, should not get here",
- __func__);
- } else {
- int len_seen;
-
- cam_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr;
- cam_sg_count = ccb->csio.sglist_cnt;
-
- for (i = 0, len_seen = 0; i < cam_sg_count; i++) {
- if ((len_seen + cam_sglist[i].ds_len) >=
- io->scsiio.kern_rel_offset) {
- cam_sg_start = i;
- cam_sg_offset =
- io->scsiio.kern_rel_offset -
- len_seen;
- break;
- }
- len_seen += cam_sglist[i].ds_len;
+ switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) {
+ case CAM_DATA_SG: {
+ int len_seen;
+
+ cam_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr;
+ cam_sg_count = ccb->csio.sglist_cnt;
+
+ for (i = 0, len_seen = 0; i < cam_sg_count; i++) {
+ if ((len_seen + cam_sglist[i].ds_len) >=
+ io->scsiio.kern_rel_offset) {
+ cam_sg_start = i;
+ cam_sg_offset = io->scsiio.kern_rel_offset -
+ len_seen;
+ break;
}
+ len_seen += cam_sglist[i].ds_len;
}
- } else {
+ break;
+ }
+ case CAM_DATA_VADDR:
cam_sglist = &cam_sg_entry;
cam_sglist[0].ds_len = ccb->csio.dxfer_len;
cam_sglist[0].ds_addr = (bus_addr_t)ccb->csio.data_ptr;
cam_sg_count = 1;
cam_sg_start = 0;
cam_sg_offset = io->scsiio.kern_rel_offset;
+ break;
+ default:
+ panic("Invalid CAM flags %#x", ccb->ccb_h.flags);
}
if (io->scsiio.kern_sg_entries > 0) {
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index 5dc20e5..e9af881 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -876,6 +876,7 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
csio->cdb_len = atio->cdb_len;
+ flags &= ~CAM_DATA_MASK;
if (io->scsiio.kern_sg_entries == 0) {
/* No S/G list */
data_ptr = io->scsiio.kern_data_ptr;
@@ -883,7 +884,9 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
csio->sglist_cnt = 0;
if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
- flags |= CAM_DATA_PHYS;
+ flags |= CAM_DATA_PADDR;
+ else
+ flags |= CAM_DATA_VADDR;
} else if (io->scsiio.kern_sg_entries <=
(sizeof(cmd_info->cam_sglist)/
sizeof(cmd_info->cam_sglist[0]))) {
@@ -907,11 +910,10 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
ctl_sglist[i].len;
}
csio->sglist_cnt = io->scsiio.kern_sg_entries;
- flags |= CAM_SCATTER_VALID;
if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
- flags |= CAM_SG_LIST_PHYS;
+ flags |= CAM_DATA_SG_PADDR;
else
- flags &= ~CAM_SG_LIST_PHYS;
+ flags &= ~CAM_DATA_SG;
data_ptr = (uint8_t *)cam_sglist;
dxfer_len = io->scsiio.kern_data_len;
} else {
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c
index fa6af7c..f3710c8 100644
--- a/sys/cam/scsi/scsi_pass.c
+++ b/sys/cam/scsi/scsi_pass.c
@@ -696,8 +696,11 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
* do the right thing, even if there isn't data to map, but since CCBs
* without data are a reasonably common occurance (e.g. test unit
* ready), it will save a few cycles if we check for it here.
+ *
+ * XXX What happens if a sg list is supplied? We don't filter that
+ * out.
*/
- if (((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0)
+ if (((ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR)
&& (((ccb->ccb_h.func_code == XPT_SCSI_IO ||
ccb->ccb_h.func_code == XPT_ATA_IO)
&& ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE))
diff --git a/sys/cam/scsi/scsi_target.c b/sys/cam/scsi/scsi_target.c
index c45e8d5..963b4e6 100644
--- a/sys/cam/scsi/scsi_target.c
+++ b/sys/cam/scsi/scsi_target.c
@@ -737,7 +737,7 @@ targsendccb(struct targ_softc *softc, union ccb *ccb,
* without data are a reasonably common occurance (e.g. test unit
* ready), it will save a few cycles if we check for it here.
*/
- if (((ccb_h->flags & CAM_DATA_PHYS) == 0)
+ if (((ccb_h->flags & CAM_DATA_MASK) == CAM_DATA_VADDR)
&& (((ccb_h->func_code == XPT_CONT_TARGET_IO)
&& ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE))
|| (ccb_h->func_code == XPT_DEV_MATCH))) {
OpenPOWER on IntegriCloud