This source file includes following definitions.
- sdmmc_scsi_attach
- sdmmc_scsi_detach
- sdmmc_alloc_ccbs
- sdmmc_free_ccbs
- sdmmc_get_ccb
- sdmmc_put_ccb
- sdmmc_scsi_decode_rw
- sdmmc_scsi_cmd
- sdmmc_start_xs
- sdmmc_complete_xs
- sdmmc_done_xs
- sdmmc_stimeout
- sdmmc_scsi_minphys
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <sys/param.h>
22 #include <sys/buf.h>
23 #include <sys/kernel.h>
24 #include <sys/malloc.h>
25 #include <sys/proc.h>
26 #include <sys/systm.h>
27
28 #include <scsi/scsi_all.h>
29 #include <scsi/scsi_disk.h>
30 #include <scsi/scsiconf.h>
31
32 #include <dev/sdmmc/sdmmc_scsi.h>
33 #include <dev/sdmmc/sdmmcvar.h>
34
35 #define SDMMC_SCSIID_HOST 0x00
36 #define SDMMC_SCSIID_MAX 0x0f
37
38 #define SDMMC_SCSI_MAXCMDS 8
39
40 struct sdmmc_scsi_target {
41 struct sdmmc_function *card;
42 };
43
44 struct sdmmc_ccb {
45 struct sdmmc_scsi_softc *ccb_scbus;
46 struct scsi_xfer *ccb_xs;
47 int ccb_flags;
48 #define SDMMC_CCB_F_ERR 0x0001
49 void (*ccb_done)(struct sdmmc_ccb *);
50 u_int32_t ccb_blockno;
51 u_int32_t ccb_blockcnt;
52 volatile enum {
53 SDMMC_CCB_FREE,
54 SDMMC_CCB_READY,
55 SDMMC_CCB_QUEUED
56 } ccb_state;
57 struct sdmmc_command ccb_cmd;
58 struct sdmmc_task ccb_task;
59 TAILQ_ENTRY(sdmmc_ccb) ccb_link;
60 };
61
62 TAILQ_HEAD(sdmmc_ccb_list, sdmmc_ccb);
63
64 struct sdmmc_scsi_softc {
65 struct scsi_adapter sc_adapter;
66 struct scsi_link sc_link;
67 struct device *sc_child;
68 struct sdmmc_scsi_target *sc_tgt;
69 int sc_ntargets;
70 struct sdmmc_ccb *sc_ccbs;
71 struct sdmmc_ccb_list sc_ccb_freeq;
72 struct sdmmc_ccb_list sc_ccb_runq;
73 };
74
75 int sdmmc_alloc_ccbs(struct sdmmc_scsi_softc *, int);
76 void sdmmc_free_ccbs(struct sdmmc_scsi_softc *);
77 struct sdmmc_ccb *sdmmc_get_ccb(struct sdmmc_scsi_softc *, int);
78 void sdmmc_put_ccb(struct sdmmc_ccb *);
79
80 int sdmmc_scsi_cmd(struct scsi_xfer *);
81 int sdmmc_start_xs(struct sdmmc_softc *, struct sdmmc_ccb *);
82 void sdmmc_complete_xs(void *);
83 void sdmmc_done_xs(struct sdmmc_ccb *);
84 void sdmmc_stimeout(void *);
85 void sdmmc_scsi_minphys(struct buf *);
86
87 #define DEVNAME(sc) SDMMCDEVNAME(sc)
88
89 #ifdef SDMMC_DEBUG
90 #define DPRINTF(s) printf s
91 #else
92 #define DPRINTF(s)
93 #endif
94
95 void
96 sdmmc_scsi_attach(struct sdmmc_softc *sc)
97 {
98 struct scsibus_attach_args saa;
99 struct sdmmc_scsi_softc *scbus;
100 struct sdmmc_function *sf;
101
102 MALLOC(scbus, struct sdmmc_scsi_softc *,
103 sizeof *scbus, M_DEVBUF, M_WAITOK);
104 bzero(scbus, sizeof *scbus);
105
106 MALLOC(scbus->sc_tgt, struct sdmmc_scsi_target *,
107 sizeof(*scbus->sc_tgt) * (SDMMC_SCSIID_MAX+1),
108 M_DEVBUF, M_WAITOK);
109 bzero(scbus->sc_tgt, sizeof(*scbus->sc_tgt) * (SDMMC_SCSIID_MAX+1));
110
111
112
113
114
115 scbus->sc_ntargets = 1;
116 SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
117 if (scbus->sc_ntargets >= SDMMC_SCSIID_MAX+1)
118 break;
119 scbus->sc_tgt[scbus->sc_ntargets].card = sf;
120 scbus->sc_ntargets++;
121 }
122
123
124 if (sdmmc_alloc_ccbs(scbus, SDMMC_SCSI_MAXCMDS) != 0) {
125 printf("%s: can't allocate ccbs\n", sc->sc_dev.dv_xname);
126 goto free_sctgt;
127 }
128
129 sc->sc_scsibus = scbus;
130
131 scbus->sc_adapter.scsi_cmd = sdmmc_scsi_cmd;
132 scbus->sc_adapter.scsi_minphys = sdmmc_scsi_minphys;
133
134 scbus->sc_link.adapter_target = SDMMC_SCSIID_HOST;
135 scbus->sc_link.adapter_buswidth = scbus->sc_ntargets;
136 scbus->sc_link.adapter_softc = sc;
137 scbus->sc_link.luns = 1;
138 scbus->sc_link.openings = 1;
139 scbus->sc_link.adapter = &scbus->sc_adapter;
140
141 bzero(&saa, sizeof(saa));
142 saa.saa_sc_link = &scbus->sc_link;
143
144 scbus->sc_child = config_found(&sc->sc_dev, &saa, scsiprint);
145 if (scbus->sc_child == NULL) {
146 printf("%s: can't attach scsibus\n", sc->sc_dev.dv_xname);
147 goto free_ccbs;
148 }
149 return;
150
151 free_ccbs:
152 sc->sc_scsibus = NULL;
153 sdmmc_free_ccbs(scbus);
154 free_sctgt:
155 free(scbus->sc_tgt, M_DEVBUF);
156 free(scbus, M_DEVBUF);
157 }
158
159 void
160 sdmmc_scsi_detach(struct sdmmc_softc *sc)
161 {
162 struct sdmmc_scsi_softc *scbus;
163 struct sdmmc_ccb *ccb;
164 int s;
165
166 scbus = sc->sc_scsibus;
167 if (scbus == NULL)
168 return;
169
170
171 s = splbio();
172 for (ccb = TAILQ_FIRST(&scbus->sc_ccb_runq); ccb != NULL;
173 ccb = TAILQ_FIRST(&scbus->sc_ccb_runq))
174 sdmmc_stimeout(ccb);
175 splx(s);
176
177 if (scbus->sc_child != NULL)
178 config_detach(scbus->sc_child, DETACH_FORCE);
179
180 if (scbus->sc_tgt != NULL)
181 FREE(scbus->sc_tgt, M_DEVBUF);
182
183 sdmmc_free_ccbs(scbus);
184 FREE(scbus, M_DEVBUF);
185 sc->sc_scsibus = NULL;
186 }
187
188
189
190
191
192 int
193 sdmmc_alloc_ccbs(struct sdmmc_scsi_softc *scbus, int nccbs)
194 {
195 struct sdmmc_ccb *ccb;
196 int i;
197
198 scbus->sc_ccbs = malloc(sizeof(struct sdmmc_ccb) * nccbs,
199 M_DEVBUF, M_NOWAIT);
200 if (scbus->sc_ccbs == NULL)
201 return 1;
202
203 TAILQ_INIT(&scbus->sc_ccb_freeq);
204 TAILQ_INIT(&scbus->sc_ccb_runq);
205
206 for (i = 0; i < nccbs; i++) {
207 ccb = &scbus->sc_ccbs[i];
208 ccb->ccb_scbus = scbus;
209 ccb->ccb_state = SDMMC_CCB_FREE;
210 ccb->ccb_flags = 0;
211 ccb->ccb_xs = NULL;
212 ccb->ccb_done = NULL;
213
214 TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link);
215 }
216 return 0;
217 }
218
219 void
220 sdmmc_free_ccbs(struct sdmmc_scsi_softc *scbus)
221 {
222 if (scbus->sc_ccbs != NULL) {
223 free(scbus->sc_ccbs, M_DEVBUF);
224 scbus->sc_ccbs = NULL;
225 }
226 }
227
228 struct sdmmc_ccb *
229 sdmmc_get_ccb(struct sdmmc_scsi_softc *scbus, int flags)
230 {
231 struct sdmmc_ccb *ccb;
232 int s;
233
234 s = splbio();
235 while ((ccb = TAILQ_FIRST(&scbus->sc_ccb_freeq)) == NULL &&
236 !ISSET(flags, SCSI_NOSLEEP))
237 tsleep(&scbus->sc_ccb_freeq, PRIBIO, "getccb", 0);
238 if (ccb != NULL) {
239 TAILQ_REMOVE(&scbus->sc_ccb_freeq, ccb, ccb_link);
240 ccb->ccb_state = SDMMC_CCB_READY;
241 }
242 splx(s);
243 return ccb;
244 }
245
246 void
247 sdmmc_put_ccb(struct sdmmc_ccb *ccb)
248 {
249 struct sdmmc_scsi_softc *scbus = ccb->ccb_scbus;
250 int s;
251
252 s = splbio();
253 if (ccb->ccb_state == SDMMC_CCB_QUEUED)
254 TAILQ_REMOVE(&scbus->sc_ccb_runq, ccb, ccb_link);
255 ccb->ccb_state = SDMMC_CCB_FREE;
256 ccb->ccb_flags = 0;
257 ccb->ccb_xs = NULL;
258 ccb->ccb_done = NULL;
259 TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link);
260 if (TAILQ_NEXT(ccb, ccb_link) == NULL)
261 wakeup(&scbus->sc_ccb_freeq);
262 splx(s);
263 }
264
265
266
267
268
269
270 static void
271 sdmmc_scsi_decode_rw(struct scsi_xfer *xs, u_int32_t *blocknop,
272 u_int32_t *blockcntp)
273 {
274 struct scsi_rw *rw;
275 struct scsi_rw_big *rwb;
276
277 if (xs->cmdlen == 6) {
278 rw = (struct scsi_rw *)xs->cmd;
279 *blocknop = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff);
280 *blockcntp = rw->length ? rw->length : 0x100;
281 } else {
282 rwb = (struct scsi_rw_big *)xs->cmd;
283 *blocknop = _4btol(rwb->addr);
284 *blockcntp = _2btol(rwb->length);
285 }
286 }
287
288 int
289 sdmmc_scsi_cmd(struct scsi_xfer *xs)
290 {
291 struct scsi_link *link = xs->sc_link;
292 struct sdmmc_softc *sc = link->adapter_softc;
293 struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
294 struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
295 struct scsi_inquiry_data inq;
296 struct scsi_read_cap_data rcd;
297 u_int32_t blockno;
298 u_int32_t blockcnt;
299 struct sdmmc_ccb *ccb;
300 int s;
301
302 if (link->target >= scbus->sc_ntargets || tgt->card == NULL ||
303 link->lun != 0) {
304 DPRINTF(("%s: sdmmc_scsi_cmd: no target %d\n",
305 DEVNAME(sc), link->target));
306
307 xs->error = XS_DRIVER_STUFFUP;
308 xs->flags |= ITSDONE;
309 s = splbio();
310 scsi_done(xs);
311 splx(s);
312 return COMPLETE;
313 }
314
315 DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (poll=%#x)\n",
316 DEVNAME(sc), link->target, xs->cmd->opcode, curproc ?
317 curproc->p_comm : "", xs->flags & SCSI_POLL));
318
319 xs->error = XS_NOERROR;
320
321 switch (xs->cmd->opcode) {
322 case READ_COMMAND:
323 case READ_BIG:
324 case WRITE_COMMAND:
325 case WRITE_BIG:
326
327 break;
328
329 case INQUIRY:
330 bzero(&inq, sizeof inq);
331 inq.device = T_DIRECT;
332 inq.version = 2;
333 inq.response_format = 2;
334 inq.additional_length = 32;
335 strlcpy(inq.vendor, "SD/MMC ", sizeof(inq.vendor));
336 snprintf(inq.product, sizeof(inq.product),
337 "Drive #%02d", link->target);
338 strlcpy(inq.revision, " ", sizeof(inq.revision));
339 bcopy(&inq, xs->data, MIN(xs->datalen, sizeof inq));
340 s = splbio();
341 scsi_done(xs);
342 splx(s);
343 return COMPLETE;
344
345 case TEST_UNIT_READY:
346 case START_STOP:
347 case SYNCHRONIZE_CACHE:
348 return COMPLETE;
349
350 case READ_CAPACITY:
351 bzero(&rcd, sizeof rcd);
352 _lto4b(tgt->card->csd.capacity - 1, rcd.addr);
353 _lto4b(tgt->card->csd.sector_size, rcd.length);
354 bcopy(&rcd, xs->data, MIN(xs->datalen, sizeof rcd));
355 s = splbio();
356 scsi_done(xs);
357 splx(s);
358 return COMPLETE;
359
360 default:
361 DPRINTF(("%s: unsupported scsi command %#x\n",
362 DEVNAME(sc), xs->cmd->opcode));
363 xs->error = XS_DRIVER_STUFFUP;
364 s = splbio();
365 scsi_done(xs);
366 splx(s);
367 return COMPLETE;
368 }
369
370
371 sdmmc_scsi_decode_rw(xs, &blockno, &blockcnt);
372
373 if (blockno >= tgt->card->csd.capacity ||
374 blockno + blockcnt > tgt->card->csd.capacity) {
375 DPRINTF(("%s: out of bounds %u-%u >= %u\n", DEVNAME(sc),
376 blockno, blockcnt, tgt->card->csd.capacity));
377 xs->error = XS_DRIVER_STUFFUP;
378 s = splbio();
379 scsi_done(xs);
380 splx(s);
381 return COMPLETE;
382 }
383
384 ccb = sdmmc_get_ccb(sc->sc_scsibus, xs->flags);
385 if (ccb == NULL) {
386 printf("%s: out of ccbs\n", DEVNAME(sc));
387 xs->error = XS_DRIVER_STUFFUP;
388 s = splbio();
389 scsi_done(xs);
390 splx(s);
391 return COMPLETE;
392 }
393
394 ccb->ccb_xs = xs;
395 ccb->ccb_done = sdmmc_done_xs;
396
397 ccb->ccb_blockcnt = blockcnt;
398 ccb->ccb_blockno = blockno;
399
400 return sdmmc_start_xs(sc, ccb);
401 }
402
403 int
404 sdmmc_start_xs(struct sdmmc_softc *sc, struct sdmmc_ccb *ccb)
405 {
406 struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
407 struct scsi_xfer *xs = ccb->ccb_xs;
408 int s;
409
410 timeout_set(&xs->stimeout, sdmmc_stimeout, ccb);
411 sdmmc_init_task(&ccb->ccb_task, sdmmc_complete_xs, ccb);
412
413 s = splbio();
414 TAILQ_INSERT_TAIL(&scbus->sc_ccb_runq, ccb, ccb_link);
415 ccb->ccb_state = SDMMC_CCB_QUEUED;
416 splx(s);
417
418 if (ISSET(xs->flags, SCSI_POLL)) {
419 sdmmc_complete_xs(ccb);
420 return COMPLETE;
421 }
422
423 timeout_add(&xs->stimeout, (xs->timeout * hz) / 1000);
424 sdmmc_add_task(sc, &ccb->ccb_task);
425 return SUCCESSFULLY_QUEUED;
426 }
427
428 void
429 sdmmc_complete_xs(void *arg)
430 {
431 struct sdmmc_ccb *ccb = arg;
432 struct scsi_xfer *xs = ccb->ccb_xs;
433 struct scsi_link *link = xs->sc_link;
434 struct sdmmc_softc *sc = link->adapter_softc;
435 struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
436 struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
437 int error;
438 int s;
439
440 DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (poll=%#x)"
441 " complete\n", DEVNAME(sc), link->target, xs->cmd->opcode,
442 curproc ? curproc->p_comm : "", xs->flags & SCSI_POLL));
443
444 s = splbio();
445
446 if (ISSET(xs->flags, SCSI_DATA_IN))
447 error = sdmmc_mem_read_block(tgt->card, ccb->ccb_blockno,
448 xs->data, ccb->ccb_blockcnt * DEV_BSIZE);
449 else
450 error = sdmmc_mem_write_block(tgt->card, ccb->ccb_blockno,
451 xs->data, ccb->ccb_blockcnt * DEV_BSIZE);
452
453 if (error != 0)
454 xs->error = XS_DRIVER_STUFFUP;
455
456 ccb->ccb_done(ccb);
457 splx(s);
458 }
459
460 void
461 sdmmc_done_xs(struct sdmmc_ccb *ccb)
462 {
463 struct scsi_xfer *xs = ccb->ccb_xs;
464 #ifdef SDMMC_DEBUG
465 struct scsi_link *link = xs->sc_link;
466 struct sdmmc_softc *sc = link->adapter_softc;
467 #endif
468
469 timeout_del(&xs->stimeout);
470
471 DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (error=%#x)"
472 " done\n", DEVNAME(sc), link->target, xs->cmd->opcode,
473 curproc ? curproc->p_comm : "", xs->error));
474
475 xs->resid = 0;
476 xs->flags |= ITSDONE;
477
478 if (ISSET(ccb->ccb_flags, SDMMC_CCB_F_ERR))
479 xs->error = XS_DRIVER_STUFFUP;
480
481 sdmmc_put_ccb(ccb);
482 scsi_done(xs);
483 }
484
485 void
486 sdmmc_stimeout(void *arg)
487 {
488 struct sdmmc_ccb *ccb = arg;
489 int s;
490
491 s = splbio();
492 ccb->ccb_flags |= SDMMC_CCB_F_ERR;
493 if (sdmmc_task_pending(&ccb->ccb_task)) {
494 sdmmc_del_task(&ccb->ccb_task);
495 ccb->ccb_done(ccb);
496 }
497 splx(s);
498 }
499
500 void
501 sdmmc_scsi_minphys(struct buf *bp)
502 {
503
504 if (bp->b_bcount > DEV_BSIZE)
505 bp->b_bcount = DEV_BSIZE;
506 minphys(bp);
507 }