xref: /openbsd-src/sys/dev/sdmmc/sdmmc_scsi.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: sdmmc_scsi.c,v 1.17 2009/04/07 16:35:52 blambert 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/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;		/* allocated ccbs */
71 	struct sdmmc_ccb_list sc_ccb_freeq;	/* free ccbs */
72 	struct sdmmc_ccb_list sc_ccb_runq;	/* queued ccbs */
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 *, struct scsi_link *);
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 sdmmc_attach_args saa;
99 	struct sdmmc_scsi_softc *scbus;
100 	struct sdmmc_function *sf;
101 
102 	SDMMC_ASSERT_LOCKED(sc);
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 
139 	bzero(&saa, sizeof(saa));
140 	saa.scsi_link = &scbus->sc_link;
141 
142 	scbus->sc_child = config_found(&sc->sc_dev, &saa, scsiprint);
143 	if (scbus->sc_child == NULL) {
144 		printf("%s: can't attach scsibus\n", sc->sc_dev.dv_xname);
145 		goto free_ccbs;
146 	}
147 	return;
148 
149  free_ccbs:
150 	sc->sc_scsibus = NULL;
151 	sdmmc_free_ccbs(scbus);
152  free_sctgt:
153 	free(scbus->sc_tgt, M_DEVBUF);
154 	free(scbus, M_DEVBUF);
155 }
156 
157 void
158 sdmmc_scsi_detach(struct sdmmc_softc *sc)
159 {
160 	struct sdmmc_scsi_softc *scbus;
161 	struct sdmmc_ccb *ccb;
162 	int s;
163 
164 	SDMMC_ASSERT_LOCKED(sc);
165 
166 	scbus = sc->sc_scsibus;
167 	if (scbus == NULL)
168 		return;
169 
170 	/* Complete all open scsi xfers. */
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  * CCB management
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  * SCSI command emulation
267  */
268 
269 /* XXX move to some sort of "scsi emulation layer". */
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 		/* XXX should be XS_SENSE and sense filled out */
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 		/* Deal with I/O outside the switch. */
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 	/* A read or write operation. */
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_msec(&xs->stimeout, xs->timeout);
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, struct scsi_link *sl)
502 {
503 	struct sdmmc_softc *sc = sl->adapter_softc;
504 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
505 	struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[sl->target];
506 	struct sdmmc_function *sf = tgt->card;
507 
508 	/* limit to max. transfer size supported by card/host */
509 	if (sc->sc_max_xfer != 0 &&
510 	    bp->b_bcount > sf->csd.sector_size * sc->sc_max_xfer)
511 		bp->b_bcount = sf->csd.sector_size * sc->sc_max_xfer;
512 
513 	minphys(bp);
514 }
515