xref: /openbsd-src/sys/dev/sdmmc/sdmmc_scsi.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /*	$OpenBSD: sdmmc_scsi.c,v 1.36 2016/05/05 10:51:10 kettenis Exp $	*/
2 
3 /*
4  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /* A SCSI adapter emulation to access SD/MMC memory cards */
20 
21 #include <sys/param.h>
22 #include <sys/buf.h>
23 #include <sys/device.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 	u_int32_t ccb_blockno;
50 	u_int32_t ccb_blockcnt;
51 	volatile enum {
52 		SDMMC_CCB_FREE,
53 		SDMMC_CCB_READY,
54 		SDMMC_CCB_QUEUED
55 	} ccb_state;
56 	struct sdmmc_command ccb_cmd;
57 	struct sdmmc_task ccb_task;
58 	TAILQ_ENTRY(sdmmc_ccb) ccb_link;
59 };
60 
61 TAILQ_HEAD(sdmmc_ccb_list, sdmmc_ccb);
62 
63 struct sdmmc_scsi_softc {
64 	struct scsi_adapter sc_adapter;
65 	struct scsi_link sc_link;
66 	struct device *sc_child;
67 	struct sdmmc_scsi_target *sc_tgt;
68 	int sc_ntargets;
69 	struct sdmmc_ccb *sc_ccbs;		/* allocated ccbs */
70 	struct sdmmc_ccb_list sc_ccb_freeq;	/* free ccbs */
71 	struct sdmmc_ccb_list sc_ccb_runq;	/* queued ccbs */
72 	struct mutex sc_ccb_mtx;
73 	struct scsi_iopool sc_iopool;
74 };
75 
76 int	sdmmc_alloc_ccbs(struct sdmmc_scsi_softc *, int);
77 void	sdmmc_free_ccbs(struct sdmmc_scsi_softc *);
78 void	*sdmmc_ccb_alloc(void *);
79 void	sdmmc_ccb_free(void *, void *);
80 
81 void	sdmmc_scsi_cmd(struct scsi_xfer *);
82 void	sdmmc_inquiry(struct scsi_xfer *);
83 void	sdmmc_start_xs(struct sdmmc_softc *, struct sdmmc_ccb *);
84 void	sdmmc_complete_xs(void *);
85 void	sdmmc_done_xs(struct sdmmc_ccb *);
86 void	sdmmc_stimeout(void *);
87 void	sdmmc_scsi_minphys(struct buf *, struct scsi_link *);
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 sdmmc_attach_args saa;
99 	struct sdmmc_scsi_softc *scbus;
100 	struct sdmmc_function *sf;
101 
102 	rw_assert_wrlock(&sc->sc_lock);
103 
104 	scbus = malloc(sizeof *scbus, M_DEVBUF, M_WAITOK | M_ZERO);
105 
106 	scbus->sc_tgt = malloc(sizeof(*scbus->sc_tgt) *
107 	    (SDMMC_SCSIID_MAX+1), M_DEVBUF, M_WAITOK | M_ZERO);
108 
109 	/*
110 	 * Each card that sent us a CID in the identification stage
111 	 * gets a SCSI ID > 0, whether it is a memory card or not.
112 	 */
113 	scbus->sc_ntargets = 1;
114 	SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
115 		if (scbus->sc_ntargets >= SDMMC_SCSIID_MAX+1)
116 			break;
117 		scbus->sc_tgt[scbus->sc_ntargets].card = sf;
118 		scbus->sc_ntargets++;
119 	}
120 
121 	/* Preallocate some CCBs and initialize the CCB lists. */
122 	if (sdmmc_alloc_ccbs(scbus, SDMMC_SCSI_MAXCMDS) != 0) {
123 		printf("%s: can't allocate ccbs\n", sc->sc_dev.dv_xname);
124 		goto free_sctgt;
125 	}
126 
127 	sc->sc_scsibus = scbus;
128 
129 	scbus->sc_adapter.scsi_cmd = sdmmc_scsi_cmd;
130 	scbus->sc_adapter.scsi_minphys = sdmmc_scsi_minphys;
131 
132 	scbus->sc_link.adapter_target = SDMMC_SCSIID_HOST;
133 	scbus->sc_link.adapter_buswidth = scbus->sc_ntargets;
134 	scbus->sc_link.adapter_softc = sc;
135 	scbus->sc_link.luns = 1;
136 	scbus->sc_link.openings = 1;
137 	scbus->sc_link.adapter = &scbus->sc_adapter;
138 	scbus->sc_link.pool = &scbus->sc_iopool;
139 
140 	bzero(&saa, sizeof(saa));
141 	saa.scsi_link = &scbus->sc_link;
142 
143 	scbus->sc_child = config_found(&sc->sc_dev, &saa, scsiprint);
144 	if (scbus->sc_child == NULL) {
145 		printf("%s: can't attach scsibus\n", sc->sc_dev.dv_xname);
146 		goto free_ccbs;
147 	}
148 	return;
149 
150  free_ccbs:
151 	sc->sc_scsibus = NULL;
152 	sdmmc_free_ccbs(scbus);
153  free_sctgt:
154 	free(scbus->sc_tgt, M_DEVBUF, 0);
155 	free(scbus, M_DEVBUF, 0);
156 }
157 
158 void
159 sdmmc_scsi_detach(struct sdmmc_softc *sc)
160 {
161 	struct sdmmc_scsi_softc *scbus;
162 	struct sdmmc_ccb *ccb;
163 	int s;
164 
165 	rw_assert_wrlock(&sc->sc_lock);
166 
167 	scbus = sc->sc_scsibus;
168 	if (scbus == NULL)
169 		return;
170 
171 	/* Complete all open scsi xfers. */
172 	s = splbio();
173 	for (ccb = TAILQ_FIRST(&scbus->sc_ccb_runq); ccb != NULL;
174 	     ccb = TAILQ_FIRST(&scbus->sc_ccb_runq))
175 		sdmmc_stimeout(ccb);
176 	splx(s);
177 
178 	if (scbus->sc_child != NULL)
179 		config_detach(scbus->sc_child, DETACH_FORCE);
180 
181 	if (scbus->sc_tgt != NULL)
182 		free(scbus->sc_tgt, M_DEVBUF, 0);
183 
184 	sdmmc_free_ccbs(scbus);
185 	free(scbus, M_DEVBUF, 0);
186 	sc->sc_scsibus = NULL;
187 }
188 
189 /*
190  * CCB management
191  */
192 
193 int
194 sdmmc_alloc_ccbs(struct sdmmc_scsi_softc *scbus, int nccbs)
195 {
196 	struct sdmmc_ccb *ccb;
197 	int i;
198 
199 	scbus->sc_ccbs = mallocarray(nccbs, sizeof(struct sdmmc_ccb),
200 	    M_DEVBUF, M_NOWAIT);
201 	if (scbus->sc_ccbs == NULL)
202 		return 1;
203 
204 	TAILQ_INIT(&scbus->sc_ccb_freeq);
205 	TAILQ_INIT(&scbus->sc_ccb_runq);
206 	mtx_init(&scbus->sc_ccb_mtx, IPL_BIO);
207 	scsi_iopool_init(&scbus->sc_iopool, scbus, sdmmc_ccb_alloc,
208 	    sdmmc_ccb_free);
209 
210 	for (i = 0; i < nccbs; i++) {
211 		ccb = &scbus->sc_ccbs[i];
212 		ccb->ccb_scbus = scbus;
213 		ccb->ccb_state = SDMMC_CCB_FREE;
214 		ccb->ccb_flags = 0;
215 		ccb->ccb_xs = NULL;
216 
217 		TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link);
218 	}
219 	return 0;
220 }
221 
222 void
223 sdmmc_free_ccbs(struct sdmmc_scsi_softc *scbus)
224 {
225 	if (scbus->sc_ccbs != NULL) {
226 		free(scbus->sc_ccbs, M_DEVBUF, 0);
227 		scbus->sc_ccbs = NULL;
228 	}
229 }
230 
231 void *
232 sdmmc_ccb_alloc(void *xscbus)
233 {
234 	struct sdmmc_scsi_softc *scbus = xscbus;
235 	struct sdmmc_ccb *ccb;
236 
237 	mtx_enter(&scbus->sc_ccb_mtx);
238 	ccb = TAILQ_FIRST(&scbus->sc_ccb_freeq);
239 	if (ccb != NULL) {
240 		TAILQ_REMOVE(&scbus->sc_ccb_freeq, ccb, ccb_link);
241 		ccb->ccb_state = SDMMC_CCB_READY;
242 	}
243 	mtx_leave(&scbus->sc_ccb_mtx);
244 
245 	return ccb;
246 }
247 
248 void
249 sdmmc_ccb_free(void *xscbus, void *xccb)
250 {
251 	struct sdmmc_scsi_softc *scbus = xscbus;
252 	struct sdmmc_ccb *ccb = xccb;
253 	int s;
254 
255 	s = splbio();
256 	if (ccb->ccb_state == SDMMC_CCB_QUEUED)
257 		TAILQ_REMOVE(&scbus->sc_ccb_runq, ccb, ccb_link);
258 	splx(s);
259 
260 	ccb->ccb_state = SDMMC_CCB_FREE;
261 	ccb->ccb_flags = 0;
262 	ccb->ccb_xs = NULL;
263 
264 	mtx_enter(&scbus->sc_ccb_mtx);
265 	TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link);
266 	mtx_leave(&scbus->sc_ccb_mtx);
267 }
268 
269 /*
270  * SCSI command emulation
271  */
272 
273 /* XXX move to some sort of "scsi emulation layer". */
274 static void
275 sdmmc_scsi_decode_rw(struct scsi_xfer *xs, u_int32_t *blocknop,
276     u_int32_t *blockcntp)
277 {
278 	struct scsi_rw *rw;
279 	struct scsi_rw_big *rwb;
280 
281 	if (xs->cmdlen == 6) {
282 		rw = (struct scsi_rw *)xs->cmd;
283 		*blocknop = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff);
284 		*blockcntp = rw->length ? rw->length : 0x100;
285 	} else {
286 		rwb = (struct scsi_rw_big *)xs->cmd;
287 		*blocknop = _4btol(rwb->addr);
288 		*blockcntp = _2btol(rwb->length);
289 	}
290 }
291 
292 void
293 sdmmc_scsi_cmd(struct scsi_xfer *xs)
294 {
295 	struct scsi_link *link = xs->sc_link;
296 	struct sdmmc_softc *sc = link->adapter_softc;
297 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
298 	struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
299 	struct scsi_read_cap_data rcd;
300 	u_int32_t blockno;
301 	u_int32_t blockcnt;
302 	struct sdmmc_ccb *ccb;
303 
304 	if (link->target >= scbus->sc_ntargets || tgt->card == NULL ||
305 	    link->lun != 0) {
306 		DPRINTF(("%s: sdmmc_scsi_cmd: no target %d\n",
307 		    DEVNAME(sc), link->target));
308 		/* XXX should be XS_SENSE and sense filled out */
309 		xs->error = XS_DRIVER_STUFFUP;
310 		scsi_done(xs);
311 		return;
312 	}
313 
314 	DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (poll=%#x)\n",
315 	    DEVNAME(sc), link->target, xs->cmd->opcode, curproc ?
316 	    curproc->p_comm : "", xs->flags & SCSI_POLL));
317 
318 	xs->error = XS_NOERROR;
319 
320 	switch (xs->cmd->opcode) {
321 	case READ_COMMAND:
322 	case READ_BIG:
323 	case WRITE_COMMAND:
324 	case WRITE_BIG:
325 		/* Deal with I/O outside the switch. */
326 		break;
327 
328 	case INQUIRY:
329 		sdmmc_inquiry(xs);
330 		return;
331 
332 	case TEST_UNIT_READY:
333 	case START_STOP:
334 	case SYNCHRONIZE_CACHE:
335 		scsi_done(xs);
336 		return;
337 
338 	case READ_CAPACITY:
339 		bzero(&rcd, sizeof rcd);
340 		_lto4b(tgt->card->csd.capacity - 1, rcd.addr);
341 		_lto4b(tgt->card->csd.sector_size, rcd.length);
342 		bcopy(&rcd, xs->data, MIN(xs->datalen, sizeof rcd));
343 		scsi_done(xs);
344 		return;
345 
346 	default:
347 		DPRINTF(("%s: unsupported scsi command %#x\n",
348 		    DEVNAME(sc), xs->cmd->opcode));
349 		xs->error = XS_DRIVER_STUFFUP;
350 		scsi_done(xs);
351 		return;
352 	}
353 
354 	/* A read or write operation. */
355 	sdmmc_scsi_decode_rw(xs, &blockno, &blockcnt);
356 
357 	if (blockno >= tgt->card->csd.capacity ||
358 	    blockno + blockcnt > tgt->card->csd.capacity) {
359 		DPRINTF(("%s: out of bounds %u-%u >= %u\n", DEVNAME(sc),
360 		    blockno, blockcnt, tgt->card->csd.capacity));
361 		xs->error = XS_DRIVER_STUFFUP;
362 		scsi_done(xs);
363 		return;
364 	}
365 
366 	ccb = xs->io;
367 
368 	ccb->ccb_xs = xs;
369 	ccb->ccb_blockcnt = blockcnt;
370 	ccb->ccb_blockno = blockno;
371 
372 	sdmmc_start_xs(sc, ccb);
373 }
374 
375 void
376 sdmmc_inquiry(struct scsi_xfer *xs)
377 {
378 	struct scsi_link *link = xs->sc_link;
379 	struct sdmmc_softc *sc = link->adapter_softc;
380 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
381 	struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
382 	struct scsi_inquiry_data inq;
383 	struct scsi_inquiry *cdb = (struct scsi_inquiry *)xs->cmd;
384 	char vendor[sizeof(inq.vendor) + 1];
385 	char product[sizeof(inq.product) + 1];
386 	char revision[sizeof(inq.revision) + 1];
387 
388         if (xs->cmdlen != sizeof(*cdb)) {
389 		xs->error = XS_DRIVER_STUFFUP;
390 		goto done;
391 	}
392 
393 	if (ISSET(cdb->flags, SI_EVPD)) {
394 		xs->error = XS_DRIVER_STUFFUP;
395 		goto done;
396 	}
397 
398 	memset(vendor, 0, sizeof(vendor));
399 	memset(product, 0, sizeof(product));
400 	memset(revision, 0, sizeof(revision));
401 	switch (tgt->card->cid.mid) {
402 	case 0x02:
403 	case 0x45:
404 		strlcpy(vendor, "Sandisk", sizeof(vendor));
405 		break;
406 	case 0x11:
407 		strlcpy(vendor, "Toshiba", sizeof(vendor));
408 		break;
409 	case 0x13:
410 		strlcpy(vendor, "Micron", sizeof(vendor));
411 		break;
412 	case 0x15:
413 		strlcpy(vendor, "Samsung", sizeof(vendor));
414 		break;
415 	case 0x70:
416 		strlcpy(vendor, "Kingston", sizeof(vendor));
417 		break;
418 	default:
419 		strlcpy(vendor, "SD/MMC", sizeof(vendor));
420 		break;
421 	}
422 	strlcpy(product, tgt->card->cid.pnm, sizeof(product));
423 	snprintf(revision, sizeof(revision), "%04X", tgt->card->cid.rev);
424 
425 	memset(&inq, 0, sizeof inq);
426 	inq.device = T_DIRECT;
427 	inq.version = 2;
428 	inq.response_format = 2;
429 	inq.additional_length = 32;
430 	memcpy(inq.vendor, vendor, sizeof(inq.vendor));
431 	memcpy(inq.product, product, sizeof(inq.product));
432 	memcpy(inq.revision, revision, sizeof(inq.revision));
433 
434 	memcpy(xs->data, &inq, MIN(xs->datalen, sizeof(inq)));
435 
436 done:
437 	scsi_done(xs);
438 }
439 
440 void
441 sdmmc_start_xs(struct sdmmc_softc *sc, struct sdmmc_ccb *ccb)
442 {
443 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
444 	struct scsi_xfer *xs = ccb->ccb_xs;
445 	int s;
446 
447 	timeout_set(&xs->stimeout, sdmmc_stimeout, ccb);
448 	sdmmc_init_task(&ccb->ccb_task, sdmmc_complete_xs, ccb);
449 
450 	s = splbio();
451 	TAILQ_INSERT_TAIL(&scbus->sc_ccb_runq, ccb, ccb_link);
452 	ccb->ccb_state = SDMMC_CCB_QUEUED;
453 	splx(s);
454 
455 	if (ISSET(xs->flags, SCSI_POLL)) {
456 		sdmmc_complete_xs(ccb);
457 		return;
458 	}
459 
460 	timeout_add_msec(&xs->stimeout, xs->timeout);
461 	sdmmc_add_task(sc, &ccb->ccb_task);
462 }
463 
464 void
465 sdmmc_complete_xs(void *arg)
466 {
467 	struct sdmmc_ccb *ccb = arg;
468 	struct scsi_xfer *xs = ccb->ccb_xs;
469 	struct scsi_link *link = xs->sc_link;
470 	struct sdmmc_softc *sc = link->adapter_softc;
471 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
472 	struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
473 	int error;
474 	int s;
475 
476 	DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (poll=%#x)"
477 	    " complete\n", DEVNAME(sc), link->target, xs->cmd->opcode,
478 	    curproc ? curproc->p_comm : "", xs->flags & SCSI_POLL));
479 
480 	s = splbio();
481 
482 	if (ISSET(xs->flags, SCSI_DATA_IN))
483 		error = sdmmc_mem_read_block(tgt->card, ccb->ccb_blockno,
484 		    xs->data, ccb->ccb_blockcnt * DEV_BSIZE);
485 	else
486 		error = sdmmc_mem_write_block(tgt->card, ccb->ccb_blockno,
487 		    xs->data, ccb->ccb_blockcnt * DEV_BSIZE);
488 
489 	if (error != 0)
490 		xs->error = XS_DRIVER_STUFFUP;
491 
492 	sdmmc_done_xs(ccb);
493 	splx(s);
494 }
495 
496 void
497 sdmmc_done_xs(struct sdmmc_ccb *ccb)
498 {
499 	struct scsi_xfer *xs = ccb->ccb_xs;
500 #ifdef SDMMC_DEBUG
501 	struct scsi_link *link = xs->sc_link;
502 	struct sdmmc_softc *sc = link->adapter_softc;
503 #endif
504 
505 	timeout_del(&xs->stimeout);
506 
507 	DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (error=%#x)"
508 	    " done\n", DEVNAME(sc), link->target, xs->cmd->opcode,
509 	    curproc ? curproc->p_comm : "", xs->error));
510 
511 	xs->resid = 0;
512 
513 	if (ISSET(ccb->ccb_flags, SDMMC_CCB_F_ERR))
514 		xs->error = XS_DRIVER_STUFFUP;
515 
516 	scsi_done(xs);
517 }
518 
519 void
520 sdmmc_stimeout(void *arg)
521 {
522 	struct sdmmc_ccb *ccb = arg;
523 	int s;
524 
525 	s = splbio();
526 	ccb->ccb_flags |= SDMMC_CCB_F_ERR;
527 	if (sdmmc_task_pending(&ccb->ccb_task)) {
528 		sdmmc_del_task(&ccb->ccb_task);
529 		sdmmc_done_xs(ccb);
530 	}
531 	splx(s);
532 }
533 
534 void
535 sdmmc_scsi_minphys(struct buf *bp, struct scsi_link *sl)
536 {
537 	struct sdmmc_softc *sc = sl->adapter_softc;
538 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
539 	struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[sl->target];
540 	struct sdmmc_function *sf = tgt->card;
541 
542 	/* limit to max. transfer size supported by card/host */
543 	if (sc->sc_max_xfer != 0 &&
544 	    bp->b_bcount > sf->csd.sector_size * sc->sc_max_xfer)
545 		bp->b_bcount = sf->csd.sector_size * sc->sc_max_xfer;
546 
547 	minphys(bp);
548 }
549