FreeBSD kernel CAM code
mmc_sim.c
Go to the documentation of this file.
1/*-
2 * Copyright (c) 2020-2021 Emmanuel Vadot <manu@FreeBSD.org>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
20 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * $FreeBSD$
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD$");
30
31#include <sys/param.h>
32#include <sys/kernel.h>
33#include <sys/systm.h>
34#include <sys/malloc.h>
35#include <sys/mutex.h>
36
37#include <cam/cam.h>
38#include <cam/cam_ccb.h>
39#include <cam/cam_debug.h>
40#include <cam/cam_sim.h>
41#include <cam/cam_xpt_sim.h>
42#include <cam/mmc/mmc_sim.h>
43
44#include "mmc_sim_if.h"
45
46static void
48{
49 struct mmc_sim *mmc_sim;
50
52 MMC_SIM_CAM_POLL(mmc_sim->dev);
53}
54
55static void
56mmc_sim_task(void *arg, int pending)
57{
58 struct mmc_sim *mmc_sim;
59 struct ccb_trans_settings *cts;
60 int rv;
61
62 mmc_sim = arg;
63
64 if (mmc_sim->ccb == NULL)
65 return;
66
67 cts = &mmc_sim->ccb->cts;
68 switch (mmc_sim->ccb->ccb_h.func_code) {
70 rv = MMC_SIM_GET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
71 if (rv != 0)
73 else
75 break;
77 rv = MMC_SIM_SET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
78 if (rv != 0)
80 else
82 break;
83 default:
84 panic("Unsupported ccb func %x\n", mmc_sim->ccb->ccb_h.func_code);
85 break;
86 }
87
89 mmc_sim->ccb = NULL;
90}
91
92
93static void
95{
96 struct mmc_sim *mmc_sim;
97 struct ccb_trans_settings_mmc mmc;
98 int rv;
99
100 mmc_sim = cam_sim_softc(sim);
101
102 mtx_assert(&mmc_sim->mtx, MA_OWNED);
103
104 if (mmc_sim->ccb != NULL) {
106 xpt_done(ccb);
107 return;
108 }
109
110 switch (ccb->ccb_h.func_code) {
111 case XPT_PATH_INQ:
112 rv = MMC_SIM_GET_TRAN_SETTINGS(mmc_sim->dev, &mmc);
113 if (rv != 0) {
115 } else {
116 mmc_path_inq(&ccb->cpi, "Deglitch Networks",
117 sim, mmc.host_max_data);
118 }
119 break;
121 {
122 struct ccb_trans_settings *cts = &ccb->cts;
123
124 rv = MMC_SIM_GET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
125 if (rv != 0)
127 else {
128 cts->protocol = PROTO_MMCSD;
129 cts->protocol_version = 1;
130 cts->transport = XPORT_MMCSD;
131 cts->transport_version = 1;
132 cts->xport_specific.valid = 0;
134 }
135 break;
136 }
138 {
140 mmc_sim->ccb = ccb;
141 taskqueue_enqueue(taskqueue_thread, &mmc_sim->sim_task);
142 return;
143 /* NOTREACHED */
144 break;
145 }
147 {
148 struct ccb_trans_settings *cts = &ccb->cts;
149
150 rv = MMC_SIM_SET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
151 if (rv != 0)
153 else
155 break;
156 }
158 {
160 mmc_sim->ccb = ccb;
161 taskqueue_enqueue(taskqueue_thread, &mmc_sim->sim_task);
162 return;
163 /* NOTREACHED */
164 break;
165 }
166 case XPT_RESET_BUS:
168 break;
169 case XPT_MMC_IO:
170 {
171 rv = MMC_SIM_CAM_REQUEST(mmc_sim->dev, ccb);
172 if (rv != 0)
174 return;
175 /* NOTREACHED */
176 break;
177 }
178 default:
180 break;
181 }
182 xpt_done(ccb);
183 return;
184}
185
186int
187mmc_cam_sim_alloc(device_t dev, const char *name, struct mmc_sim *mmc_sim)
188{
189 kobjop_desc_t kobj_desc;
190 kobj_method_t *kobj_method;
191
192 mmc_sim->dev = dev;
193
194 if ((mmc_sim->devq = cam_simq_alloc(1)) == NULL) {
195 goto fail;
196 }
197
198 snprintf(mmc_sim->name, sizeof(mmc_sim->name), "%s_sim", name);
199 mtx_init(&mmc_sim->mtx, mmc_sim->name, NULL, MTX_DEF);
200
201 /* Provide sim_poll hook only if the device has the poll method. */
202 kobj_desc = &mmc_sim_cam_poll_desc;
203 kobj_method = kobj_lookup_method(((kobj_t)dev)->ops->cls, NULL,
204 kobj_desc);
206 kobj_method == &kobj_desc->deflt ? NULL : mmc_cam_default_poll,
207 mmc_sim->name, mmc_sim, device_get_unit(dev),
208 &mmc_sim->mtx, 1, 1, mmc_sim->devq);
209
210 if (mmc_sim->sim == NULL) {
212 device_printf(dev, "cannot allocate CAM SIM\n");
213 goto fail;
214 }
215
216 mtx_lock(&mmc_sim->mtx);
217 if (xpt_bus_register(mmc_sim->sim, dev, 0) != 0) {
218 device_printf(dev, "cannot register SCSI pass-through bus\n");
219 cam_sim_free(mmc_sim->sim, FALSE);
221 mtx_unlock(&mmc_sim->mtx);
222 goto fail;
223 }
224
225 mtx_unlock(&mmc_sim->mtx);
226 TASK_INIT(&mmc_sim->sim_task, 0, mmc_sim_task, mmc_sim);
227
228 return (0);
229
230fail:
232 return (1);
233}
234
235void
237{
238
239 if (mmc_sim->sim != NULL) {
240 mtx_lock(&mmc_sim->mtx);
242 cam_sim_free(mmc_sim->sim, FALSE);
243 mtx_unlock(&mmc_sim->mtx);
244 }
245
246 if (mmc_sim->devq != NULL)
248}
249
250void
252{
253
255}
@ CAM_REQ_INVALID
Definition: cam.h:152
@ CAM_BUSY
Definition: cam.h:149
@ CAM_REQ_CMP
Definition: cam.h:137
@ CAM_SIM_QUEUED
Definition: cam.h:296
@ PROTO_MMCSD
Definition: cam_ccb.h:285
@ XPORT_MMCSD
Definition: cam_ccb.h:302
@ XPT_RESET_BUS
Definition: cam_ccb.h:174
@ XPT_GET_TRAN_SETTINGS
Definition: cam_ccb.h:183
@ XPT_MMC_GET_TRAN_SETTINGS
Definition: cam_ccb.h:257
@ XPT_MMC_IO
Definition: cam_ccb.h:220
@ XPT_SET_TRAN_SETTINGS
Definition: cam_ccb.h:188
@ XPT_PATH_INQ
Definition: cam_ccb.h:147
@ XPT_MMC_SET_TRAN_SETTINGS
Definition: cam_ccb.h:256
struct cam_sim * cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll, const char *sim_name, void *softc, u_int32_t unit, struct mtx *mtx, int max_dev_transactions, int max_tagged_dev_transactions, struct cam_devq *queue)
allocate a new sim and fill in the details
Definition: cam_sim.c:103
struct cam_devq * cam_simq_alloc(u_int32_t max_sim_transactions)
Definition: cam_sim.c:55
void cam_sim_free(struct cam_sim *sim, int free_devq)
frees up the sim
Definition: cam_sim.c:144
void cam_simq_free(struct cam_devq *devq)
Definition: cam_sim.c:61
static __inline u_int32_t cam_sim_path(const struct cam_sim *sim)
Definition: cam_sim.h:109
static __inline void * cam_sim_softc(const struct cam_sim *sim)
Definition: cam_sim.h:121
int xpt_bus_deregister(path_id_t pathid)
Definition: cam_xpt.c:4065
void xpt_done(union ccb *done_ccb)
Definition: cam_xpt.c:4562
int xpt_bus_register(struct cam_sim *sim, device_t parent, uint32_t bus)
Definition: cam_xpt.c:3965
void mmc_path_inq(struct ccb_pathinq *cpi, const char *hba, const struct cam_sim *sim, size_t maxio)
Definition: mmc_xpt.c:1216
void mmccam_start_discovery(struct cam_sim *sim)
Definition: mmc_xpt.c:403
static void mmc_sim_task(void *arg, int pending)
Definition: mmc_sim.c:56
static void mmc_cam_sim_default_action(struct cam_sim *sim, union ccb *ccb)
Definition: mmc_sim.c:94
void mmc_cam_sim_free(struct mmc_sim *mmc_sim)
Definition: mmc_sim.c:236
__FBSDID("$FreeBSD$")
static void mmc_cam_default_poll(struct cam_sim *sim)
Definition: mmc_sim.c:47
void mmc_cam_sim_discover(struct mmc_sim *mmc_sim)
Definition: mmc_sim.c:251
int mmc_cam_sim_alloc(device_t dev, const char *name, struct mmc_sim *mmc_sim)
Definition: mmc_sim.c:187
union ccb * ccb
Definition: mmc_sim_if.m:53
struct ccb_trans_settings_mmc * cts
Definition: mmc_sim_if.m:43
INTERFACE mmc_sim
Definition: mmc_sim_if.m:39
xpt_opcode func_code
Definition: cam_ccb.h:362
u_int32_t status
Definition: cam_ccb.h:363
uint32_t host_max_data
Definition: cam_ccb.h:1101
device_t dev
Definition: mmc_sim.h:39
struct mtx mtx
Definition: mmc_sim.h:35
struct cam_sim * sim
Definition: mmc_sim.h:38
char name[16]
Definition: mmc_sim.h:36
struct cam_devq * devq
Definition: mmc_sim.h:37
struct task sim_task
Definition: mmc_sim.h:40
union ccb * ccb
Definition: mmc_sim.h:41
Definition: cam_ccb.h:1345
struct ccb_trans_settings cts
Definition: cam_ccb.h:1357
struct ccb_hdr ccb_h
Definition: cam_ccb.h:1346
struct ccb_pathinq cpi
Definition: cam_ccb.h:1350