1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2022-2024 Chelsio Communications, Inc.
5 * Written by: John Baldwin <jhb@FreeBSD.org>
6 */
7
8#ifndef __NVMF_TRANSPORT_INTERNAL_H__
9#define	__NVMF_TRANSPORT_INTERNAL_H__
10
11#include <sys/memdesc.h>
12
13/*
14 * Interface between the transport-independent APIs in
15 * nvmf_transport.c and individual transports.
16 */
17
18struct module;
19struct nvmf_io_request;
20
21struct nvmf_transport_ops {
22	/* Queue pair management. */
23	struct nvmf_qpair *(*allocate_qpair)(bool controller,
24	    const struct nvmf_handoff_qpair_params *params);
25	void (*free_qpair)(struct nvmf_qpair *qp);
26
27	/* Capsule operations. */
28	struct nvmf_capsule *(*allocate_capsule)(struct nvmf_qpair *qp,
29	    int how);
30	void (*free_capsule)(struct nvmf_capsule *nc);
31	int (*transmit_capsule)(struct nvmf_capsule *nc);
32	uint8_t (*validate_command_capsule)(struct nvmf_capsule *nc);
33
34	/* Transferring controller data. */
35	size_t (*capsule_data_len)(const struct nvmf_capsule *nc);
36	int (*receive_controller_data)(struct nvmf_capsule *nc,
37	    uint32_t data_offset, struct nvmf_io_request *io);
38	u_int (*send_controller_data)(struct nvmf_capsule *nc,
39	    uint32_t data_offset, struct mbuf *m, size_t len);
40
41	enum nvmf_trtype trtype;
42	int priority;
43};
44
45/* Either an Admin or I/O Submission/Completion Queue pair. */
46struct nvmf_qpair {
47	struct nvmf_transport *nq_transport;
48	struct nvmf_transport_ops *nq_ops;
49	bool nq_controller;
50
51	/* Callback to invoke for a received capsule. */
52	nvmf_capsule_receive_t *nq_receive;
53	void *nq_receive_arg;
54
55	/* Callback to invoke for an error. */
56	nvmf_qpair_error_t *nq_error;
57	void *nq_error_arg;
58
59	bool nq_admin;
60};
61
62struct nvmf_io_request {
63	/*
64	 * Data buffer contains io_len bytes in the backing store
65	 * described by mem.
66	 */
67	struct memdesc io_mem;
68	size_t	io_len;
69	nvmf_io_complete_t *io_complete;
70	void	*io_complete_arg;
71};
72
73/*
74 * Fabrics Command and Response Capsules.  The Fabrics host
75 * (initiator) and controller (target) drivers work with capsules that
76 * are transmitted and received by a specific transport.
77 */
78struct nvmf_capsule {
79	struct nvmf_qpair *nc_qpair;
80
81	/* Either a SQE or CQE. */
82	union {
83		struct nvme_command nc_sqe;
84		struct nvme_completion nc_cqe;
85	};
86	int	nc_qe_len;
87
88	/*
89	 * Is SQHD in received capsule valid?  False for locally-
90	 * synthesized responses.
91	 */
92	bool	nc_sqhd_valid;
93
94	bool	nc_send_data;
95	struct nvmf_io_request nc_data;
96};
97
98static void __inline
99nvmf_qpair_error(struct nvmf_qpair *nq, int error)
100{
101	nq->nq_error(nq->nq_error_arg, error);
102}
103
104static void __inline
105nvmf_capsule_received(struct nvmf_qpair *nq, struct nvmf_capsule *nc)
106{
107	nq->nq_receive(nq->nq_receive_arg, nc);
108}
109
110static void __inline
111nvmf_complete_io_request(struct nvmf_io_request *io, size_t xfered, int error)
112{
113	io->io_complete(io->io_complete_arg, xfered, error);
114}
115
116int	nvmf_transport_module_handler(struct module *, int, void *);
117
118#define	NVMF_TRANSPORT(name, ops)					\
119static moduledata_t nvmf_transport_##name##_mod = {			\
120	"nvmf/" #name,							\
121	nvmf_transport_module_handler,					\
122	&(ops)								\
123};									\
124DECLARE_MODULE(nvmf_transport_##name, nvmf_transport_##name##_mod,	\
125    SI_SUB_DRIVERS, SI_ORDER_ANY);					\
126MODULE_DEPEND(nvmf_transport_##name, nvmf_transport, 1, 1, 1)
127
128#endif /* !__NVMF_TRANSPORT_INTERNAL_H__ */
129