1 1.28 jmcneill /* $NetBSD: nvmevar.h,v 1.28 2022/08/14 12:08:57 jmcneill Exp $ */ 2 1.1 nonaka /* $OpenBSD: nvmevar.h,v 1.8 2016/04/14 11:18:32 dlg Exp $ */ 3 1.1 nonaka 4 1.1 nonaka /* 5 1.1 nonaka * Copyright (c) 2014 David Gwynne <dlg (at) openbsd.org> 6 1.1 nonaka * 7 1.1 nonaka * Permission to use, copy, modify, and distribute this software for any 8 1.1 nonaka * purpose with or without fee is hereby granted, provided that the above 9 1.1 nonaka * copyright notice and this permission notice appear in all copies. 10 1.1 nonaka * 11 1.1 nonaka * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 1.1 nonaka * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 1.1 nonaka * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 1.1 nonaka * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 1.1 nonaka * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 1.1 nonaka * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 1.1 nonaka * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 1.1 nonaka */ 19 1.1 nonaka 20 1.1 nonaka #include <sys/bus.h> 21 1.1 nonaka #include <sys/cpu.h> 22 1.1 nonaka #include <sys/device.h> 23 1.1 nonaka #include <sys/mutex.h> 24 1.1 nonaka #include <sys/pool.h> 25 1.1 nonaka #include <sys/queue.h> 26 1.27 mlelstv #include <sys/buf.h> 27 1.1 nonaka 28 1.1 nonaka struct nvme_dmamem { 29 1.1 nonaka bus_dmamap_t ndm_map; 30 1.1 nonaka bus_dma_segment_t ndm_seg; 31 1.1 nonaka size_t ndm_size; 32 1.1 nonaka void *ndm_kva; 33 1.1 nonaka }; 34 1.9 jdolecek #define NVME_DMA_MAP(_ndm) ((_ndm)->ndm_map) 35 1.9 jdolecek #define NVME_DMA_LEN(_ndm) ((_ndm)->ndm_map->dm_segs[0].ds_len) 36 1.9 jdolecek #define NVME_DMA_DVA(_ndm) ((uint64_t)(_ndm)->ndm_map->dm_segs[0].ds_addr) 37 1.9 jdolecek #define NVME_DMA_KVA(_ndm) ((void *)(_ndm)->ndm_kva) 38 1.1 nonaka 39 1.1 nonaka struct nvme_softc; 40 1.1 nonaka struct nvme_queue; 41 1.1 nonaka 42 1.12 jdolecek typedef void (*nvme_nnc_done)(void *, struct buf *, uint16_t, uint32_t); 43 1.4 jdolecek 44 1.1 nonaka struct nvme_ccb { 45 1.1 nonaka SIMPLEQ_ENTRY(nvme_ccb) ccb_entry; 46 1.1 nonaka 47 1.4 jdolecek /* DMA handles */ 48 1.1 nonaka bus_dmamap_t ccb_dmamap; 49 1.1 nonaka 50 1.4 jdolecek bus_addr_t ccb_prpl_off; 51 1.4 jdolecek uint64_t ccb_prpl_dva; 52 1.4 jdolecek uint64_t *ccb_prpl; 53 1.4 jdolecek 54 1.4 jdolecek /* command context */ 55 1.4 jdolecek uint16_t ccb_id; 56 1.1 nonaka void *ccb_cookie; 57 1.8 jdolecek #define NVME_CCB_FREE 0xbeefdeed 58 1.1 nonaka void (*ccb_done)(struct nvme_queue *, 59 1.1 nonaka struct nvme_ccb *, struct nvme_cqe *); 60 1.1 nonaka 61 1.4 jdolecek /* namespace context */ 62 1.4 jdolecek void *nnc_cookie; 63 1.4 jdolecek nvme_nnc_done nnc_done; 64 1.4 jdolecek uint16_t nnc_nsid; 65 1.4 jdolecek uint16_t nnc_flags; 66 1.4 jdolecek #define NVME_NS_CTX_F_READ __BIT(0) 67 1.4 jdolecek #define NVME_NS_CTX_F_POLL __BIT(1) 68 1.13 jdolecek #define NVME_NS_CTX_F_FUA __BIT(2) 69 1.1 nonaka 70 1.4 jdolecek struct buf *nnc_buf; 71 1.4 jdolecek daddr_t nnc_blkno; 72 1.4 jdolecek size_t nnc_datasize; 73 1.4 jdolecek int nnc_secsize; 74 1.1 nonaka }; 75 1.1 nonaka 76 1.1 nonaka struct nvme_queue { 77 1.1 nonaka struct nvme_softc *q_sc; 78 1.1 nonaka kmutex_t q_sq_mtx; 79 1.1 nonaka kmutex_t q_cq_mtx; 80 1.9 jdolecek struct nvme_dmamem *q_sq_dmamem; 81 1.9 jdolecek struct nvme_dmamem *q_cq_dmamem; 82 1.27 mlelstv struct nvme_dmamem *q_nvmmu_dmamem; /* for apple m1 nvme */ 83 1.27 mlelstv 84 1.1 nonaka bus_size_t q_sqtdbl; /* submission queue tail doorbell */ 85 1.1 nonaka bus_size_t q_cqhdbl; /* completion queue head doorbell */ 86 1.1 nonaka uint16_t q_id; 87 1.1 nonaka uint32_t q_entries; 88 1.1 nonaka uint32_t q_sq_tail; 89 1.1 nonaka uint32_t q_cq_head; 90 1.1 nonaka uint16_t q_cq_phase; 91 1.1 nonaka 92 1.1 nonaka kmutex_t q_ccb_mtx; 93 1.15 jdolecek kcondvar_t q_ccb_wait; /* wait for ccb avail/finish */ 94 1.15 jdolecek bool q_ccb_waiting; /* whether there are waiters */ 95 1.10 jdolecek uint16_t q_nccbs; /* total number of ccbs */ 96 1.1 nonaka struct nvme_ccb *q_ccbs; 97 1.4 jdolecek SIMPLEQ_HEAD(, nvme_ccb) q_ccb_list; 98 1.9 jdolecek struct nvme_dmamem *q_ccb_prpls; 99 1.1 nonaka }; 100 1.1 nonaka 101 1.1 nonaka struct nvme_namespace { 102 1.1 nonaka struct nvm_identify_namespace *ident; 103 1.1 nonaka device_t dev; 104 1.2 nonaka uint32_t flags; 105 1.2 nonaka #define NVME_NS_F_OPEN __BIT(0) 106 1.1 nonaka }; 107 1.1 nonaka 108 1.27 mlelstv struct nvme_ops { 109 1.27 mlelstv void (*op_enable)(struct nvme_softc *); 110 1.27 mlelstv 111 1.27 mlelstv int (*op_q_alloc)(struct nvme_softc *, 112 1.27 mlelstv struct nvme_queue *); 113 1.27 mlelstv void (*op_q_free)(struct nvme_softc *, 114 1.27 mlelstv struct nvme_queue *); 115 1.27 mlelstv 116 1.27 mlelstv uint32_t (*op_sq_enter)(struct nvme_softc *, 117 1.27 mlelstv struct nvme_queue *, struct nvme_ccb *); 118 1.27 mlelstv void (*op_sq_leave)(struct nvme_softc *, 119 1.27 mlelstv struct nvme_queue *, struct nvme_ccb *); 120 1.27 mlelstv uint32_t (*op_sq_enter_locked)(struct nvme_softc *, 121 1.27 mlelstv struct nvme_queue *, struct nvme_ccb *); 122 1.27 mlelstv void (*op_sq_leave_locked)(struct nvme_softc *, 123 1.27 mlelstv struct nvme_queue *, struct nvme_ccb *); 124 1.27 mlelstv 125 1.27 mlelstv void (*op_cq_done)(struct nvme_softc *, 126 1.27 mlelstv struct nvme_queue *, struct nvme_ccb *); 127 1.27 mlelstv }; 128 1.27 mlelstv 129 1.1 nonaka struct nvme_softc { 130 1.1 nonaka device_t sc_dev; 131 1.1 nonaka 132 1.27 mlelstv const struct nvme_ops *sc_ops; 133 1.27 mlelstv 134 1.1 nonaka bus_space_tag_t sc_iot; 135 1.1 nonaka bus_space_handle_t sc_ioh; 136 1.1 nonaka bus_size_t sc_ios; 137 1.1 nonaka bus_dma_tag_t sc_dmat; 138 1.1 nonaka 139 1.1 nonaka int (*sc_intr_establish)(struct nvme_softc *, 140 1.1 nonaka uint16_t qid, struct nvme_queue *); 141 1.1 nonaka int (*sc_intr_disestablish)(struct nvme_softc *, 142 1.1 nonaka uint16_t qid); 143 1.3 jdolecek void **sc_ih; /* interrupt handlers */ 144 1.3 jdolecek void **sc_softih; /* softintr handlers */ 145 1.1 nonaka 146 1.3 jdolecek u_int sc_rdy_to; /* RDY timeout */ 147 1.27 mlelstv size_t sc_mps; /* memory page size */ 148 1.3 jdolecek size_t sc_mdts; /* max data trasfer size */ 149 1.3 jdolecek u_int sc_max_sgl; /* max S/G segments */ 150 1.27 mlelstv u_int sc_dstrd; 151 1.1 nonaka 152 1.1 nonaka struct nvm_identify_controller 153 1.1 nonaka sc_identify; 154 1.1 nonaka 155 1.3 jdolecek u_int sc_nn; /* namespace count */ 156 1.1 nonaka struct nvme_namespace *sc_namespaces; 157 1.1 nonaka 158 1.1 nonaka bool sc_use_mq; 159 1.1 nonaka u_int sc_nq; /* # of io queue (sc_q) */ 160 1.1 nonaka struct nvme_queue *sc_admin_q; 161 1.1 nonaka struct nvme_queue **sc_q; 162 1.1 nonaka 163 1.1 nonaka uint32_t sc_flags; 164 1.1 nonaka #define NVME_F_ATTACHED __BIT(0) 165 1.2 nonaka #define NVME_F_OPEN __BIT(1) 166 1.16 nonaka 167 1.16 nonaka uint32_t sc_quirks; 168 1.16 nonaka #define NVME_QUIRK_DELAY_B4_CHK_RDY __BIT(0) 169 1.27 mlelstv #define NVME_QUIRK_NOMSI __BIT(1) 170 1.27 mlelstv 171 1.27 mlelstv char sc_modelname[81]; 172 1.1 nonaka }; 173 1.1 nonaka 174 1.1 nonaka #define lemtoh16(p) le16toh(*((uint16_t *)(p))) 175 1.1 nonaka #define lemtoh32(p) le32toh(*((uint32_t *)(p))) 176 1.1 nonaka #define lemtoh64(p) le64toh(*((uint64_t *)(p))) 177 1.1 nonaka #define htolem16(p, x) (*((uint16_t *)(p)) = htole16(x)) 178 1.1 nonaka #define htolem32(p, x) (*((uint32_t *)(p)) = htole32(x)) 179 1.1 nonaka #define htolem64(p, x) (*((uint64_t *)(p)) = htole64(x)) 180 1.1 nonaka 181 1.1 nonaka struct nvme_attach_args { 182 1.1 nonaka uint16_t naa_nsid; 183 1.11 jdolecek uint32_t naa_qentries; /* total number of queue slots */ 184 1.11 jdolecek uint32_t naa_maxphys; /* maximum device transfer size */ 185 1.27 mlelstv const char *naa_typename; /* identifier */ 186 1.1 nonaka }; 187 1.1 nonaka 188 1.1 nonaka int nvme_attach(struct nvme_softc *); 189 1.1 nonaka int nvme_detach(struct nvme_softc *, int flags); 190 1.6 pgoyette int nvme_rescan(device_t, const char *, const int *); 191 1.1 nonaka void nvme_childdet(device_t, device_t); 192 1.27 mlelstv int nvme_suspend(struct nvme_softc *); 193 1.27 mlelstv int nvme_resume(struct nvme_softc *); 194 1.1 nonaka int nvme_intr(void *); 195 1.7 jdolecek void nvme_softintr_intx(void *); 196 1.3 jdolecek int nvme_intr_msi(void *); 197 1.3 jdolecek void nvme_softintr_msi(void *); 198 1.1 nonaka 199 1.17 christos static __inline struct nvme_queue * 200 1.28 jmcneill nvme_get_q(struct nvme_softc *sc) 201 1.1 nonaka { 202 1.28 jmcneill return sc->sc_q[cpu_index(curcpu()) % sc->sc_nq]; 203 1.1 nonaka } 204 1.1 nonaka 205 1.1 nonaka /* 206 1.1 nonaka * namespace 207 1.1 nonaka */ 208 1.17 christos static __inline struct nvme_namespace * 209 1.1 nonaka nvme_ns_get(struct nvme_softc *sc, uint16_t nsid) 210 1.1 nonaka { 211 1.1 nonaka if (nsid == 0 || nsid - 1 >= sc->sc_nn) 212 1.1 nonaka return NULL; 213 1.1 nonaka return &sc->sc_namespaces[nsid - 1]; 214 1.1 nonaka } 215 1.1 nonaka 216 1.27 mlelstv #define nvme_read4(_s, _r) \ 217 1.27 mlelstv bus_space_read_4((_s)->sc_iot, (_s)->sc_ioh, (_r)) 218 1.27 mlelstv #define nvme_write4(_s, _r, _v) \ 219 1.27 mlelstv bus_space_write_4((_s)->sc_iot, (_s)->sc_ioh, (_r), (_v)) 220 1.27 mlelstv uint64_t 221 1.27 mlelstv nvme_read8(struct nvme_softc *, bus_size_t); 222 1.27 mlelstv void nvme_write8(struct nvme_softc *, bus_size_t, uint64_t); 223 1.27 mlelstv 224 1.27 mlelstv #define nvme_barrier(_s, _r, _l, _f) \ 225 1.27 mlelstv bus_space_barrier((_s)->sc_iot, (_s)->sc_ioh, (_r), (_l), (_f)) 226 1.27 mlelstv 227 1.27 mlelstv struct nvme_dmamem * 228 1.27 mlelstv nvme_dmamem_alloc(struct nvme_softc *, size_t); 229 1.27 mlelstv void nvme_dmamem_free(struct nvme_softc *, struct nvme_dmamem *); 230 1.27 mlelstv void nvme_dmamem_sync(struct nvme_softc *, struct nvme_dmamem *, int); 231 1.27 mlelstv 232 1.1 nonaka int nvme_ns_identify(struct nvme_softc *, uint16_t); 233 1.1 nonaka void nvme_ns_free(struct nvme_softc *, uint16_t); 234 1.4 jdolecek int nvme_ns_dobio(struct nvme_softc *, uint16_t, void *, 235 1.4 jdolecek struct buf *, void *, size_t, int, daddr_t, int, nvme_nnc_done); 236 1.15 jdolecek int nvme_ns_sync(struct nvme_softc *, uint16_t, int); 237 1.15 jdolecek int nvme_admin_getcache(struct nvme_softc *, int *); 238 1.27 mlelstv int nvme_admin_setcache(struct nvme_softc *, int); 239