xref: /openbsd-src/sys/dev/sdmmc/sdmmc_scsi.c (revision 43003dfe3ad45d1698bed8a37f2b0f5b14f20d4f)
1 /*	$OpenBSD: sdmmc_scsi.c,v 1.19 2009/10/03 18:42:36 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/kernel.h>
25 #include <sys/malloc.h>
26 #include <sys/proc.h>
27 #include <sys/systm.h>
28 
29 #include <scsi/scsi_all.h>
30 #include <scsi/scsi_disk.h>
31 #include <scsi/scsiconf.h>
32 
33 #include <dev/sdmmc/sdmmc_scsi.h>
34 #include <dev/sdmmc/sdmmcvar.h>
35 
36 #define SDMMC_SCSIID_HOST	0x00
37 #define SDMMC_SCSIID_MAX	0x0f
38 
39 #define SDMMC_SCSI_MAXCMDS	8
40 
41 struct sdmmc_scsi_target {
42 	struct sdmmc_function *card;
43 };
44 
45 struct sdmmc_ccb {
46 	struct sdmmc_scsi_softc *ccb_scbus;
47 	struct scsi_xfer *ccb_xs;
48 	int ccb_flags;
49 #define SDMMC_CCB_F_ERR		0x0001
50 	void (*ccb_done)(struct sdmmc_ccb *);
51 	u_int32_t ccb_blockno;
52 	u_int32_t ccb_blockcnt;
53 	volatile enum {
54 		SDMMC_CCB_FREE,
55 		SDMMC_CCB_READY,
56 		SDMMC_CCB_QUEUED
57 	} ccb_state;
58 	struct sdmmc_command ccb_cmd;
59 	struct sdmmc_task ccb_task;
60 	TAILQ_ENTRY(sdmmc_ccb) ccb_link;
61 };
62 
63 TAILQ_HEAD(sdmmc_ccb_list, sdmmc_ccb);
64 
65 struct sdmmc_scsi_softc {
66 	struct scsi_adapter sc_adapter;
67 	struct scsi_link sc_link;
68 	struct device *sc_child;
69 	struct sdmmc_scsi_target *sc_tgt;
70 	int sc_ntargets;
71 	struct sdmmc_ccb *sc_ccbs;		/* allocated ccbs */
72 	struct sdmmc_ccb_list sc_ccb_freeq;	/* free ccbs */
73 	struct sdmmc_ccb_list sc_ccb_runq;	/* queued ccbs */
74 };
75 
76 int	sdmmc_alloc_ccbs(struct sdmmc_scsi_softc *, int);
77 void	sdmmc_free_ccbs(struct sdmmc_scsi_softc *);
78 struct sdmmc_ccb *sdmmc_get_ccb(struct sdmmc_scsi_softc *, int);
79 void	sdmmc_put_ccb(struct sdmmc_ccb *);
80 
81 int	sdmmc_scsi_cmd(struct scsi_xfer *);
82 int	sdmmc_start_xs(struct sdmmc_softc *, struct sdmmc_ccb *);
83 void	sdmmc_complete_xs(void *);
84 void	sdmmc_done_xs(struct sdmmc_ccb *);
85 void	sdmmc_stimeout(void *);
86 void	sdmmc_scsi_minphys(struct buf *, struct scsi_link *);
87 
88 #define DEVNAME(sc)	SDMMCDEVNAME(sc)
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 	SDMMC_ASSERT_LOCKED(sc);
104 
105 	scbus = malloc(sizeof *scbus, M_DEVBUF, M_WAITOK | M_ZERO);
106 
107 	scbus->sc_tgt = malloc(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 
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);
155 	free(scbus, M_DEVBUF);
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 	SDMMC_ASSERT_LOCKED(sc);
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);
183 
184 	sdmmc_free_ccbs(scbus);
185 	free(scbus, M_DEVBUF);
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 = malloc(sizeof(struct sdmmc_ccb) * nccbs,
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 
207 	for (i = 0; i < nccbs; i++) {
208 		ccb = &scbus->sc_ccbs[i];
209 		ccb->ccb_scbus = scbus;
210 		ccb->ccb_state = SDMMC_CCB_FREE;
211 		ccb->ccb_flags = 0;
212 		ccb->ccb_xs = NULL;
213 		ccb->ccb_done = NULL;
214 
215 		TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link);
216 	}
217 	return 0;
218 }
219 
220 void
221 sdmmc_free_ccbs(struct sdmmc_scsi_softc *scbus)
222 {
223 	if (scbus->sc_ccbs != NULL) {
224 		free(scbus->sc_ccbs, M_DEVBUF);
225 		scbus->sc_ccbs = NULL;
226 	}
227 }
228 
229 struct sdmmc_ccb *
230 sdmmc_get_ccb(struct sdmmc_scsi_softc *scbus, int flags)
231 {
232 	struct sdmmc_ccb *ccb;
233 	int s;
234 
235 	s = splbio();
236 	while ((ccb = TAILQ_FIRST(&scbus->sc_ccb_freeq)) == NULL &&
237 	    !ISSET(flags, SCSI_NOSLEEP))
238 		tsleep(&scbus->sc_ccb_freeq, PRIBIO, "getccb", 0);
239 	if (ccb != NULL) {
240 		TAILQ_REMOVE(&scbus->sc_ccb_freeq, ccb, ccb_link);
241 		ccb->ccb_state = SDMMC_CCB_READY;
242 	}
243 	splx(s);
244 	return ccb;
245 }
246 
247 void
248 sdmmc_put_ccb(struct sdmmc_ccb *ccb)
249 {
250 	struct sdmmc_scsi_softc *scbus = ccb->ccb_scbus;
251 	int s;
252 
253 	s = splbio();
254 	if (ccb->ccb_state == SDMMC_CCB_QUEUED)
255 		TAILQ_REMOVE(&scbus->sc_ccb_runq, ccb, ccb_link);
256 	ccb->ccb_state = SDMMC_CCB_FREE;
257 	ccb->ccb_flags = 0;
258 	ccb->ccb_xs = NULL;
259 	ccb->ccb_done = NULL;
260 	TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link);
261 	if (TAILQ_NEXT(ccb, ccb_link) == NULL)
262 		wakeup(&scbus->sc_ccb_freeq);
263 	splx(s);
264 }
265 
266 /*
267  * SCSI command emulation
268  */
269 
270 /* XXX move to some sort of "scsi emulation layer". */
271 static void
272 sdmmc_scsi_decode_rw(struct scsi_xfer *xs, u_int32_t *blocknop,
273     u_int32_t *blockcntp)
274 {
275 	struct scsi_rw *rw;
276 	struct scsi_rw_big *rwb;
277 
278 	if (xs->cmdlen == 6) {
279 		rw = (struct scsi_rw *)xs->cmd;
280 		*blocknop = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff);
281 		*blockcntp = rw->length ? rw->length : 0x100;
282 	} else {
283 		rwb = (struct scsi_rw_big *)xs->cmd;
284 		*blocknop = _4btol(rwb->addr);
285 		*blockcntp = _2btol(rwb->length);
286 	}
287 }
288 
289 int
290 sdmmc_scsi_cmd(struct scsi_xfer *xs)
291 {
292 	struct scsi_link *link = xs->sc_link;
293 	struct sdmmc_softc *sc = link->adapter_softc;
294 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
295 	struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
296 	struct scsi_inquiry_data inq;
297 	struct scsi_read_cap_data rcd;
298 	u_int32_t blockno;
299 	u_int32_t blockcnt;
300 	struct sdmmc_ccb *ccb;
301 	int s;
302 
303 	if (link->target >= scbus->sc_ntargets || tgt->card == NULL ||
304 	    link->lun != 0) {
305 		DPRINTF(("%s: sdmmc_scsi_cmd: no target %d\n",
306 		    DEVNAME(sc), link->target));
307 		/* XXX should be XS_SENSE and sense filled out */
308 		xs->error = XS_DRIVER_STUFFUP;
309 		xs->flags |= ITSDONE;
310 		s = splbio();
311 		scsi_done(xs);
312 		splx(s);
313 		return COMPLETE;
314 	}
315 
316 	DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (poll=%#x)\n",
317 	    DEVNAME(sc), link->target, xs->cmd->opcode, curproc ?
318 	    curproc->p_comm : "", xs->flags & SCSI_POLL));
319 
320 	xs->error = XS_NOERROR;
321 
322 	switch (xs->cmd->opcode) {
323 	case READ_COMMAND:
324 	case READ_BIG:
325 	case WRITE_COMMAND:
326 	case WRITE_BIG:
327 		/* Deal with I/O outside the switch. */
328 		break;
329 
330 	case INQUIRY:
331 		bzero(&inq, sizeof inq);
332 		inq.device = T_DIRECT;
333 		inq.version = 2;
334 		inq.response_format = 2;
335 		inq.additional_length = 32;
336 		strlcpy(inq.vendor, "SD/MMC ", sizeof(inq.vendor));
337 		snprintf(inq.product, sizeof(inq.product),
338 		    "Drive #%02d", link->target);
339 		strlcpy(inq.revision, "   ", sizeof(inq.revision));
340 		bcopy(&inq, xs->data, MIN(xs->datalen, sizeof inq));
341 		s = splbio();
342 		scsi_done(xs);
343 		splx(s);
344 		return COMPLETE;
345 
346 	case TEST_UNIT_READY:
347 	case START_STOP:
348 	case SYNCHRONIZE_CACHE:
349 		s = splbio();
350 		scsi_done(xs);
351 		splx(s);
352 		return COMPLETE;
353 
354 	case READ_CAPACITY:
355 		bzero(&rcd, sizeof rcd);
356 		_lto4b(tgt->card->csd.capacity - 1, rcd.addr);
357 		_lto4b(tgt->card->csd.sector_size, rcd.length);
358 		bcopy(&rcd, xs->data, MIN(xs->datalen, sizeof rcd));
359 		s = splbio();
360 		scsi_done(xs);
361 		splx(s);
362 		return COMPLETE;
363 
364 	default:
365 		DPRINTF(("%s: unsupported scsi command %#x\n",
366 		    DEVNAME(sc), xs->cmd->opcode));
367 		xs->error = XS_DRIVER_STUFFUP;
368 		s = splbio();
369 		scsi_done(xs);
370 		splx(s);
371 		return COMPLETE;
372 	}
373 
374 	/* A read or write operation. */
375 	sdmmc_scsi_decode_rw(xs, &blockno, &blockcnt);
376 
377 	if (blockno >= tgt->card->csd.capacity ||
378 	    blockno + blockcnt > tgt->card->csd.capacity) {
379 		DPRINTF(("%s: out of bounds %u-%u >= %u\n", DEVNAME(sc),
380 		    blockno, blockcnt, tgt->card->csd.capacity));
381 		xs->error = XS_DRIVER_STUFFUP;
382 		s = splbio();
383 		scsi_done(xs);
384 		splx(s);
385 		return COMPLETE;
386 	}
387 
388 	ccb = sdmmc_get_ccb(sc->sc_scsibus, xs->flags);
389 	if (ccb == NULL) {
390 		printf("%s: out of ccbs\n", DEVNAME(sc));
391 		xs->error = XS_DRIVER_STUFFUP;
392 		s = splbio();
393 		scsi_done(xs);
394 		splx(s);
395 		return COMPLETE;
396 	}
397 
398 	ccb->ccb_xs = xs;
399 	ccb->ccb_done = sdmmc_done_xs;
400 
401 	ccb->ccb_blockcnt = blockcnt;
402 	ccb->ccb_blockno = blockno;
403 
404 	return sdmmc_start_xs(sc, ccb);
405 }
406 
407 int
408 sdmmc_start_xs(struct sdmmc_softc *sc, struct sdmmc_ccb *ccb)
409 {
410 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
411 	struct scsi_xfer *xs = ccb->ccb_xs;
412 	int s;
413 
414 	timeout_set(&xs->stimeout, sdmmc_stimeout, ccb);
415 	sdmmc_init_task(&ccb->ccb_task, sdmmc_complete_xs, ccb);
416 
417 	s = splbio();
418 	TAILQ_INSERT_TAIL(&scbus->sc_ccb_runq, ccb, ccb_link);
419 	ccb->ccb_state = SDMMC_CCB_QUEUED;
420 	splx(s);
421 
422 	if (ISSET(xs->flags, SCSI_POLL)) {
423 		sdmmc_complete_xs(ccb);
424 		return COMPLETE;
425 	}
426 
427 	timeout_add_msec(&xs->stimeout, xs->timeout);
428 	sdmmc_add_task(sc, &ccb->ccb_task);
429 	return SUCCESSFULLY_QUEUED;
430 }
431 
432 void
433 sdmmc_complete_xs(void *arg)
434 {
435 	struct sdmmc_ccb *ccb = arg;
436 	struct scsi_xfer *xs = ccb->ccb_xs;
437 	struct scsi_link *link = xs->sc_link;
438 	struct sdmmc_softc *sc = link->adapter_softc;
439 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
440 	struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
441 	int error;
442 	int s;
443 
444 	DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (poll=%#x)"
445 	    " complete\n", DEVNAME(sc), link->target, xs->cmd->opcode,
446 	    curproc ? curproc->p_comm : "", xs->flags & SCSI_POLL));
447 
448 	s = splbio();
449 
450 	if (ISSET(xs->flags, SCSI_DATA_IN))
451 		error = sdmmc_mem_read_block(tgt->card, ccb->ccb_blockno,
452 		    xs->data, ccb->ccb_blockcnt * DEV_BSIZE);
453 	else
454 		error = sdmmc_mem_write_block(tgt->card, ccb->ccb_blockno,
455 		    xs->data, ccb->ccb_blockcnt * DEV_BSIZE);
456 
457 	if (error != 0)
458 		xs->error = XS_DRIVER_STUFFUP;
459 
460 	ccb->ccb_done(ccb);
461 	splx(s);
462 }
463 
464 void
465 sdmmc_done_xs(struct sdmmc_ccb *ccb)
466 {
467 	struct scsi_xfer *xs = ccb->ccb_xs;
468 #ifdef SDMMC_DEBUG
469 	struct scsi_link *link = xs->sc_link;
470 	struct sdmmc_softc *sc = link->adapter_softc;
471 #endif
472 
473 	timeout_del(&xs->stimeout);
474 
475 	DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (error=%#x)"
476 	    " done\n", DEVNAME(sc), link->target, xs->cmd->opcode,
477 	    curproc ? curproc->p_comm : "", xs->error));
478 
479 	xs->resid = 0;
480 	xs->flags |= ITSDONE;
481 
482 	if (ISSET(ccb->ccb_flags, SDMMC_CCB_F_ERR))
483 		xs->error = XS_DRIVER_STUFFUP;
484 
485 	sdmmc_put_ccb(ccb);
486 	scsi_done(xs);
487 }
488 
489 void
490 sdmmc_stimeout(void *arg)
491 {
492 	struct sdmmc_ccb *ccb = arg;
493 	int s;
494 
495 	s = splbio();
496 	ccb->ccb_flags |= SDMMC_CCB_F_ERR;
497 	if (sdmmc_task_pending(&ccb->ccb_task)) {
498 		sdmmc_del_task(&ccb->ccb_task);
499 		ccb->ccb_done(ccb);
500 	}
501 	splx(s);
502 }
503 
504 void
505 sdmmc_scsi_minphys(struct buf *bp, struct scsi_link *sl)
506 {
507 	struct sdmmc_softc *sc = sl->adapter_softc;
508 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
509 	struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[sl->target];
510 	struct sdmmc_function *sf = tgt->card;
511 
512 	/* limit to max. transfer size supported by card/host */
513 	if (sc->sc_max_xfer != 0 &&
514 	    bp->b_bcount > sf->csd.sector_size * sc->sc_max_xfer)
515 		bp->b_bcount = sf->csd.sector_size * sc->sc_max_xfer;
516 
517 	minphys(bp);
518 }
519