Index: sys/cam/cam_periph.c =================================================================== --- sys/cam/cam_periph.c +++ sys/cam/cam_periph.c @@ -819,6 +819,16 @@ dirs[1] = CAM_DIR_IN; numbufs = 2; break; + case XPT_NVME_IO: + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) + return(0); + if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR) + return (EINVAL); + data_ptrs[0] = &ccb->nvmeio.data_ptr; + lengths[0] = ccb->nvmeio.dxfer_len; + dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK; + numbufs = 1; + break; case XPT_DEV_ADVINFO: if (ccb->cdai.bufsiz == 0) return (0); Index: sys/cam/scsi/scsi_pass.c =================================================================== --- sys/cam/scsi/scsi_pass.c +++ sys/cam/scsi/scsi_pass.c @@ -2182,6 +2182,7 @@ * preserved, the rest we get from the user. */ xpt_merge_ccb(ccb, inccb); + /*XXX*/ccb->ccb_h.xflags = inccb->ccb_h.xflags; if (ccb->ccb_h.flags & CAM_CDB_POINTER) { cmd = __builtin_alloca(ccb->csio.cdb_len); @@ -2202,6 +2203,7 @@ */ fc = ccb->ccb_h.func_code; if ((fc == XPT_SCSI_IO) || (fc == XPT_ATA_IO) || (fc == XPT_SMP_IO) + || (fc == XPT_NVME_IO) || (fc == XPT_DEV_MATCH) || (fc == XPT_DEV_ADVINFO)) { bzero(&mapinfo, sizeof(mapinfo)); Index: sys/dev/nvme/nvme_sim.c =================================================================== --- sys/dev/nvme/nvme_sim.c +++ sys/dev/nvme/nvme_sim.c @@ -110,7 +110,10 @@ memcpy(&req->cmd, &ccb->nvmeio.cmd, sizeof(ccb->nvmeio.cmd)); - nvme_ctrlr_submit_io_request(ctrlr, req); + if (ccb->ccb_h.xflags & 0x10) + nvme_ctrlr_submit_admin_request(ctrlr, req); + else + nvme_ctrlr_submit_io_request(ctrlr, req); ccb->ccb_h.status |= CAM_SIM_QUEUED; }