Index: usr.sbin/bhyve/pci_nvme.c =================================================================== --- usr.sbin/bhyve/pci_nvme.c +++ usr.sbin/bhyve/pci_nvme.c @@ -156,6 +156,16 @@ NVME_COPY_FROM_PRP, }; +struct nvme_feature_lba_range_type_data { + uint8_t type; + uint8_t attribute; + uint8_t reserved1[14]; + uint64_t slba; + uint64_t nlb; + uint8_t guid[16]; + uint8_t reserved2[16]; +} __packed __aligned(4) lba_range_type_data; + #define NVME_CQ_INTEN 0x01 #define NVME_CQ_INTCOAL 0x02 @@ -242,7 +252,7 @@ struct nvme_completion *); struct nvme_feature_obj { - uint32_t cdw11; + void *data; nvme_feature_cb set; nvme_feature_cb get; bool namespace_specific; @@ -351,6 +361,10 @@ struct nvme_feature_obj *, struct nvme_command *, struct nvme_completion *); +static void nvme_feature_lba_range_type_get(struct pci_nvme_softc *, + struct nvme_feature_obj *, + struct nvme_command *, + struct nvme_completion *); static void nvme_feature_num_queues(struct pci_nvme_softc *, struct nvme_feature_obj *, struct nvme_command *, @@ -618,7 +632,15 @@ sc->feat[0].set = nvme_feature_invalid_cb; sc->feat[0].get = nvme_feature_invalid_cb; + memset(&lba_range_type_data, 0, sizeof(lba_range_type_data)); + lba_range_type_data.type = 0x00; /* Reserved */ + lba_range_type_data.attribute = 0x01; /* Writable */ + lba_range_type_data.slba = 0; /* Starting LBA */ + lba_range_type_data.nlb = sc->nsdata.nsze; /* Number of Logical Blocks */ + + sc->feat[NVME_FEAT_LBA_RANGE_TYPE].data = &lba_range_type_data; sc->feat[NVME_FEAT_LBA_RANGE_TYPE].namespace_specific = true; + sc->feat[NVME_FEAT_LBA_RANGE_TYPE].get = nvme_feature_lba_range_type_get; sc->feat[NVME_FEAT_ERROR_RECOVERY].namespace_specific = true; sc->feat[NVME_FEAT_NUMBER_OF_QUEUES].set = nvme_feature_num_queues; sc->feat[NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION].set = @@ -1326,6 +1348,24 @@ } +static void +nvme_feature_lba_range_type_get(struct pci_nvme_softc *sc, + struct nvme_feature_obj *feat, + struct nvme_command *command, + struct nvme_completion *compl) +{ + + struct nvme_feature_lba_range_type_data *data = + (struct nvme_feature_lba_range_type_data *)feat->data; + + command->cdw11 = 0; /* 1 range */ + + nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1, + command->prp2, (uint8_t *)data, + sizeof(struct nvme_feature_lba_range_type_data), + NVME_COPY_TO_PRP); +} + static void nvme_feature_num_queues(struct pci_nvme_softc *sc, struct nvme_feature_obj *feat, @@ -1406,9 +1446,6 @@ if (feat->set) feat->set(sc, feat, command, compl); - if (compl->status == NVME_SC_SUCCESS) - feat->cdw11 = command->cdw11; - return (0); } @@ -1435,10 +1472,6 @@ feat->get(sc, feat, command, compl); } - if (compl->status == NVME_SC_SUCCESS) { - compl->cdw0 = feat->cdw11; - } - return (0); }