aboutsummaryrefslogtreecommitdiff
path: root/sys/cam/cam_periph.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/cam_periph.c')
-rw-r--r--sys/cam/cam_periph.c167
1 files changed, 105 insertions, 62 deletions
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 1d49bf277ba1..e957edee67f1 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -1,7 +1,7 @@
/*-
* Common functions for CAM "type" (peripheral) drivers.
*
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1997, 1998 Justin T. Gibbs.
* Copyright (c) 1997, 1998, 1999, 2000 Kenneth D. Merry.
@@ -29,9 +29,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
@@ -52,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam.h>
#include <cam/cam_ccb.h>
+#include <cam/cam_compat.h>
#include <cam/cam_queue.h>
#include <cam/cam_xpt_periph.h>
#include <cam/cam_xpt_internal.h>
@@ -77,20 +75,20 @@ static void camperiphfree(struct cam_periph *periph);
static int camperiphscsistatuserror(union ccb *ccb,
union ccb **orig_ccb,
cam_flags camflags,
- u_int32_t sense_flags,
+ uint32_t sense_flags,
int *openings,
- u_int32_t *relsim_flags,
- u_int32_t *timeout,
- u_int32_t *action,
+ uint32_t *relsim_flags,
+ uint32_t *timeout,
+ uint32_t *action,
const char **action_string);
static int camperiphscsisenseerror(union ccb *ccb,
union ccb **orig_ccb,
cam_flags camflags,
- u_int32_t sense_flags,
+ uint32_t sense_flags,
int *openings,
- u_int32_t *relsim_flags,
- u_int32_t *timeout,
- u_int32_t *action,
+ uint32_t *relsim_flags,
+ uint32_t *timeout,
+ uint32_t *action,
const char **action_string);
static void cam_periph_devctl_notify(union ccb *ccb);
@@ -808,9 +806,9 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo,
u_int maxmap)
{
int numbufs, i;
- u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
- u_int32_t lengths[CAM_PERIPH_MAXMAPS];
- u_int32_t dirs[CAM_PERIPH_MAXMAPS];
+ uint8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
+ uint32_t lengths[CAM_PERIPH_MAXMAPS];
+ uint32_t dirs[CAM_PERIPH_MAXMAPS];
bzero(mapinfo, sizeof(*mapinfo));
if (maxmap == 0)
@@ -825,15 +823,15 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo,
return(EINVAL);
}
if (ccb->cdm.pattern_buf_len > 0) {
- data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
+ data_ptrs[0] = (uint8_t **)&ccb->cdm.patterns;
lengths[0] = ccb->cdm.pattern_buf_len;
dirs[0] = CAM_DIR_OUT;
- data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches;
+ data_ptrs[1] = (uint8_t **)&ccb->cdm.matches;
lengths[1] = ccb->cdm.match_buf_len;
dirs[1] = CAM_DIR_IN;
numbufs = 2;
} else {
- data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
+ data_ptrs[0] = (uint8_t **)&ccb->cdm.matches;
lengths[0] = ccb->cdm.match_buf_len;
dirs[0] = CAM_DIR_IN;
numbufs = 1;
@@ -1015,31 +1013,31 @@ fail:
* Unmap memory segments mapped into kernel virtual address space by
* cam_periph_mapmem().
*/
-void
+int
cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
{
- int numbufs, i;
- u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
- u_int32_t lengths[CAM_PERIPH_MAXMAPS];
- u_int32_t dirs[CAM_PERIPH_MAXMAPS];
+ int error, numbufs, i;
+ uint8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
+ uint32_t lengths[CAM_PERIPH_MAXMAPS];
+ uint32_t dirs[CAM_PERIPH_MAXMAPS];
if (mapinfo->num_bufs_used <= 0) {
/* nothing to free and the process wasn't held. */
- return;
+ return (0);
}
switch (ccb->ccb_h.func_code) {
case XPT_DEV_MATCH:
if (ccb->cdm.pattern_buf_len > 0) {
- data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
+ data_ptrs[0] = (uint8_t **)&ccb->cdm.patterns;
lengths[0] = ccb->cdm.pattern_buf_len;
dirs[0] = CAM_DIR_OUT;
- data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches;
+ data_ptrs[1] = (uint8_t **)&ccb->cdm.matches;
lengths[1] = ccb->cdm.match_buf_len;
dirs[1] = CAM_DIR_IN;
numbufs = 2;
} else {
- data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
+ data_ptrs[0] = (uint8_t **)&ccb->cdm.matches;
lengths[0] = ccb->cdm.match_buf_len;
dirs[0] = CAM_DIR_IN;
numbufs = 1;
@@ -1059,10 +1057,10 @@ cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
numbufs = 1;
break;
case XPT_MMC_IO:
- data_ptrs[0] = (u_int8_t **)&ccb->mmcio.cmd.data;
+ data_ptrs[0] = (uint8_t **)&ccb->mmcio.cmd.data;
lengths[0] = sizeof(struct mmc_data *);
dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
- data_ptrs[1] = (u_int8_t **)&ccb->mmcio.cmd.data->data;
+ data_ptrs[1] = (uint8_t **)&ccb->mmcio.cmd.data->data;
lengths[1] = ccb->mmcio.cmd.data->len;
dirs[1] = ccb->ccb_h.flags & CAM_DIR_MASK;
numbufs = 2;
@@ -1090,12 +1088,11 @@ cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
numbufs = 1;
break;
default:
- /* allow ourselves to be swapped once again */
- PRELE(curproc);
- return;
- break; /* NOTREACHED */
+ numbufs = 0;
+ break;
}
+ error = 0;
for (i = 0; i < numbufs; i++) {
if (mapinfo->bp[i]) {
/* unmap the buffer */
@@ -1105,8 +1102,12 @@ cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
uma_zfree(pbuf_zone, mapinfo->bp[i]);
} else {
if (dirs[i] != CAM_DIR_OUT) {
- copyout(*data_ptrs[i], mapinfo->orig[i],
+ int error1;
+
+ error1 = copyout(*data_ptrs[i], mapinfo->orig[i],
lengths[i]);
+ if (error == 0)
+ error = error1;
}
free(*data_ptrs[i], M_CAMPERIPH);
}
@@ -1117,13 +1118,15 @@ cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
/* allow ourselves to be swapped once again */
PRELE(curproc);
+
+ return (error);
}
int
cam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr,
int (*error_routine)(union ccb *ccb,
cam_flags camflags,
- u_int32_t sense_flags))
+ uint32_t sense_flags))
{
union ccb *ccb;
int error;
@@ -1132,6 +1135,7 @@ cam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr,
error = found = 0;
switch(cmd){
+ case CAMGETPASSTHRU_0x19:
case CAMGETPASSTHRU:
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
xpt_setup_ccb(&ccb->ccb_h,
@@ -1221,8 +1225,8 @@ int
cam_periph_runccb(union ccb *ccb,
int (*error_routine)(union ccb *ccb,
cam_flags camflags,
- u_int32_t sense_flags),
- cam_flags camflags, u_int32_t sense_flags,
+ uint32_t sense_flags),
+ cam_flags camflags, uint32_t sense_flags,
struct devstat *ds)
{
struct bintime *starttime;
@@ -1260,7 +1264,7 @@ cam_periph_runccb(union ccb *ccb,
* shutdown_post_sync event will run with the scheduler stopped, but
* before we're officially dumping. To avoid hanging in adashutdown
* initiated commands (or other similar situations), we have to test for
- * either SCHEDULER_STOPPED() here as well.
+ * either dumping or SCHEDULER_STOPPED() here.
*
* To avoid locking problems, dumping/polling callers must call
* without a periph lock held.
@@ -1296,6 +1300,11 @@ cam_periph_runccb(union ccb *ccb,
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
error = 0;
else if (error_routine != NULL) {
+ /*
+ * cbfcnp is modified by cam_periph_ccbwait so
+ * reset it before we call the error routine
+ * which may call xpt_done.
+ */
ccb->ccb_h.cbfcnp = cam_periph_done;
error = (*error_routine)(ccb, camflags, sense_flags);
} else
@@ -1352,9 +1361,9 @@ cam_freeze_devq(struct cam_path *path)
xpt_action((union ccb *)&ccb_h);
}
-u_int32_t
-cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
- u_int32_t openings, u_int32_t arg,
+uint32_t
+cam_release_devq(struct cam_path *path, uint32_t relsim_flags,
+ uint32_t openings, uint32_t arg,
int getcount_only)
{
struct ccb_relsim crs;
@@ -1380,7 +1389,7 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
cam_status status;
struct scsi_start_stop_unit *scsi_cmd;
int error = 0, error_code, sense_key, asc, ascq;
- u_int16_t done_flags;
+ uint16_t done_flags;
scsi_cmd = (struct scsi_start_stop_unit *)
&done_ccb->csio.cdb_io.cdb_bytes;
@@ -1478,7 +1487,7 @@ out:
* and leave the rest to this function.
*/
void
-cam_periph_async(struct cam_periph *periph, u_int32_t code,
+cam_periph_async(struct cam_periph *periph, uint32_t code,
struct cam_path *path, void *arg)
{
switch (code) {
@@ -1533,9 +1542,9 @@ cam_periph_freeze_after_event(struct cam_periph *periph,
static int
camperiphscsistatuserror(union ccb *ccb, union ccb **orig_ccb,
- cam_flags camflags, u_int32_t sense_flags,
- int *openings, u_int32_t *relsim_flags,
- u_int32_t *timeout, u_int32_t *action, const char **action_string)
+ cam_flags camflags, uint32_t sense_flags,
+ int *openings, uint32_t *relsim_flags,
+ uint32_t *timeout, uint32_t *action, const char **action_string)
{
struct cam_periph *periph;
int error;
@@ -1648,14 +1657,14 @@ camperiphscsistatuserror(union ccb *ccb, union ccb **orig_ccb,
static int
camperiphscsisenseerror(union ccb *ccb, union ccb **orig,
- cam_flags camflags, u_int32_t sense_flags,
- int *openings, u_int32_t *relsim_flags,
- u_int32_t *timeout, u_int32_t *action, const char **action_string)
+ cam_flags camflags, uint32_t sense_flags,
+ int *openings, uint32_t *relsim_flags,
+ uint32_t *timeout, uint32_t *action, const char **action_string)
{
struct cam_periph *periph;
union ccb *orig_ccb = ccb;
int error, recoveryccb;
- u_int16_t flags;
+ uint16_t flags;
#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
if (ccb->ccb_h.func_code == XPT_SCSI_IO && ccb->csio.bio != NULL)
@@ -1872,7 +1881,7 @@ sense_error_done:
*/
int
cam_periph_error(union ccb *ccb, cam_flags camflags,
- u_int32_t sense_flags)
+ uint32_t sense_flags)
{
struct cam_path *newpath;
union ccb *orig_ccb, *scan_ccb;
@@ -1880,7 +1889,7 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
const char *action_string;
cam_status status;
int frozen, error, openings, devctl_err;
- u_int32_t action, relsim_flags, timeout;
+ uint32_t action, relsim_flags, timeout;
action = SSQ_PRINT_SENSE;
periph = xpt_path_periph(ccb->ccb_h.path);
@@ -1902,6 +1911,8 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
case CAM_SCSI_STATUS_ERROR:
case CAM_ATA_STATUS_ERROR:
case CAM_SMP_STATUS_ERROR:
+ case CAM_DEV_NOT_THERE:
+ case CAM_NVME_STATUS_ERROR:
devctl_err++;
break;
default:
@@ -1994,6 +2005,8 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT;
/* FALLTHROUGH */
case CAM_ATA_STATUS_ERROR:
+ case CAM_NVME_STATUS_ERROR:
+ case CAM_SMP_STATUS_ERROR:
case CAM_REQ_CMP_ERR:
case CAM_CMD_TIMEOUT:
case CAM_UNEXP_BUSFREE:
@@ -2131,7 +2144,7 @@ cam_periph_devctl_notify(union ccb *ccb)
sbuf_printf(&sb, "device=%s%d ", periph->periph_name,
periph->unit_number);
- sbuf_printf(&sb, "serial=\"");
+ sbuf_cat(&sb, "serial=\"");
if ((cgd = (struct ccb_getdev *)xpt_alloc_ccb_nowait()) != NULL) {
xpt_setup_ccb(&cgd->ccb_h, ccb->ccb_h.path,
CAM_PRIORITY_NORMAL);
@@ -2142,7 +2155,7 @@ cam_periph_devctl_notify(union ccb *ccb)
sbuf_bcat(&sb, cgd->serial_num, cgd->serial_num_len);
xpt_free_ccb((union ccb *)cgd);
}
- sbuf_printf(&sb, "\" ");
+ sbuf_cat(&sb, "\" ");
sbuf_printf(&sb, "cam_status=\"0x%x\" ", ccb->ccb_h.status);
switch (ccb->ccb_h.status & CAM_STATUS_MASK) {
@@ -2158,24 +2171,54 @@ cam_periph_devctl_notify(union ccb *ccb)
type = "error";
break;
case CAM_ATA_STATUS_ERROR:
- sbuf_printf(&sb, "RES=\"");
+ sbuf_cat(&sb, "RES=\"");
ata_res_sbuf(&ccb->ataio.res, &sb);
- sbuf_printf(&sb, "\" ");
+ sbuf_cat(&sb, "\" ");
+ type = "error";
+ break;
+ case CAM_NVME_STATUS_ERROR:
+ {
+ struct ccb_nvmeio *n = &ccb->nvmeio;
+
+ sbuf_printf(&sb, "sc=\"%02x\" sct=\"%02x\" cdw0=\"%08x\" ",
+ NVME_STATUS_GET_SC(n->cpl.status),
+ NVME_STATUS_GET_SCT(n->cpl.status), n->cpl.cdw0);
type = "error";
break;
+ }
default:
type = "error";
break;
}
- if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
- sbuf_printf(&sb, "CDB=\"");
+
+ switch (ccb->ccb_h.func_code) {
+ case XPT_SCSI_IO:
+ sbuf_cat(&sb, "CDB=\"");
scsi_cdb_sbuf(scsiio_cdb_ptr(&ccb->csio), &sb);
- sbuf_printf(&sb, "\" ");
- } else if (ccb->ccb_h.func_code == XPT_ATA_IO) {
- sbuf_printf(&sb, "ACB=\"");
+ sbuf_cat(&sb, "\" ");
+ break;
+ case XPT_ATA_IO:
+ sbuf_cat(&sb, "ACB=\"");
ata_cmd_sbuf(&ccb->ataio.cmd, &sb);
- sbuf_printf(&sb, "\" ");
+ sbuf_cat(&sb, "\" ");
+ break;
+ case XPT_NVME_IO:
+ case XPT_NVME_ADMIN:
+ {
+ struct ccb_nvmeio *n = &ccb->nvmeio;
+ struct nvme_command *cmd = &n->cmd;
+
+ // XXX Likely should be nvme_cmd_sbuf
+ sbuf_printf(&sb, "opc=\"%02x\" fuse=\"%02x\" cid=\"%04x\" "
+ "nsid=\"%08x\" cdw10=\"%08x\" cdw11=\"%08x\" cdw12=\"%08x\" "
+ "cdw13=\"%08x\" cdw14=\"%08x\" cdw15=\"%08x\" ",
+ cmd->opc, cmd->fuse, cmd->cid, cmd->nsid, cmd->cdw10,
+ cmd->cdw11, cmd->cdw12, cmd->cdw13, cmd->cdw14, cmd->cdw15);
+ break;
+ }
+ default:
+ break;
}
if (sbuf_finish(&sb) == 0)