summaryrefslogtreecommitdiffstats
path: root/sys/cam/cam_ccb.h
diff options
context:
space:
mode:
authorken <ken@FreeBSD.org>2010-11-30 22:39:46 +0000
committerken <ken@FreeBSD.org>2010-11-30 22:39:46 +0000
commit7f0ccdf947fabcfc0c34dffe169de18e4ee3aa1f (patch)
treef6f5a0b39082e4a685754786ebe504ed99d56b5e /sys/cam/cam_ccb.h
parent705fce2dae1505594d70d91548368b9248be744e (diff)
downloadFreeBSD-src-7f0ccdf947fabcfc0c34dffe169de18e4ee3aa1f.zip
FreeBSD-src-7f0ccdf947fabcfc0c34dffe169de18e4ee3aa1f.tar.gz
Add Serial Management Protocol (SMP) passthrough support to CAM.
This includes support in the kernel, camcontrol(8), libcam and the mps(4) driver for SMP passthrough. The CAM SCSI probe code has been modified to fetch Inquiry VPD page 0x00 to determine supported pages, and will now fetch page 0x83 in addition to page 0x80 if supported. Add two new CAM CCBs, XPT_SMP_IO, and XPT_GDEV_ADVINFO. The SMP CCB is intended for SMP requests and responses. The ADVINFO is currently used to fetch cached VPD page 0x83 data from the transport layer, but is intended to be extensible to fetch other types of device-specific data. SMP-only devices are not currently represented in the CAM topology, and so the current semantics are that the SIM will route SMP CCBs to either the addressed device, if it contains an SMP target, or its parent, if it contains an SMP target. (This is noted in cam_ccb.h, since it will change later once we have the ability to have SMP-only devices in CAM's topology.) smp_all.c, smp_all.h: New helper routines for SMP. This includes SMP request building routines, response parsing routines, error decoding routines, and structure definitions for a number of SMP commands. libcam/Makefile: Add smp_all.c to libcam, so that SMP functionality is available to userland applications. camcontrol.8, camcontrol.c: Add smp passthrough support to camcontrol. Several new subcommands are now available: 'smpcmd' functions much like 'cmd', except that it allows the user to send generic SMP commands. 'smprg' sends the SMP report general command, and displays the decoded output. It will automatically fetch extended output if it is available. 'smppc' sends the SMP phy control command, with any number of potential options. Among other things, this allows the user to reset a phy on a SAS expander, or disable a phy on an expander. 'smpmaninfo' sends the SMP report manufacturer information and displays the decoded output. 'smpphylist' displays a list of phys on an expander, and the CAM devices attached to those phys, if any. cam.h, cam.c: Add a status value for SMP errors (CAM_SMP_STATUS_ERROR). Add a missing description for CAM_SCSI_IT_NEXUS_LOST. Add support for SMP commands to cam_error_string(). cam_ccb.h: Rename the CAM_DIR_RESV flag to CAM_DIR_BOTH. SMP commands are by nature bi-directional, and we may need to support bi-directional SCSI commands later. Add the XPT_SMP_IO CCB. Since SMP commands are bi-directional, there are pointers for both the request and response. Add a fill routine for SMP CCBs. Add the XPT_GDEV_ADVINFO CCB. This is currently used to fetch cached page 0x83 data from the transport later, but is extensible to fetch many other types of data. cam_periph.c: Add support in cam_periph_mapmem() for XPT_SMP_IO and XPT_GDEV_ADVINFO CCBs. cam_xpt.c: Add support for executing XPT_SMP_IO CCBs. cam_xpt_internal.h: Add fields for VPD pages 0x00 and 0x83 in struct cam_ed. scsi_all.c: Add scsi_get_sas_addr(), a function that parses VPD page 0x83 data and pulls out a SAS address. scsi_all.h: Add VPD page 0x00 and 0x83 structures, and a prototype for scsi_get_sas_addr(). scsi_pass.c: Add support for mapping buffers in XPT_SMP_IO and XPT_GDEV_ADVINFO CCBs. scsi_xpt.c: In the SCSI probe code, first ask the device for VPD page 0x00. If any VPD pages are supported, that page is required to be implemented. Based on the response, we may probe for the serial number (page 0x80) or device id (page 0x83). Add support for the XPT_GDEV_ADVINFO CCB. sys/conf/files: Add smp_all.c. mps.c: Add support for passing in a uio in mps_map_command(), so we can map a S/G list at once. Add support for SMP passthrough commands in mps_data_cb(). SMP is a special case, because the first buffer in the S/G list is outbound and the second buffer is inbound. Add support for warning the user if the busdma code comes back with more buffers than will work for the command. This will, for example, help the user determine why an SMP command failed if busdma comes back with three buffers. mps_pci.c: Add sys/uio.h. mps_sas.c: Add the SAS address and the parent handle to the list of fields we pull from device page 0 and cache in struct mpssas_target. These are needed for SMP passthrough. Add support for the XPT_SMP_IO CCB. For now, this CCB is routed to the addressed device if it supports SMP, or to its parent if it does not and the parent does. This is necessary because CAM does not currently support SMP-only nodes in the topology. Make SMP passthrough support conditional on __FreeBSD_version >= 900026. This will make it easier to MFC this change to the driver without MFCing the CAM changes as well. mps_user.c: Un-staticize mpi_init_sge() so we can use it for the SMP passthrough code. mpsvar.h: Add a uio and iovecs into struct mps_command for SMP passthrough commands. Add a cm_max_segs field to struct mps_command so that we can warn the user if busdma comes back with too many segments. Clear the cm_reply when a command gets freed. If it is not cleared, reply frames will eventually get freed into the pool multiple times and corrupt the pool. (This fix is from scottl.) Add a prototype for mpi_init_sge(). sys/param.h: Bump __FreeBSD_version to 900026 for the for the inclusion of the XPT_GDEV_ADVINFO and XPT_SMP_IO CAM CCBs.
Diffstat (limited to 'sys/cam/cam_ccb.h')
-rw-r--r--sys/cam/cam_ccb.h88
1 files changed, 87 insertions, 1 deletions
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index bbb5069..9c1e3ab 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -66,7 +66,7 @@ typedef enum {
*/
CAM_SCATTER_VALID = 0x00000010,/* Scatter/gather list is valid */
CAM_DIS_AUTOSENSE = 0x00000020,/* Disable autosense feature */
- CAM_DIR_RESV = 0x00000000,/* Data direction (00:reserved) */
+ 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) */
@@ -144,6 +144,8 @@ typedef enum {
/* Device statistics (error counts, etc.) */
XPT_FREEZE_QUEUE = 0x0d,
/* Freeze device queue */
+ XPT_GDEV_ADVINFO = 0x0e,
+ /* Advanced device information */
/* SCSI Control Functions: 0x10->0x1F */
XPT_ABORT = 0x10,
/* Abort the specified CCB */
@@ -185,6 +187,9 @@ typedef enum {
* Set SIM specific knob values.
*/
+ XPT_SMP_IO = 0x1b | XPT_FC_DEV_QUEUED,
+ /* Serial Management Protocol */
+
XPT_SCAN_TGT = 0x1E | XPT_FC_QUEUED | XPT_FC_USER_CCB
| XPT_FC_XPT_ONLY,
/* Scan Target */
@@ -608,6 +613,32 @@ struct ccb_pathstats {
struct timeval last_reset; /* Time of last bus reset/loop init */
};
+typedef enum {
+ SMP_FLAG_NONE = 0x00,
+ SMP_FLAG_REQ_SG = 0x01,
+ SMP_FLAG_RSP_SG = 0x02
+} ccb_smp_pass_flags;
+
+/*
+ * Serial Management Protocol CCB
+ * XXX Currently the semantics for this CCB are that it is executed either
+ * by the addressed device, or that device's parent (i.e. an expander for
+ * any device on an expander) if the addressed device doesn't support SMP.
+ * Later, once we have the ability to probe SMP-only devices and put them
+ * in CAM's topology, the CCB will only be executed by the addressed device
+ * if possible.
+ */
+struct ccb_smpio {
+ struct ccb_hdr ccb_h;
+ uint8_t *smp_request;
+ int smp_request_len;
+ uint16_t smp_request_sglist_cnt;
+ uint8_t *smp_response;
+ int smp_response_len;
+ uint16_t smp_response_sglist_cnt;
+ ccb_smp_pass_flags flags;
+};
+
typedef union {
u_int8_t *sense_ptr; /*
* Pointer to storage
@@ -1054,6 +1085,26 @@ struct ccb_eng_exec { /* This structure must match SCSIIO size */
#define XPT_CCB_INVALID -1 /* for signaling a bad CCB to free */
/*
+ * CCB for getting advanced device information. This operates in a fashion
+ * similar to XPT_GDEV_TYPE. Specify the target in ccb_h, the buffer
+ * type requested, and provide a buffer size/buffer to write to. If the
+ * buffer is too small, the handler will set GDEVAI_FLAG_MORE.
+ */
+struct ccb_getdev_advinfo {
+ struct ccb_hdr ccb_h;
+ uint32_t flags;
+#define CGDAI_FLAG_TRANSPORT 0x1
+#define CGDAI_FLAG_PROTO 0x2
+ uint32_t buftype; /* IN: Type of data being requested */
+ /* NB: buftype is interpreted on a per-transport basis */
+#define CGDAI_TYPE_SCSI_DEVID 1
+ off_t bufsiz; /* IN: Size of external buffer */
+#define CAM_SCSI_DEVID_MAXLEN 65536 /* length in buffer is an uint16_t */
+ off_t provsiz; /* OUT: Size required/used */
+ uint8_t *buf; /* IN/OUT: Buffer for requested data */
+};
+
+/*
* Union of all CCB types for kernel space allocation. This union should
* never be used for manipulating CCBs - its only use is for the allocation
* and deallocation of raw CCB space and is the return type of xpt_ccb_alloc
@@ -1087,9 +1138,11 @@ union ccb {
struct ccb_notify_acknowledge cna2;
struct ccb_eng_inq cei;
struct ccb_eng_exec cee;
+ struct ccb_smpio smpio;
struct ccb_rescan crcn;
struct ccb_debug cdbg;
struct ccb_ataio ataio;
+ struct ccb_getdev_advinfo cgdai;
};
__BEGIN_DECLS
@@ -1116,6 +1169,13 @@ cam_fill_ataio(struct ccb_ataio *ataio, u_int32_t retries,
u_int32_t timeout);
static __inline void
+cam_fill_smpio(struct ccb_smpio *smpio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *), uint32_t flags,
+ uint8_t *smp_request, int smp_request_len,
+ uint8_t *smp_response, int smp_response_len,
+ uint32_t timeout);
+
+static __inline void
cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
u_int32_t flags, u_int8_t tag_action,
@@ -1172,6 +1232,32 @@ cam_fill_ataio(struct ccb_ataio *ataio, u_int32_t retries,
ataio->tag_action = tag_action;
}
+static __inline void
+cam_fill_smpio(struct ccb_smpio *smpio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *), uint32_t flags,
+ uint8_t *smp_request, int smp_request_len,
+ uint8_t *smp_response, int smp_response_len,
+ uint32_t timeout)
+{
+#ifdef _KERNEL
+ KASSERT((flags & CAM_DIR_MASK) == CAM_DIR_BOTH,
+ ("direction != CAM_DIR_BOTH"));
+ KASSERT((smp_request != NULL) && (smp_response != NULL),
+ ("need valid request and response buffers"));
+ KASSERT((smp_request_len != 0) && (smp_response_len != 0),
+ ("need non-zero request and response lengths"));
+#endif /*_KERNEL*/
+ smpio->ccb_h.func_code = XPT_SMP_IO;
+ smpio->ccb_h.flags = flags;
+ smpio->ccb_h.retry_count = retries;
+ smpio->ccb_h.cbfcnp = cbfcnp;
+ smpio->ccb_h.timeout = timeout;
+ smpio->smp_request = smp_request;
+ smpio->smp_request_len = smp_request_len;
+ smpio->smp_response = smp_response;
+ smpio->smp_response_len = smp_response_len;
+}
+
void cam_calc_geometry(struct ccb_calc_geometry *ccg, int extended);
__END_DECLS
OpenPOWER on IntegriCloud