aboutsummaryrefslogtreecommitdiff
path: root/sys/cam/cam.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/cam.c')
-rw-r--r--sys/cam/cam.c156
1 files changed, 114 insertions, 42 deletions
diff --git a/sys/cam/cam.c b/sys/cam/cam.c
index 5b7e2a7e924f..d9cff3468da0 100644
--- a/sys/cam/cam.c
+++ b/sys/cam/cam.c
@@ -1,7 +1,7 @@
/*-
* Generic utility routines for the Common Access Method layer.
*
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1997 Justin T. Gibbs.
* All rights reserved.
@@ -28,13 +28,11 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#ifdef _KERNEL
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/memdesc.h>
#include <sys/sysctl.h>
#else /* _KERNEL */
#include <stdlib.h>
@@ -51,6 +49,7 @@ __FBSDID("$FreeBSD$");
#ifdef _KERNEL
#include <sys/libkern.h>
+#include <machine/bus.h>
#include <cam/cam_queue.h>
#include <cam/cam_xpt.h>
@@ -88,10 +87,12 @@ const struct cam_status_entry cam_status_table[] = {
{ CAM_REQ_TERMIO, "CCB request terminated by the host" },
{ CAM_UNREC_HBA_ERROR, "Unrecoverable Host Bus Adapter Error" },
{ CAM_REQ_TOO_BIG, "The request was too large for this host" },
- { CAM_REQUEUE_REQ, "Unconditionally Re-queue Request", },
+ { CAM_REQUEUE_REQ, "Unconditionally Re-queue Request" },
{ CAM_ATA_STATUS_ERROR, "ATA Status Error" },
{ CAM_SCSI_IT_NEXUS_LOST,"Initiator/Target Nexus Lost" },
{ CAM_SMP_STATUS_ERROR, "SMP Status Error" },
+ { CAM_REQ_SOFTTIMEOUT, "Completed w/o error, but took too long" },
+ { CAM_NVME_STATUS_ERROR, "NVME Status Error" },
{ CAM_IDE, "Initiator Detected Error Message Received" },
{ CAM_RESRC_UNAVAIL, "Resource Unavailable" },
{ CAM_UNACKED_EVENT, "Unacknowledged Event by Host" },
@@ -121,44 +122,25 @@ SYSCTL_INT(_kern_cam, OID_AUTO, sort_io_queues, CTLFLAG_RWTUN,
#endif
void
-cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen)
+cam_strvis(uint8_t *dst, const uint8_t *src, int srclen, int dstlen)
{
+ cam_strvis_flag(dst, src, srclen, dstlen,
+ CAM_STRVIS_FLAG_NONASCII_ESC);
+}
- /* Trim leading/trailing spaces, nulls. */
- while (srclen > 0 && src[0] == ' ')
- src++, srclen--;
- while (srclen > 0
- && (src[srclen-1] == ' ' || src[srclen-1] == '\0'))
- srclen--;
-
- while (srclen > 0 && dstlen > 1) {
- u_int8_t *cur_pos = dst;
+void
+cam_strvis_flag(uint8_t *dst, const uint8_t *src, int srclen, int dstlen,
+ uint32_t flags)
+{
+ struct sbuf sb;
- if (*src < 0x20 || *src >= 0x80) {
- /* SCSI-II Specifies that these should never occur. */
- /* non-printable character */
- if (dstlen > 4) {
- *cur_pos++ = '\\';
- *cur_pos++ = ((*src & 0300) >> 6) + '0';
- *cur_pos++ = ((*src & 0070) >> 3) + '0';
- *cur_pos++ = ((*src & 0007) >> 0) + '0';
- } else {
- *cur_pos++ = '?';
- }
- } else {
- /* normal character */
- *cur_pos++ = *src;
- }
- src++;
- srclen--;
- dstlen -= cur_pos - dst;
- dst = cur_pos;
- }
- *dst = '\0';
+ sbuf_new(&sb, dst, dstlen, SBUF_FIXEDLEN);
+ cam_strvis_sbuf(&sb, src, srclen, flags);
+ sbuf_finish(&sb);
}
void
-cam_strvis_sbuf(struct sbuf *sb, const u_int8_t *src, int srclen,
+cam_strvis_sbuf(struct sbuf *sb, const uint8_t *src, int srclen,
uint32_t flags)
{
@@ -220,7 +202,7 @@ cam_strvis_sbuf(struct sbuf *sb, const u_int8_t *src, int srclen,
* Each '*' generates recursion, so keep the number of * in check.
*/
int
-cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, int str_len)
+cam_strmatch(const uint8_t *str, const uint8_t *pattern, int str_len)
{
while (*pattern != '\0' && str_len > 0) {
@@ -436,7 +418,7 @@ cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
ccb->ccb_h.func_code);
break;
}
- sbuf_printf(&sb, "\n");
+ sbuf_putc(&sb, '\n');
}
if (flags & CAM_ESF_CAM_STATUS) {
@@ -467,13 +449,13 @@ cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
if (proto_flags & CAM_EAF_PRINT_STATUS) {
sbuf_cat(&sb, path_str);
ata_status_sbuf(&ccb->ataio, &sb);
- sbuf_printf(&sb, "\n");
+ sbuf_putc(&sb, '\n');
}
if (proto_flags & CAM_EAF_PRINT_RESULT) {
sbuf_cat(&sb, path_str);
- sbuf_printf(&sb, "RES: ");
+ sbuf_cat(&sb, "RES: ");
ata_res_sbuf(&ccb->ataio.res, &sb);
- sbuf_printf(&sb, "\n");
+ sbuf_putc(&sb, '\n');
}
break;
@@ -590,3 +572,93 @@ cam_calc_geometry(struct ccb_calc_geometry *ccg, int extended)
ccg->cylinders = ccg->volume_size / secs_per_cylinder;
ccg->ccb_h.status = CAM_REQ_CMP;
}
+
+#ifdef _KERNEL
+struct memdesc
+memdesc_ccb(union ccb *ccb)
+{
+ struct ccb_hdr *ccb_h;
+ void *data_ptr;
+ uint32_t dxfer_len;
+ uint16_t sglist_cnt;
+
+ ccb_h = &ccb->ccb_h;
+ switch (ccb_h->func_code) {
+ case XPT_SCSI_IO: {
+ struct ccb_scsiio *csio;
+
+ csio = &ccb->csio;
+ data_ptr = csio->data_ptr;
+ dxfer_len = csio->dxfer_len;
+ sglist_cnt = csio->sglist_cnt;
+ break;
+ }
+ case XPT_CONT_TARGET_IO: {
+ struct ccb_scsiio *ctio;
+
+ ctio = &ccb->ctio;
+ data_ptr = ctio->data_ptr;
+ dxfer_len = ctio->dxfer_len;
+ sglist_cnt = ctio->sglist_cnt;
+ break;
+ }
+ case XPT_ATA_IO: {
+ struct ccb_ataio *ataio;
+
+ ataio = &ccb->ataio;
+ data_ptr = ataio->data_ptr;
+ dxfer_len = ataio->dxfer_len;
+ sglist_cnt = 0;
+ break;
+ }
+ case XPT_NVME_IO:
+ case XPT_NVME_ADMIN: {
+ struct ccb_nvmeio *nvmeio;
+
+ nvmeio = &ccb->nvmeio;
+ data_ptr = nvmeio->data_ptr;
+ dxfer_len = nvmeio->dxfer_len;
+ sglist_cnt = nvmeio->sglist_cnt;
+ break;
+ }
+ default:
+ panic("%s: Unsupported func code %d", __func__,
+ ccb_h->func_code);
+ }
+
+ switch ((ccb_h->flags & CAM_DATA_MASK)) {
+ case CAM_DATA_VADDR:
+ return (memdesc_vaddr(data_ptr, dxfer_len));
+ case CAM_DATA_PADDR:
+ return (memdesc_paddr((vm_paddr_t)(uintptr_t)data_ptr,
+ dxfer_len));
+ case CAM_DATA_SG:
+ return (memdesc_vlist(data_ptr, sglist_cnt));
+ case CAM_DATA_SG_PADDR:
+ return (memdesc_plist(data_ptr, sglist_cnt));
+ case CAM_DATA_BIO:
+ return (memdesc_bio(data_ptr));
+ default:
+ panic("%s: flags 0x%X unimplemented", __func__, ccb_h->flags);
+ }
+}
+
+int
+bus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb,
+ bus_dmamap_callback_t *callback, void *callback_arg,
+ int flags)
+{
+ struct ccb_hdr *ccb_h;
+ struct memdesc mem;
+
+ ccb_h = &ccb->ccb_h;
+ if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) {
+ callback(callback_arg, NULL, 0, 0);
+ return (0);
+ }
+
+ mem = memdesc_ccb(ccb);
+ return (bus_dmamap_load_mem(dmat, map, &mem, callback, callback_arg,
+ flags));
+}
+#endif