35#include <sys/endian.h>
38#include <sys/malloc.h>
39#include <sys/kernel.h>
47#include <sys/sysctl.h>
63#include <machine/stdarg.h>
68#define CAM_QUIRK_MAXTAGS 1
93 "NVME_PROBE_IDENTIFY_CD",
94 "NVME_PROBE_IDENTIFY_NS",
99#define NVME_PROBE_SET_ACTION(softc, newaction) \
102 text = nvme_probe_action_text; \
103 CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \
104 ("Probe %s to %s\n", text[(softc)->action], \
105 text[(newaction)])); \
106 (softc)->action = (newaction); \
116 struct nvme_controller_data cd;
117 struct nvme_namespace_data ns;
132 .
quirks = 0, .mintags = 0, .maxtags = 0
170#define NVME_XPT_XPORT(x, X) \
171static struct xpt_xport nvme_xport_ ## x = { \
172 .xport = XPORT_ ## X, \
174 .ops = &nvme_xport_ops, \
176CAM_XPT_XPORT(nvme_xport_ ## x);
202 union ccb *request_ccb;
205 request_ccb = (
union ccb *)arg;
206 if (request_ccb == NULL) {
207 printf(
"nvme_probe_register: no probe CCB, "
208 "can't register device\n");
212 softc = (
nvme_probe_softc *)malloc(
sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT);
215 printf(
"nvme_probe_register: Unable to probe new device. "
216 "Unable to allocate softc\n");
219 TAILQ_INIT(&softc->request_ccbs);
220 TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->
ccb_h,
223 periph->
softc = softc;
244 ccb = (
union ccb *)TAILQ_FIRST(&softc->request_ccbs);
251 softc->
flags &= ~NVME_PROBE_NO_ANNOUNCE;
266 nvmeio = &start_ccb->
nvmeio;
280 (uint8_t *)&softc->cd,
291 (uint8_t *)&softc->ns,
298 panic(
"nvme_probe_start: invalid action state 0x%x\n", softc->
action);
307 struct nvme_namespace_data *nvme_data;
308 struct nvme_controller_data *nvme_cdata;
314 int found = 1, e, g, len;
356 nvme_controller_data_swapbytes(&softc->cd);
359 if (nvme_cdata == NULL) {
360 nvme_cdata = malloc(
sizeof(*nvme_cdata), M_CAMXPT,
362 if (nvme_cdata == NULL) {
363 xpt_print(path,
"Can't allocate memory");
367 bcopy(&softc->cd, nvme_cdata,
sizeof(*nvme_cdata));
377 malloc(NVME_SERIAL_NUMBER_LENGTH + 1, M_CAMXPT, M_NOWAIT);
380 nvme_cdata->sn,
sizeof(nvme_cdata->sn),
381 NVME_SERIAL_NUMBER_LENGTH + 1,
395 nvme_namespace_data_swapbytes(&softc->ns);
398 if (softc->ns.nsze == 0)
402 if (nvme_data == NULL) {
403 nvme_data = malloc(
sizeof(*nvme_data), M_CAMXPT,
405 if (nvme_data == NULL) {
406 xpt_print(path,
"Can't allocate memory");
410 bcopy(&softc->ns, nvme_data,
sizeof(*nvme_data));
420 for (g = 0; g <
sizeof(nvme_data->nguid); g++) {
421 if (nvme_data->nguid[g] != 0)
424 if (g <
sizeof(nvme_data->nguid))
426 for (e = 0; e <
sizeof(nvme_data->eui64); e++) {
427 if (nvme_data->eui64[e] != 0)
430 if (e <
sizeof(nvme_data->eui64))
443 if (g <
sizeof(nvme_data->nguid)) {
451 if (e <
sizeof(nvme_data->eui64)) {
470 panic(
"nvme_probe_done: invalid action state 0x%x\n", softc->
action);
481 while ((done_ccb = (
union ccb *)TAILQ_FIRST(&softc->request_ccbs))) {
482 TAILQ_REMOVE(&softc->request_ccbs,
483 &done_ccb->
ccb_h, periph_links.tqe);
497 free(periph->
softc, M_CAMXPT);
503nvme_find_quirk(
struct cam_ed *device)
514 panic(
"xpt_find_quirk: device didn't match wildcard entry!!");
517 device->
quirk = quirk;
539 if (request_ccb != NULL) {
561 TAILQ_INSERT_TAIL(&
softc->request_ccbs,
562 &request_ccb->
ccb_h, periph_links.tqe);
565 (
"restarting nvme_probe device\n"));
569 (
"Failing to restart nvme_probe device\n"));
574 (
"Adding nvme_probe device\n"));
583 "returned an error, can't continue probe\n");
636 memset(&
cts, 0,
sizeof(
cts));
644 cts.proto_specific.valid = 0;
645 cts.xport_specific.valid = 0;
659 cdai = &start_ccb->
cdai;
713 amt =
sizeof(
struct nvme_controller_data);
722 amt =
sizeof(
struct nvme_namespace_data);
735 (
void *)(uintptr_t)cdai->
buftype);
768 struct cam_ed *device,
void *async_arg)
798 memset(&
cts, 0,
sizeof(
cts));
805 nvmex = &
cts.xport_specific.nvme;
809 sbuf_new(&sb, buffer,
sizeof(buffer), SBUF_FIXEDLEN);
810 sbuf_printf(&sb,
"%s%d: nvme version %d.%d",
812 NVME_MAJOR(nvmex->
spec),
813 NVME_MINOR(nvmex->
spec));
815 sbuf_printf(&sb,
" x%d (max x%d) lanes PCIe Gen%d (max Gen%d) link",
818 sbuf_printf(&sb,
"\n");
829 sbuf_new(&sb, buffer,
sizeof(buffer), SBUF_FIXEDLEN);
845 char cdb_str[(
sizeof(
struct nvme_command) * 3) + 1];
caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries, int entry_size, cam_quirkmatch_t *comp_func)
void cam_strvis_flag(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen, uint32_t flags)
#define CAM_TARGET_WILDCARD
@ CAM_STRVIS_FLAG_NONASCII_SPC
#define CAM_PRIORITY_NORMAL
#define CAM_PRIORITY_NONE
@ CTS_TYPE_CURRENT_SETTINGS
#define CTS_NVME_VALID_LINK
#define CDAI_TYPE_NVME_CNTRL
static __inline void cam_fill_nvmeadmin(struct ccb_nvmeio *nvmeio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int32_t flags, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int32_t timeout)
#define CDAI_TYPE_SERIAL_NUM
#define CDAI_TYPE_PHYS_PATH
#define CDAI_TYPE_NVME_NS
#define CDAI_TYPE_SCSI_DEVID
#define CAM_DEBUG(path, flag, printfargs)
void cam_periph_release_locked(struct cam_periph *periph)
struct cam_periph * cam_periph_find(struct cam_path *path, char *name)
u_int32_t cam_release_devq(struct cam_path *path, u_int32_t relsim_flags, u_int32_t openings, u_int32_t arg, int getcount_only)
int cam_periph_acquire(struct cam_periph *periph)
void cam_periph_invalidate(struct cam_periph *periph)
int cam_periph_error(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags)
cam_status cam_periph_alloc(periph_ctor_t *periph_ctor, periph_oninv_t *periph_oninvalidate, periph_dtor_t *periph_dtor, periph_start_t *periph_start, char *name, cam_periph_type type, struct cam_path *path, ac_callback_t *ac_callback, ac_code code, void *arg)
#define CAM_PERIPH_INVALID
#define cam_periph_assert(periph, what)
#define CAM_PERIPH_DRV_EARLY
void() periph_init_t(void)
void xpt_acquire_device(struct cam_ed *device)
void xpt_schedule(struct cam_periph *periph, u_int32_t new_priority)
void xpt_release_device(struct cam_ed *device)
void xpt_print(struct cam_path *path, const char *fmt,...)
void xpt_async(u_int32_t async_code, struct cam_path *path, void *async_arg)
void xpt_setup_ccb(struct ccb_hdr *ccb_h, struct cam_path *path, u_int32_t priority)
void xpt_action(union ccb *start_ccb)
void xpt_done(union ccb *done_ccb)
lun_id_t xpt_path_lun_id(struct cam_path *path)
void xpt_action_default(union ccb *start_ccb)
void xpt_release_ccb(union ccb *free_ccb)
struct cam_ed * xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
void xpt_release_devq(struct cam_path *path, u_int count, int run_queue)
#define xpt_path_unlock(path)
#define xpt_path_owned(path)
#define xpt_path_lock(path)
#define xpt_path_assert(path, what)
static void xpt_path_inq(struct ccb_pathinq *cpi, struct cam_path *path)
#define CAM_DEV_UNCONFIGURED
struct ccb_trans_settings_mmc * cts
const char * nvme_cmd_string(const struct nvme_command *cmd, char *cmd_string, size_t len)
void nvme_print_ident(const struct nvme_controller_data *cdata, const struct nvme_namespace_data *data, struct sbuf *sb)
const char * nvme_op_string(const struct nvme_command *cmd, int admin)
int nvme_identify_match(caddr_t identbuffer, caddr_t table_entry)
void nvme_ns_cmd(struct ccb_nvmeio *nvmeio, uint8_t cmd, uint32_t nsid, uint32_t cdw10, uint32_t cdw11, uint32_t cdw12, uint32_t cdw13, uint32_t cdw14, uint32_t cdw15)
static struct xpt_xport_ops nvme_xport_ops
static void nvme_proto_announce(struct cam_ed *device)
static periph_init_t nvme_probe_periph_init
static struct xpt_proto_ops nvme_proto_ops
PERIPHDRIVER_DECLARE(nvme_probe, nvme_probe_driver)
static void nvme_action(union ccb *start_ccb)
static void nvme_probe_done(struct cam_periph *periph, union ccb *done_ccb)
static void nvme_probe_cleanup(struct cam_periph *periph)
CAM_XPT_PROTO(nvme_proto)
static struct cam_ed * nvme_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
static void nvme_proto_debug_out(union ccb *ccb)
static void nvme_dev_advinfo(union ccb *start_ccb)
static cam_status nvme_probe_register(struct cam_periph *periph, void *arg)
static void nvme_scan_lun(struct cam_periph *periph, struct cam_path *path, cam_flags flags, union ccb *ccb)
#define CAM_QUIRK_MAXTAGS
static char * nvme_probe_action_text[]
static void nvme_proto_denounce(struct cam_ed *device)
static void nvme_device_transport(struct cam_path *path)
#define NVME_PROBE_SET_ACTION(softc, newaction)
static struct nvme_quirk_entry nvme_quirk_table[]
#define NVME_XPT_XPORT(x, X)
static void nvme_probe_start(struct cam_periph *periph, union ccb *start_ccb)
static struct xpt_proto nvme_proto
static const int nvme_quirk_table_size
static void nvme_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, struct cam_ed *device, void *async_arg)
static void nvme_probe_schedule(struct cam_periph *nvme_probe_periph)
static void nvme_announce_periph(struct cam_periph *periph)
static struct periph_driver nvme_probe_driver
#define SVPD_ID_CODESET_BINARY
static __inline void scsi_ulto2b(u_int32_t val, u_int8_t *bytes)
#define SVPD_ID_ASSOC_LUN
#define SID_QUAL_LU_CONNECTED
#define SVPD_ID_TYPE_EUI64
#define SVPD_DEVICE_ID_HDR_LEN
struct nvme_namespace_data * nvme_data
struct nvme_controller_data * nvme_cdata
struct cam_periph * periph
struct cam_periph * periph
xpt_proto_announce_func announce
xpt_alloc_device_func alloc_device
struct ccb_dev_advinfo cdai