-/* $OpenBSD: nvme.c,v 1.2 2014/04/15 10:28:07 dlg Exp $ */
+/* $OpenBSD: nvme.c,v 1.3 2014/04/16 00:26:59 dlg Exp $ */
/*
* Copyright (c) 2014 David Gwynne <dlg@openbsd.org>
int nvme_identify(struct nvme_softc *);
void nvme_fill_identify(struct nvme_softc *,
struct nvme_ccb *, void *);
-void nvme_identify_done(struct nvme_softc *,
- struct nvme_ccb *, struct nvme_cqe *);
int nvme_ccbs_alloc(struct nvme_softc *, u_int);
void nvme_ccbs_free(struct nvme_softc *);
struct nvme_ccb *, void *);
void nvme_poll_done(struct nvme_softc *,
struct nvme_ccb *, struct nvme_cqe *);
+void nvme_empty_done(struct nvme_softc *,
+ struct nvme_ccb *, struct nvme_cqe *);
struct nvme_queue * nvme_q_alloc(struct nvme_softc *,
u_int, u_int, u_int);
struct nvme_poll_state state;
void (*done)(struct nvme_softc *, struct nvme_ccb *, struct nvme_cqe *);
void *cookie;
+ u_int16_t flags;
memset(&state, 0, sizeof(state));
state.s.cid = ccb->ccb_id;
ccb->ccb_cookie = cookie;
done(sc, ccb, &state.c);
- return (0);
+ flags = lemtoh16(&state.c.flags);
+
+ return (NVME_CQE_SCT(flags) | NVME_CQE_SC(flags));
}
void
state->c = *cqe;
}
+void
+nvme_empty_done(struct nvme_softc *sc, struct nvme_ccb *ccb,
+ struct nvme_cqe *cqe)
+{
+}
+
int
nvme_q_complete(struct nvme_softc *sc, struct nvme_queue *q)
{
int
nvme_identify(struct nvme_softc *sc)
{
- struct nvme_ccb *ccb;
+ char sn[41], mn[81], fr[17];
+ struct nvm_identify_controller *identify;
struct nvme_dmamem *mem;
+ struct nvme_ccb *ccb;
int rv = 1;
ccb = nvme_ccb_get(sc);
if (ccb == NULL)
panic("nvme_identify: nvme_ccb_get returned NULL");
- mem = nvme_dmamem_alloc(sc, sizeof(struct nvm_identify_controller));
+ mem = nvme_dmamem_alloc(sc, sizeof(*identify));
if (mem == NULL)
return (1);
- ccb->ccb_done = nvme_identify_done;
+ identify = NVME_DMA_KVA(mem);
+
+ ccb->ccb_done = nvme_empty_done;
ccb->ccb_cookie = mem;
+ bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(mem),
+ 0, sizeof(*identify), BUS_DMASYNC_PREREAD);
rv = nvme_poll(sc, sc->sc_admin_q, ccb, nvme_fill_identify);
+ bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(mem),
+ 0, sizeof(*identify), BUS_DMASYNC_POSTREAD);
+ if (rv != 0)
+ goto done;
+
+ scsi_strvis(sn, identify->sn, sizeof(identify->sn));
+ scsi_strvis(mn, identify->mn, sizeof(identify->mn));
+ scsi_strvis(fr, identify->fr, sizeof(identify->fr));
+
+ printf("%s: %s, firmware %s, serial %s\n", DEVNAME(sc), mn, fr, sn);
+
+done:
nvme_dmamem_free(sc, mem);
return (rv);
{
struct nvme_sqe *sqe = slot;
struct nvme_dmamem *mem = ccb->ccb_cookie;
- struct nvm_identify_controller *identify = NVME_DMA_KVA(mem);
-
- bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(mem),
- 0, sizeof(*identify), BUS_DMASYNC_PREREAD);
sqe->opcode = NVM_ADMIN_IDENTIFY;
htolem64(&sqe->entry.prp[0], NVME_DMA_DVA(mem));
htolem32(&sqe->cdw10, 1);
}
-void
-nvme_identify_done(struct nvme_softc *sc, struct nvme_ccb *ccb,
- struct nvme_cqe *cqe)
-{
- struct nvme_dmamem *mem = ccb->ccb_cookie;
- struct nvm_identify_controller *identify = NVME_DMA_KVA(mem);
- u_int64_t flags = lemtoh16(&cqe->flags);
-
- bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(mem),
- 0, sizeof(*identify), BUS_DMASYNC_POSTREAD);
-
- printf("%s: dnr %c m %c sqt %x sc %x\n", DEVNAME(sc),
- ISSET(flags, NVME_CQE_DNR) ? 'Y' : 'N',
- ISSET(flags, NVME_CQE_M) ? 'Y' : 'N',
- NVME_CQE_SQT(flags), NVME_CQE_SC(flags));
-
- printf("%s: identify %p sn %s mn %s fr %s\n", DEVNAME(sc), mem,
- identify->sn, identify->mn, identify->fr);
-}
-
int
nvme_ccbs_alloc(struct nvme_softc *sc, u_int nccbs)
{
-/* $OpenBSD: nvmereg.h,v 1.3 2014/04/15 10:28:07 dlg Exp $ */
+/* $OpenBSD: nvmereg.h,v 1.4 2014/04/16 00:26:59 dlg Exp $ */
/*
* Copyright (c) 2014 David Gwynne <dlg@openbsd.org>
u_int16_t flags;
#define NVME_CQE_DNR (1 << 15)
#define NVME_CQE_M (1 << 14)
-#define NVME_CQE_SQT(_f) (((_f) >> 8) & 0x7)
-#define NVME_CQE_SC(_f) (((_f) >> 1) & 0x7f)
+#define NVME_CQE_SCT(_f) ((_f) & (0x07 << 8))
+#define NVME_CQE_SCT_GENERIC (0x00 << 8)
+#define NVME_CQE_SCT_COMMAND (0x01 << 8)
+#define NVME_CQE_SCT_MEDIAERR (0x02 << 8)
+#define NVME_CQE_SCT_VENDOR (0x07 << 8)
+#define NVME_CQE_SC(_f) ((_f) & (0x7f << 1))
+#define NVME_CQE_SC_SUCCESS (0x00 << 1)
+#define NVME_CQE_SC_INVALID_OPCODE (0x01 << 1)
+#define NVME_CQE_SC_INVALID_FIELD (0x02 << 1)
+#define NVME_CQE_SC_CID_CONFLICT (0x03 << 1)
+#define NVME_CQE_SC_DATA_XFER_ERR (0x04 << 1)
+#define NVME_CQE_SC_ABRT_BY_NO_PWR (0x05 << 1)
+#define NVME_CQE_SC_INTERNAL_DEV_ERR (0x06 << 1)
+#define NVME_CQE_SC_CMD_ABRT_REQD (0x07 << 1)
+#define NVME_CQE_SC_CMD_ABDR_SQ_DEL (0x08 << 1)
+#define NVME_CQE_SC_CMD_ABDR_FUSE_ERR (0x09 << 1)
+#define NVME_CQE_SC_CMD_ABDR_FUSE_MISS (0x0a << 1)
+#define NVME_CQE_SC_INVALID_NS (0x0b << 1)
+#define NVME_CQE_SC_CMD_SEQ_ERR (0x0c << 1)
+#define NVME_CQE_SC_INVALID_LAST_SGL (0x0d << 1)
+#define NVME_CQE_SC_INVALID_NUM_SGL (0x0e << 1)
+#define NVME_CQE_SC_DATA_SGL_LEN (0x0f << 1)
+#define NVME_CQE_SC_MDATA_SGL_LEN (0x10 << 1)
+#define NVME_CQE_SC_SGL_TYPE_INVALID (0x11 << 1)
+#define NVME_CQE_SC_LBA_RANGE (0x80 << 1)
+#define NVME_CQE_SC_CAP_EXCEEDED (0x81 << 1)
+#define NVME_CQE_NS_NOT_RDY (0x82 << 1)
+#define NVME_CQE_RSV_CONFLICT (0x83 << 1)
#define NVME_CQE_PHASE (1 << 0)
} __packed __aligned(8);
u_int8_t sn[20]; /* Serial Number */
u_int8_t mn[40]; /* Model Number */
- u_int8_t fr[40]; /* Firmware Revision */
+ u_int8_t fr[8]; /* Firmware Revision */
u_int8_t rab; /* Recommended Arbitration Burst */
u_int8_t ieee[3]; /* IEEE OUI Identifier */