1*3800fc35Sjmatthew /* $OpenBSD: nvmevar.h,v 1.31 2024/09/13 09:57:34 jmatthew Exp $ */ 2282c0692Sdlg 3282c0692Sdlg /* 4282c0692Sdlg * Copyright (c) 2014 David Gwynne <dlg@openbsd.org> 5282c0692Sdlg * 6282c0692Sdlg * Permission to use, copy, modify, and distribute this software for any 7282c0692Sdlg * purpose with or without fee is hereby granted, provided that the above 8282c0692Sdlg * copyright notice and this permission notice appear in all copies. 9282c0692Sdlg * 10282c0692Sdlg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11282c0692Sdlg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12282c0692Sdlg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13282c0692Sdlg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14282c0692Sdlg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15282c0692Sdlg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16282c0692Sdlg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17282c0692Sdlg */ 18282c0692Sdlg 19*3800fc35Sjmatthew #include <sys/sensors.h> 20*3800fc35Sjmatthew 2103d86467Sjmatthew #define NVME_IO_Q 1 2203d86467Sjmatthew #define NVME_HIB_Q 2 23767e8532Skrw #define NVME_MAXPHYS (128 * 1024) 2403d86467Sjmatthew 25282c0692Sdlg struct nvme_dmamem { 26282c0692Sdlg bus_dmamap_t ndm_map; 27282c0692Sdlg bus_dma_segment_t ndm_seg; 28282c0692Sdlg size_t ndm_size; 29282c0692Sdlg caddr_t ndm_kva; 30282c0692Sdlg }; 31282c0692Sdlg #define NVME_DMA_MAP(_ndm) ((_ndm)->ndm_map) 32448b3c09Sdlg #define NVME_DMA_LEN(_ndm) ((_ndm)->ndm_map->dm_segs[0].ds_len) 33282c0692Sdlg #define NVME_DMA_DVA(_ndm) ((u_int64_t)(_ndm)->ndm_map->dm_segs[0].ds_addr) 34282c0692Sdlg #define NVME_DMA_KVA(_ndm) ((void *)(_ndm)->ndm_kva) 35282c0692Sdlg 36448b3c09Sdlg struct nvme_softc; 37448b3c09Sdlg 38448b3c09Sdlg struct nvme_ccb { 39448b3c09Sdlg SIMPLEQ_ENTRY(nvme_ccb) ccb_entry; 40448b3c09Sdlg 41448b3c09Sdlg bus_dmamap_t ccb_dmamap; 42448b3c09Sdlg 43448b3c09Sdlg void *ccb_cookie; 44448b3c09Sdlg void (*ccb_done)(struct nvme_softc *sc, 45448b3c09Sdlg struct nvme_ccb *, struct nvme_cqe *); 46448b3c09Sdlg 475313ab17Sdlg bus_addr_t ccb_prpl_off; 485313ab17Sdlg u_int64_t ccb_prpl_dva; 495313ab17Sdlg u_int64_t *ccb_prpl; 505313ab17Sdlg 51448b3c09Sdlg u_int16_t ccb_id; 52448b3c09Sdlg }; 53448b3c09Sdlg SIMPLEQ_HEAD(nvme_ccb_list, nvme_ccb); 54448b3c09Sdlg 55282c0692Sdlg struct nvme_queue { 56448b3c09Sdlg struct mutex q_sq_mtx; 57448b3c09Sdlg struct mutex q_cq_mtx; 58282c0692Sdlg struct nvme_dmamem *q_sq_dmamem; 59282c0692Sdlg struct nvme_dmamem *q_cq_dmamem; 60d7a6b8c3Sdlg struct nvme_dmamem *q_nvmmu_dmamem; /* for aplns(4) */ 61282c0692Sdlg bus_size_t q_sqtdbl; /* submission queue tail doorbell */ 62282c0692Sdlg bus_size_t q_cqhdbl; /* completion queue head doorbell */ 63ba2fdfebSdlg u_int16_t q_id; 64448b3c09Sdlg u_int32_t q_entries; 65448b3c09Sdlg u_int32_t q_sq_tail; 66448b3c09Sdlg u_int32_t q_cq_head; 67448b3c09Sdlg u_int16_t q_cq_phase; 68282c0692Sdlg }; 69282c0692Sdlg 70bc407f60Sdlg struct nvme_namespace { 71bc407f60Sdlg struct nvm_identify_namespace *ident; 72bc407f60Sdlg }; 73bc407f60Sdlg 740ccab0b0Sdlg struct nvme_ops { 750ccab0b0Sdlg void (*op_enable)(struct nvme_softc *); 760ccab0b0Sdlg 770ccab0b0Sdlg int (*op_q_alloc)(struct nvme_softc *, 780ccab0b0Sdlg struct nvme_queue *); 790ccab0b0Sdlg void (*op_q_free)(struct nvme_softc *, 800ccab0b0Sdlg struct nvme_queue *); 810ccab0b0Sdlg 820ccab0b0Sdlg uint32_t (*op_sq_enter)(struct nvme_softc *, 830ccab0b0Sdlg struct nvme_queue *, struct nvme_ccb *); 840ccab0b0Sdlg void (*op_sq_leave)(struct nvme_softc *, 850ccab0b0Sdlg struct nvme_queue *, struct nvme_ccb *); 860ccab0b0Sdlg uint32_t (*op_sq_enter_locked)(struct nvme_softc *, 870ccab0b0Sdlg struct nvme_queue *, struct nvme_ccb *); 880ccab0b0Sdlg void (*op_sq_leave_locked)(struct nvme_softc *, 890ccab0b0Sdlg struct nvme_queue *, struct nvme_ccb *); 900ccab0b0Sdlg 910ccab0b0Sdlg void (*op_cq_done)(struct nvme_softc *, 920ccab0b0Sdlg struct nvme_queue *, struct nvme_ccb *); 930ccab0b0Sdlg }; 940ccab0b0Sdlg 95282c0692Sdlg struct nvme_softc { 96282c0692Sdlg struct device sc_dev; 97282c0692Sdlg 980ccab0b0Sdlg const struct nvme_ops *sc_ops; 99f07c0e41Skettenis u_int sc_openings; 1000ccab0b0Sdlg 101282c0692Sdlg bus_space_tag_t sc_iot; 102282c0692Sdlg bus_space_handle_t sc_ioh; 103282c0692Sdlg bus_size_t sc_ios; 104282c0692Sdlg bus_dma_tag_t sc_dmat; 105282c0692Sdlg 106282c0692Sdlg void *sc_ih; 107282c0692Sdlg 108282c0692Sdlg u_int sc_rdy_to; 109448b3c09Sdlg size_t sc_mps; 110448b3c09Sdlg size_t sc_mdts; 111abed8b8fSkrw u_int sc_max_prpl; 112aa5ddcf9Ssf u_int sc_dstrd; 113282c0692Sdlg 11417756a2bSdlg struct nvm_identify_controller 11517756a2bSdlg sc_identify; 11617756a2bSdlg 11717756a2bSdlg u_int sc_nn; 118bc407f60Sdlg struct nvme_namespace *sc_namespaces; 11917756a2bSdlg 120282c0692Sdlg struct nvme_queue *sc_admin_q; 121282c0692Sdlg struct nvme_queue *sc_q; 12203d86467Sjmatthew struct nvme_queue *sc_hib_q; 123448b3c09Sdlg 124448b3c09Sdlg struct mutex sc_ccb_mtx; 125448b3c09Sdlg struct nvme_ccb *sc_ccbs; 126448b3c09Sdlg struct nvme_ccb_list sc_ccb_list; 1275313ab17Sdlg struct nvme_dmamem *sc_ccb_prpls; 128448b3c09Sdlg struct scsi_iopool sc_iopool; 1297f4636ceSkrw struct rwlock sc_lock; 1307f4636ceSkrw struct scsibus_softc *sc_scsibus; 131*3800fc35Sjmatthew 132*3800fc35Sjmatthew struct ksensordev sc_sensordev; 133*3800fc35Sjmatthew struct ksensor sc_temp_sensor; 134*3800fc35Sjmatthew struct ksensor sc_spare_sensor; 135*3800fc35Sjmatthew struct ksensor sc_usage_sensor; 136282c0692Sdlg }; 137282c0692Sdlg 138a4b5505eSdlg #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname) 139a4b5505eSdlg 140282c0692Sdlg int nvme_attach(struct nvme_softc *); 1415313ab17Sdlg int nvme_activate(struct nvme_softc *, int); 142282c0692Sdlg int nvme_intr(void *); 143eb77e636Sdlg int nvme_intr_intx(void *); 144282c0692Sdlg 145ef9c7800Sdlg #define nvme_read4(_s, _r) \ 146ef9c7800Sdlg bus_space_read_4((_s)->sc_iot, (_s)->sc_ioh, (_r)) 147ef9c7800Sdlg #define nvme_write4(_s, _r, _v) \ 148ef9c7800Sdlg bus_space_write_4((_s)->sc_iot, (_s)->sc_ioh, (_r), (_v)) 149ef9c7800Sdlg 1509fdd10b7Sdlg u_int64_t 1519fdd10b7Sdlg nvme_read8(struct nvme_softc *, bus_size_t); 152a30550dbSdlg void nvme_write8(struct nvme_softc *, bus_size_t, u_int64_t); 153a30550dbSdlg 154738b3a9aSdlg #define nvme_barrier(_s, _r, _l, _f) \ 155738b3a9aSdlg bus_space_barrier((_s)->sc_iot, (_s)->sc_ioh, (_r), (_l), (_f)) 156738b3a9aSdlg 157a4b5505eSdlg struct nvme_dmamem * 158a4b5505eSdlg nvme_dmamem_alloc(struct nvme_softc *, size_t); 159a4b5505eSdlg void nvme_dmamem_free(struct nvme_softc *, struct nvme_dmamem *); 160a4b5505eSdlg void nvme_dmamem_sync(struct nvme_softc *, struct nvme_dmamem *, int); 161