xref: /openbsd-src/sys/dev/sdmmc/sdmmc_scsi.c (revision 850e275390052b330d93020bf619a739a3c277ac)
1 /*	$OpenBSD: sdmmc_scsi.c,v 1.9 2007/09/11 13:39:34 gilles 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 *);
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 	scbus = (struct sdmmc_scsi_softc *)malloc(sizeof *scbus,
103 	    M_DEVBUF, M_WAITOK | M_ZERO);
104 
105 	scbus->sc_tgt = (struct sdmmc_scsi_target *)malloc(sizeof(*scbus->sc_tgt) *
106 	    (SDMMC_SCSIID_MAX+1), M_DEVBUF, M_WAITOK | M_ZERO);
107 
108 	/*
109 	 * Each card that sent us a CID in the identification stage
110 	 * gets a SCSI ID > 0, whether it is a memory card or not.
111 	 */
112 	scbus->sc_ntargets = 1;
113 	SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
114 		if (scbus->sc_ntargets >= SDMMC_SCSIID_MAX+1)
115 			break;
116 		scbus->sc_tgt[scbus->sc_ntargets].card = sf;
117 		scbus->sc_ntargets++;
118 	}
119 
120 	/* Preallocate some CCBs and initialize the CCB lists. */
121 	if (sdmmc_alloc_ccbs(scbus, SDMMC_SCSI_MAXCMDS) != 0) {
122 		printf("%s: can't allocate ccbs\n", sc->sc_dev.dv_xname);
123 		goto free_sctgt;
124 	}
125 
126 	sc->sc_scsibus = scbus;
127 
128 	scbus->sc_adapter.scsi_cmd = sdmmc_scsi_cmd;
129 	scbus->sc_adapter.scsi_minphys = sdmmc_scsi_minphys;
130 
131 	scbus->sc_link.adapter_target = SDMMC_SCSIID_HOST;
132 	scbus->sc_link.adapter_buswidth = scbus->sc_ntargets;
133 	scbus->sc_link.adapter_softc = sc;
134 	scbus->sc_link.luns = 1;
135 	scbus->sc_link.openings = 1;
136 	scbus->sc_link.adapter = &scbus->sc_adapter;
137 
138 	bzero(&saa, sizeof(saa));
139 	saa.saa_sc_link = &scbus->sc_link;
140 
141 	scbus->sc_child = config_found(&sc->sc_dev, &saa, scsiprint);
142 	if (scbus->sc_child == NULL) {
143 		printf("%s: can't attach scsibus\n", sc->sc_dev.dv_xname);
144 		goto free_ccbs;
145 	}
146 	return;
147 
148  free_ccbs:
149 	sc->sc_scsibus = NULL;
150 	sdmmc_free_ccbs(scbus);
151  free_sctgt:
152 	free(scbus->sc_tgt, M_DEVBUF);
153 	free(scbus, M_DEVBUF);
154 }
155 
156 void
157 sdmmc_scsi_detach(struct sdmmc_softc *sc)
158 {
159 	struct sdmmc_scsi_softc *scbus;
160 	struct sdmmc_ccb *ccb;
161 	int s;
162 
163 	scbus = sc->sc_scsibus;
164 	if (scbus == NULL)
165 		return;
166 
167 	/* Complete all open scsi xfers. */
168 	s = splbio();
169 	for (ccb = TAILQ_FIRST(&scbus->sc_ccb_runq); ccb != NULL;
170 	     ccb = TAILQ_FIRST(&scbus->sc_ccb_runq))
171 		sdmmc_stimeout(ccb);
172 	splx(s);
173 
174 	if (scbus->sc_child != NULL)
175 		config_detach(scbus->sc_child, DETACH_FORCE);
176 
177 	if (scbus->sc_tgt != NULL)
178 		free(scbus->sc_tgt, M_DEVBUF);
179 
180 	sdmmc_free_ccbs(scbus);
181 	free(scbus, M_DEVBUF);
182 	sc->sc_scsibus = NULL;
183 }
184 
185 /*
186  * CCB management
187  */
188 
189 int
190 sdmmc_alloc_ccbs(struct sdmmc_scsi_softc *scbus, int nccbs)
191 {
192 	struct sdmmc_ccb *ccb;
193 	int i;
194 
195 	scbus->sc_ccbs = malloc(sizeof(struct sdmmc_ccb) * nccbs,
196 	    M_DEVBUF, M_NOWAIT);
197 	if (scbus->sc_ccbs == NULL)
198 		return 1;
199 
200 	TAILQ_INIT(&scbus->sc_ccb_freeq);
201 	TAILQ_INIT(&scbus->sc_ccb_runq);
202 
203 	for (i = 0; i < nccbs; i++) {
204 		ccb = &scbus->sc_ccbs[i];
205 		ccb->ccb_scbus = scbus;
206 		ccb->ccb_state = SDMMC_CCB_FREE;
207 		ccb->ccb_flags = 0;
208 		ccb->ccb_xs = NULL;
209 		ccb->ccb_done = NULL;
210 
211 		TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link);
212 	}
213 	return 0;
214 }
215 
216 void
217 sdmmc_free_ccbs(struct sdmmc_scsi_softc *scbus)
218 {
219 	if (scbus->sc_ccbs != NULL) {
220 		free(scbus->sc_ccbs, M_DEVBUF);
221 		scbus->sc_ccbs = NULL;
222 	}
223 }
224 
225 struct sdmmc_ccb *
226 sdmmc_get_ccb(struct sdmmc_scsi_softc *scbus, int flags)
227 {
228 	struct sdmmc_ccb *ccb;
229 	int s;
230 
231 	s = splbio();
232 	while ((ccb = TAILQ_FIRST(&scbus->sc_ccb_freeq)) == NULL &&
233 	    !ISSET(flags, SCSI_NOSLEEP))
234 		tsleep(&scbus->sc_ccb_freeq, PRIBIO, "getccb", 0);
235 	if (ccb != NULL) {
236 		TAILQ_REMOVE(&scbus->sc_ccb_freeq, ccb, ccb_link);
237 		ccb->ccb_state = SDMMC_CCB_READY;
238 	}
239 	splx(s);
240 	return ccb;
241 }
242 
243 void
244 sdmmc_put_ccb(struct sdmmc_ccb *ccb)
245 {
246 	struct sdmmc_scsi_softc *scbus = ccb->ccb_scbus;
247 	int s;
248 
249 	s = splbio();
250 	if (ccb->ccb_state == SDMMC_CCB_QUEUED)
251 		TAILQ_REMOVE(&scbus->sc_ccb_runq, ccb, ccb_link);
252 	ccb->ccb_state = SDMMC_CCB_FREE;
253 	ccb->ccb_flags = 0;
254 	ccb->ccb_xs = NULL;
255 	ccb->ccb_done = NULL;
256 	TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link);
257 	if (TAILQ_NEXT(ccb, ccb_link) == NULL)
258 		wakeup(&scbus->sc_ccb_freeq);
259 	splx(s);
260 }
261 
262 /*
263  * SCSI command emulation
264  */
265 
266 /* XXX move to some sort of "scsi emulation layer". */
267 static void
268 sdmmc_scsi_decode_rw(struct scsi_xfer *xs, u_int32_t *blocknop,
269     u_int32_t *blockcntp)
270 {
271 	struct scsi_rw *rw;
272 	struct scsi_rw_big *rwb;
273 
274 	if (xs->cmdlen == 6) {
275 		rw = (struct scsi_rw *)xs->cmd;
276 		*blocknop = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff);
277 		*blockcntp = rw->length ? rw->length : 0x100;
278 	} else {
279 		rwb = (struct scsi_rw_big *)xs->cmd;
280 		*blocknop = _4btol(rwb->addr);
281 		*blockcntp = _2btol(rwb->length);
282 	}
283 }
284 
285 int
286 sdmmc_scsi_cmd(struct scsi_xfer *xs)
287 {
288 	struct scsi_link *link = xs->sc_link;
289 	struct sdmmc_softc *sc = link->adapter_softc;
290 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
291 	struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
292 	struct scsi_inquiry_data inq;
293 	struct scsi_read_cap_data rcd;
294 	u_int32_t blockno;
295 	u_int32_t blockcnt;
296 	struct sdmmc_ccb *ccb;
297 	int s;
298 
299 	if (link->target >= scbus->sc_ntargets || tgt->card == NULL ||
300 	    link->lun != 0) {
301 		DPRINTF(("%s: sdmmc_scsi_cmd: no target %d\n",
302 		    DEVNAME(sc), link->target));
303 		/* XXX should be XS_SENSE and sense filled out */
304 		xs->error = XS_DRIVER_STUFFUP;
305 		xs->flags |= ITSDONE;
306 		s = splbio();
307 		scsi_done(xs);
308 		splx(s);
309 		return COMPLETE;
310 	}
311 
312 	DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (poll=%#x)\n",
313 	    DEVNAME(sc), link->target, xs->cmd->opcode, curproc ?
314 	    curproc->p_comm : "", xs->flags & SCSI_POLL));
315 
316 	xs->error = XS_NOERROR;
317 
318 	switch (xs->cmd->opcode) {
319 	case READ_COMMAND:
320 	case READ_BIG:
321 	case WRITE_COMMAND:
322 	case WRITE_BIG:
323 		/* Deal with I/O outside the switch. */
324 		break;
325 
326 	case INQUIRY:
327 		bzero(&inq, sizeof inq);
328 		inq.device = T_DIRECT;
329 		inq.version = 2;
330 		inq.response_format = 2;
331 		inq.additional_length = 32;
332 		strlcpy(inq.vendor, "SD/MMC ", sizeof(inq.vendor));
333 		snprintf(inq.product, sizeof(inq.product),
334 		    "Drive #%02d", link->target);
335 		strlcpy(inq.revision, "   ", sizeof(inq.revision));
336 		bcopy(&inq, xs->data, MIN(xs->datalen, sizeof inq));
337 		s = splbio();
338 		scsi_done(xs);
339 		splx(s);
340 		return COMPLETE;
341 
342 	case TEST_UNIT_READY:
343 	case START_STOP:
344 	case SYNCHRONIZE_CACHE:
345 		return COMPLETE;
346 
347 	case READ_CAPACITY:
348 		bzero(&rcd, sizeof rcd);
349 		_lto4b(tgt->card->csd.capacity - 1, rcd.addr);
350 		_lto4b(tgt->card->csd.sector_size, rcd.length);
351 		bcopy(&rcd, xs->data, MIN(xs->datalen, sizeof rcd));
352 		s = splbio();
353 		scsi_done(xs);
354 		splx(s);
355 		return COMPLETE;
356 
357 	default:
358 		DPRINTF(("%s: unsupported scsi command %#x\n",
359 		    DEVNAME(sc), xs->cmd->opcode));
360 		xs->error = XS_DRIVER_STUFFUP;
361 		s = splbio();
362 		scsi_done(xs);
363 		splx(s);
364 		return COMPLETE;
365 	}
366 
367 	/* A read or write operation. */
368 	sdmmc_scsi_decode_rw(xs, &blockno, &blockcnt);
369 
370 	if (blockno >= tgt->card->csd.capacity ||
371 	    blockno + blockcnt > tgt->card->csd.capacity) {
372 		DPRINTF(("%s: out of bounds %u-%u >= %u\n", DEVNAME(sc),
373 		    blockno, blockcnt, tgt->card->csd.capacity));
374 		xs->error = XS_DRIVER_STUFFUP;
375 		s = splbio();
376 		scsi_done(xs);
377 		splx(s);
378 		return COMPLETE;
379 	}
380 
381 	ccb = sdmmc_get_ccb(sc->sc_scsibus, xs->flags);
382 	if (ccb == NULL) {
383 		printf("%s: out of ccbs\n", DEVNAME(sc));
384 		xs->error = XS_DRIVER_STUFFUP;
385 		s = splbio();
386 		scsi_done(xs);
387 		splx(s);
388 		return COMPLETE;
389 	}
390 
391 	ccb->ccb_xs = xs;
392 	ccb->ccb_done = sdmmc_done_xs;
393 
394 	ccb->ccb_blockcnt = blockcnt;
395 	ccb->ccb_blockno = blockno;
396 
397 	return sdmmc_start_xs(sc, ccb);
398 }
399 
400 int
401 sdmmc_start_xs(struct sdmmc_softc *sc, struct sdmmc_ccb *ccb)
402 {
403 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
404 	struct scsi_xfer *xs = ccb->ccb_xs;
405 	int s;
406 
407 	timeout_set(&xs->stimeout, sdmmc_stimeout, ccb);
408 	sdmmc_init_task(&ccb->ccb_task, sdmmc_complete_xs, ccb);
409 
410 	s = splbio();
411 	TAILQ_INSERT_TAIL(&scbus->sc_ccb_runq, ccb, ccb_link);
412 	ccb->ccb_state = SDMMC_CCB_QUEUED;
413 	splx(s);
414 
415 	if (ISSET(xs->flags, SCSI_POLL)) {
416 		sdmmc_complete_xs(ccb);
417 		return COMPLETE;
418 	}
419 
420 	timeout_add(&xs->stimeout, (xs->timeout * hz) / 1000);
421 	sdmmc_add_task(sc, &ccb->ccb_task);
422 	return SUCCESSFULLY_QUEUED;
423 }
424 
425 void
426 sdmmc_complete_xs(void *arg)
427 {
428 	struct sdmmc_ccb *ccb = arg;
429 	struct scsi_xfer *xs = ccb->ccb_xs;
430 	struct scsi_link *link = xs->sc_link;
431 	struct sdmmc_softc *sc = link->adapter_softc;
432 	struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
433 	struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
434 	int error;
435 	int s;
436 
437 	DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (poll=%#x)"
438 	    " complete\n", DEVNAME(sc), link->target, xs->cmd->opcode,
439 	    curproc ? curproc->p_comm : "", xs->flags & SCSI_POLL));
440 
441 	s = splbio();
442 
443 	if (ISSET(xs->flags, SCSI_DATA_IN))
444 		error = sdmmc_mem_read_block(tgt->card, ccb->ccb_blockno,
445 		    xs->data, ccb->ccb_blockcnt * DEV_BSIZE);
446 	else
447 		error = sdmmc_mem_write_block(tgt->card, ccb->ccb_blockno,
448 		    xs->data, ccb->ccb_blockcnt * DEV_BSIZE);
449 
450 	if (error != 0)
451 		xs->error = XS_DRIVER_STUFFUP;
452 
453 	ccb->ccb_done(ccb);
454 	splx(s);
455 }
456 
457 void
458 sdmmc_done_xs(struct sdmmc_ccb *ccb)
459 {
460 	struct scsi_xfer *xs = ccb->ccb_xs;
461 #ifdef SDMMC_DEBUG
462 	struct scsi_link *link = xs->sc_link;
463 	struct sdmmc_softc *sc = link->adapter_softc;
464 #endif
465 
466 	timeout_del(&xs->stimeout);
467 
468 	DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (error=%#x)"
469 	    " done\n", DEVNAME(sc), link->target, xs->cmd->opcode,
470 	    curproc ? curproc->p_comm : "", xs->error));
471 
472 	xs->resid = 0;
473 	xs->flags |= ITSDONE;
474 
475 	if (ISSET(ccb->ccb_flags, SDMMC_CCB_F_ERR))
476 		xs->error = XS_DRIVER_STUFFUP;
477 
478 	sdmmc_put_ccb(ccb);
479 	scsi_done(xs);
480 }
481 
482 void
483 sdmmc_stimeout(void *arg)
484 {
485 	struct sdmmc_ccb *ccb = arg;
486 	int s;
487 
488 	s = splbio();
489 	ccb->ccb_flags |= SDMMC_CCB_F_ERR;
490 	if (sdmmc_task_pending(&ccb->ccb_task)) {
491 		sdmmc_del_task(&ccb->ccb_task);
492 		ccb->ccb_done(ccb);
493 	}
494 	splx(s);
495 }
496 
497 void
498 sdmmc_scsi_minphys(struct buf *bp)
499 {
500 	/* XXX limit to max. transfer size supported by card/host? */
501 	if (bp->b_bcount > DEV_BSIZE)
502 		bp->b_bcount = DEV_BSIZE;
503 	minphys(bp);
504 }
505