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