Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/cam/mmc/mmc_sim.c
39481 views
1
/*-
2
* Copyright (c) 2020-2021 Emmanuel Vadot <[email protected]>
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
26
#include <sys/param.h>
27
#include <sys/kernel.h>
28
#include <sys/systm.h>
29
#include <sys/malloc.h>
30
#include <sys/mutex.h>
31
32
#include <cam/cam.h>
33
#include <cam/cam_ccb.h>
34
#include <cam/cam_debug.h>
35
#include <cam/cam_sim.h>
36
#include <cam/cam_xpt_sim.h>
37
#include <cam/mmc/mmc_sim.h>
38
39
#include "mmc_sim_if.h"
40
41
static void
42
mmc_cam_default_poll(struct cam_sim *sim)
43
{
44
struct mmc_sim *mmc_sim;
45
46
mmc_sim = cam_sim_softc(sim);
47
MMC_SIM_CAM_POLL(mmc_sim->dev);
48
}
49
50
static void
51
mmc_sim_task(void *arg, int pending)
52
{
53
struct mmc_sim *mmc_sim;
54
struct ccb_trans_settings *cts;
55
int rv;
56
57
mmc_sim = arg;
58
59
if (mmc_sim->ccb == NULL)
60
return;
61
62
cts = &mmc_sim->ccb->cts;
63
switch (mmc_sim->ccb->ccb_h.func_code) {
64
case XPT_MMC_GET_TRAN_SETTINGS:
65
rv = MMC_SIM_GET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
66
if (rv != 0)
67
mmc_sim->ccb->ccb_h.status = CAM_REQ_INVALID;
68
else
69
mmc_sim->ccb->ccb_h.status = CAM_REQ_CMP;
70
break;
71
case XPT_MMC_SET_TRAN_SETTINGS:
72
rv = MMC_SIM_SET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
73
if (rv != 0)
74
mmc_sim->ccb->ccb_h.status = CAM_REQ_INVALID;
75
else
76
mmc_sim->ccb->ccb_h.status = CAM_REQ_CMP;
77
break;
78
default:
79
panic("Unsupported ccb func %x\n", mmc_sim->ccb->ccb_h.func_code);
80
break;
81
}
82
83
xpt_done(mmc_sim->ccb);
84
mmc_sim->ccb = NULL;
85
}
86
87
88
static void
89
mmc_cam_sim_default_action(struct cam_sim *sim, union ccb *ccb)
90
{
91
struct mmc_sim *mmc_sim;
92
struct ccb_trans_settings_mmc mmc;
93
int rv;
94
95
mmc_sim = cam_sim_softc(sim);
96
97
mtx_assert(&mmc_sim->mtx, MA_OWNED);
98
99
if (mmc_sim->ccb != NULL) {
100
ccb->ccb_h.status = CAM_BUSY;
101
xpt_done(ccb);
102
return;
103
}
104
105
switch (ccb->ccb_h.func_code) {
106
case XPT_PATH_INQ:
107
rv = MMC_SIM_GET_TRAN_SETTINGS(mmc_sim->dev, &mmc);
108
if (rv != 0) {
109
ccb->ccb_h.status = CAM_REQ_INVALID;
110
} else {
111
mmc_path_inq(&ccb->cpi, "Deglitch Networks",
112
sim, mmc.host_max_data * MMC_SECTOR_SIZE);
113
}
114
break;
115
case XPT_GET_TRAN_SETTINGS:
116
{
117
struct ccb_trans_settings *cts = &ccb->cts;
118
119
rv = MMC_SIM_GET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
120
if (rv != 0)
121
ccb->ccb_h.status = CAM_REQ_INVALID;
122
else {
123
cts->protocol = PROTO_MMCSD;
124
cts->protocol_version = 1;
125
cts->transport = XPORT_MMCSD;
126
cts->transport_version = 1;
127
cts->xport_specific.valid = 0;
128
ccb->ccb_h.status = CAM_REQ_CMP;
129
}
130
break;
131
}
132
case XPT_MMC_GET_TRAN_SETTINGS:
133
{
134
ccb->ccb_h.status = CAM_SIM_QUEUED;
135
mmc_sim->ccb = ccb;
136
taskqueue_enqueue(taskqueue_thread, &mmc_sim->sim_task);
137
return;
138
/* NOTREACHED */
139
break;
140
}
141
case XPT_SET_TRAN_SETTINGS:
142
{
143
struct ccb_trans_settings *cts = &ccb->cts;
144
145
rv = MMC_SIM_SET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
146
if (rv != 0)
147
ccb->ccb_h.status = CAM_REQ_INVALID;
148
else
149
ccb->ccb_h.status = CAM_REQ_CMP;
150
break;
151
}
152
case XPT_MMC_SET_TRAN_SETTINGS:
153
{
154
ccb->ccb_h.status = CAM_SIM_QUEUED;
155
mmc_sim->ccb = ccb;
156
taskqueue_enqueue(taskqueue_thread, &mmc_sim->sim_task);
157
return;
158
/* NOTREACHED */
159
break;
160
}
161
case XPT_RESET_BUS:
162
ccb->ccb_h.status = CAM_REQ_CMP;
163
break;
164
case XPT_MMC_IO:
165
{
166
rv = MMC_SIM_CAM_REQUEST(mmc_sim->dev, ccb);
167
if (rv != 0)
168
ccb->ccb_h.status = CAM_SIM_QUEUED;
169
return;
170
/* NOTREACHED */
171
break;
172
}
173
default:
174
ccb->ccb_h.status = CAM_REQ_INVALID;
175
break;
176
}
177
xpt_done(ccb);
178
return;
179
}
180
181
int
182
mmc_cam_sim_alloc(device_t dev, const char *name, struct mmc_sim *mmc_sim)
183
{
184
kobjop_desc_t kobj_desc;
185
kobj_method_t *kobj_method;
186
187
mmc_sim->dev = dev;
188
189
if ((mmc_sim->devq = cam_simq_alloc(1)) == NULL) {
190
goto fail;
191
}
192
193
snprintf(mmc_sim->name, sizeof(mmc_sim->name), "%s_sim", name);
194
mtx_init(&mmc_sim->mtx, mmc_sim->name, NULL, MTX_DEF);
195
196
/* Provide sim_poll hook only if the device has the poll method. */
197
kobj_desc = &mmc_sim_cam_poll_desc;
198
kobj_method = kobj_lookup_method(((kobj_t)dev)->ops->cls, NULL,
199
kobj_desc);
200
mmc_sim->sim = cam_sim_alloc(mmc_cam_sim_default_action,
201
kobj_method == &kobj_desc->deflt ? NULL : mmc_cam_default_poll,
202
mmc_sim->name, mmc_sim, device_get_unit(dev),
203
&mmc_sim->mtx, 1, 1, mmc_sim->devq);
204
205
if (mmc_sim->sim == NULL) {
206
cam_simq_free(mmc_sim->devq);
207
device_printf(dev, "cannot allocate CAM SIM\n");
208
goto fail;
209
}
210
211
mtx_lock(&mmc_sim->mtx);
212
if (xpt_bus_register(mmc_sim->sim, dev, 0) != 0) {
213
device_printf(dev, "cannot register SCSI pass-through bus\n");
214
cam_sim_free(mmc_sim->sim, FALSE);
215
cam_simq_free(mmc_sim->devq);
216
mtx_unlock(&mmc_sim->mtx);
217
goto fail;
218
}
219
220
mtx_unlock(&mmc_sim->mtx);
221
TASK_INIT(&mmc_sim->sim_task, 0, mmc_sim_task, mmc_sim);
222
223
return (0);
224
225
fail:
226
mmc_cam_sim_free(mmc_sim);
227
return (1);
228
}
229
230
void
231
mmc_cam_sim_free(struct mmc_sim *mmc_sim)
232
{
233
234
if (mmc_sim->sim != NULL) {
235
mtx_lock(&mmc_sim->mtx);
236
xpt_bus_deregister(cam_sim_path(mmc_sim->sim));
237
cam_sim_free(mmc_sim->sim, FALSE);
238
mtx_unlock(&mmc_sim->mtx);
239
}
240
241
if (mmc_sim->devq != NULL)
242
cam_simq_free(mmc_sim->devq);
243
}
244
245
void
246
mmc_cam_sim_discover(struct mmc_sim *mmc_sim)
247
{
248
249
mmccam_start_discovery(mmc_sim->sim);
250
}
251
252