1 /* $OpenBSD: sdmmc_scsi.c,v 1.30 2011/07/17 22:46:48 matthew 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 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 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 = 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 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 free(scbus, M_DEVBUF); 157 } 158 159 void 160 sdmmc_scsi_detach(struct sdmmc_softc *sc) 161 { 162 struct sdmmc_scsi_softc *scbus; 163 struct sdmmc_ccb *ccb; 164 int s; 165 166 rw_assert_wrlock(&sc->sc_lock); 167 168 scbus = sc->sc_scsibus; 169 if (scbus == NULL) 170 return; 171 172 /* Complete all open scsi xfers. */ 173 s = splbio(); 174 for (ccb = TAILQ_FIRST(&scbus->sc_ccb_runq); ccb != NULL; 175 ccb = TAILQ_FIRST(&scbus->sc_ccb_runq)) 176 sdmmc_stimeout(ccb); 177 splx(s); 178 179 if (scbus->sc_child != NULL) 180 config_detach(scbus->sc_child, DETACH_FORCE); 181 182 if (scbus->sc_tgt != NULL) 183 free(scbus->sc_tgt, M_DEVBUF); 184 185 sdmmc_free_ccbs(scbus); 186 free(scbus, M_DEVBUF); 187 sc->sc_scsibus = NULL; 188 } 189 190 /* 191 * CCB management 192 */ 193 194 int 195 sdmmc_alloc_ccbs(struct sdmmc_scsi_softc *scbus, int nccbs) 196 { 197 struct sdmmc_ccb *ccb; 198 int i; 199 200 scbus->sc_ccbs = malloc(sizeof(struct sdmmc_ccb) * nccbs, 201 M_DEVBUF, M_NOWAIT); 202 if (scbus->sc_ccbs == NULL) 203 return 1; 204 205 TAILQ_INIT(&scbus->sc_ccb_freeq); 206 TAILQ_INIT(&scbus->sc_ccb_runq); 207 mtx_init(&scbus->sc_ccb_mtx, IPL_BIO); 208 scsi_iopool_init(&scbus->sc_iopool, scbus, sdmmc_ccb_alloc, 209 sdmmc_ccb_free); 210 211 for (i = 0; i < nccbs; i++) { 212 ccb = &scbus->sc_ccbs[i]; 213 ccb->ccb_scbus = scbus; 214 ccb->ccb_state = SDMMC_CCB_FREE; 215 ccb->ccb_flags = 0; 216 ccb->ccb_xs = NULL; 217 218 TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link); 219 } 220 return 0; 221 } 222 223 void 224 sdmmc_free_ccbs(struct sdmmc_scsi_softc *scbus) 225 { 226 if (scbus->sc_ccbs != NULL) { 227 free(scbus->sc_ccbs, M_DEVBUF); 228 scbus->sc_ccbs = NULL; 229 } 230 } 231 232 void * 233 sdmmc_ccb_alloc(void *xscbus) 234 { 235 struct sdmmc_scsi_softc *scbus = xscbus; 236 struct sdmmc_ccb *ccb; 237 238 mtx_enter(&scbus->sc_ccb_mtx); 239 ccb = TAILQ_FIRST(&scbus->sc_ccb_freeq); 240 if (ccb != NULL) { 241 TAILQ_REMOVE(&scbus->sc_ccb_freeq, ccb, ccb_link); 242 ccb->ccb_state = SDMMC_CCB_READY; 243 } 244 mtx_leave(&scbus->sc_ccb_mtx); 245 246 return ccb; 247 } 248 249 void 250 sdmmc_ccb_free(void *xscbus, void *xccb) 251 { 252 struct sdmmc_scsi_softc *scbus = xscbus; 253 struct sdmmc_ccb *ccb = xccb; 254 int s; 255 256 s = splbio(); 257 if (ccb->ccb_state == SDMMC_CCB_QUEUED) 258 TAILQ_REMOVE(&scbus->sc_ccb_runq, ccb, ccb_link); 259 splx(s); 260 261 ccb->ccb_state = SDMMC_CCB_FREE; 262 ccb->ccb_flags = 0; 263 ccb->ccb_xs = NULL; 264 265 mtx_enter(&scbus->sc_ccb_mtx); 266 TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link); 267 mtx_leave(&scbus->sc_ccb_mtx); 268 } 269 270 /* 271 * SCSI command emulation 272 */ 273 274 /* XXX move to some sort of "scsi emulation layer". */ 275 static void 276 sdmmc_scsi_decode_rw(struct scsi_xfer *xs, u_int32_t *blocknop, 277 u_int32_t *blockcntp) 278 { 279 struct scsi_rw *rw; 280 struct scsi_rw_big *rwb; 281 282 if (xs->cmdlen == 6) { 283 rw = (struct scsi_rw *)xs->cmd; 284 *blocknop = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff); 285 *blockcntp = rw->length ? rw->length : 0x100; 286 } else { 287 rwb = (struct scsi_rw_big *)xs->cmd; 288 *blocknop = _4btol(rwb->addr); 289 *blockcntp = _2btol(rwb->length); 290 } 291 } 292 293 void 294 sdmmc_scsi_cmd(struct scsi_xfer *xs) 295 { 296 struct scsi_link *link = xs->sc_link; 297 struct sdmmc_softc *sc = link->adapter_softc; 298 struct sdmmc_scsi_softc *scbus = sc->sc_scsibus; 299 struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target]; 300 struct scsi_read_cap_data rcd; 301 u_int32_t blockno; 302 u_int32_t blockcnt; 303 struct sdmmc_ccb *ccb; 304 305 if (link->target >= scbus->sc_ntargets || tgt->card == NULL || 306 link->lun != 0) { 307 DPRINTF(("%s: sdmmc_scsi_cmd: no target %d\n", 308 DEVNAME(sc), link->target)); 309 /* XXX should be XS_SENSE and sense filled out */ 310 xs->error = XS_DRIVER_STUFFUP; 311 scsi_done(xs); 312 return; 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 sdmmc_inquiry(xs); 331 return; 332 333 case TEST_UNIT_READY: 334 case START_STOP: 335 case SYNCHRONIZE_CACHE: 336 scsi_done(xs); 337 return; 338 339 case READ_CAPACITY: 340 bzero(&rcd, sizeof rcd); 341 _lto4b(tgt->card->csd.capacity - 1, rcd.addr); 342 _lto4b(tgt->card->csd.sector_size, rcd.length); 343 bcopy(&rcd, xs->data, MIN(xs->datalen, sizeof rcd)); 344 scsi_done(xs); 345 return; 346 347 default: 348 DPRINTF(("%s: unsupported scsi command %#x\n", 349 DEVNAME(sc), xs->cmd->opcode)); 350 xs->error = XS_DRIVER_STUFFUP; 351 scsi_done(xs); 352 return; 353 } 354 355 /* A read or write operation. */ 356 sdmmc_scsi_decode_rw(xs, &blockno, &blockcnt); 357 358 if (blockno >= tgt->card->csd.capacity || 359 blockno + blockcnt > tgt->card->csd.capacity) { 360 DPRINTF(("%s: out of bounds %u-%u >= %u\n", DEVNAME(sc), 361 blockno, blockcnt, tgt->card->csd.capacity)); 362 xs->error = XS_DRIVER_STUFFUP; 363 scsi_done(xs); 364 return; 365 } 366 367 ccb = xs->io; 368 369 ccb->ccb_xs = xs; 370 ccb->ccb_blockcnt = blockcnt; 371 ccb->ccb_blockno = blockno; 372 373 sdmmc_start_xs(sc, ccb); 374 } 375 376 void 377 sdmmc_inquiry(struct scsi_xfer *xs) 378 { 379 struct scsi_link *link = xs->sc_link; 380 struct scsi_inquiry_data inq; 381 struct scsi_inquiry *cdb = (struct scsi_inquiry *)xs->cmd; 382 383 if (xs->cmdlen != sizeof(*cdb)) { 384 xs->error = XS_DRIVER_STUFFUP; 385 goto done; 386 } 387 388 if (ISSET(cdb->flags, SI_EVPD)) { 389 xs->error = XS_DRIVER_STUFFUP; 390 goto done; 391 } 392 393 bzero(&inq, sizeof inq); 394 inq.device = T_DIRECT; 395 inq.version = 2; 396 inq.response_format = 2; 397 inq.additional_length = 32; 398 strlcpy(inq.vendor, "SD/MMC ", sizeof(inq.vendor)); 399 snprintf(inq.product, sizeof(inq.product), 400 "Drive #%02d", link->target); 401 strlcpy(inq.revision, " ", sizeof(inq.revision)); 402 403 bcopy(&inq, xs->data, MIN(xs->datalen, sizeof(inq))); 404 405 done: 406 scsi_done(xs); 407 } 408 409 void 410 sdmmc_start_xs(struct sdmmc_softc *sc, struct sdmmc_ccb *ccb) 411 { 412 struct sdmmc_scsi_softc *scbus = sc->sc_scsibus; 413 struct scsi_xfer *xs = ccb->ccb_xs; 414 int s; 415 416 timeout_set(&xs->stimeout, sdmmc_stimeout, ccb); 417 sdmmc_init_task(&ccb->ccb_task, sdmmc_complete_xs, ccb); 418 419 s = splbio(); 420 TAILQ_INSERT_TAIL(&scbus->sc_ccb_runq, ccb, ccb_link); 421 ccb->ccb_state = SDMMC_CCB_QUEUED; 422 splx(s); 423 424 if (ISSET(xs->flags, SCSI_POLL)) { 425 sdmmc_complete_xs(ccb); 426 return; 427 } 428 429 timeout_add_msec(&xs->stimeout, xs->timeout); 430 sdmmc_add_task(sc, &ccb->ccb_task); 431 } 432 433 void 434 sdmmc_complete_xs(void *arg) 435 { 436 struct sdmmc_ccb *ccb = arg; 437 struct scsi_xfer *xs = ccb->ccb_xs; 438 struct scsi_link *link = xs->sc_link; 439 struct sdmmc_softc *sc = link->adapter_softc; 440 struct sdmmc_scsi_softc *scbus = sc->sc_scsibus; 441 struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target]; 442 int error; 443 int s; 444 445 DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (poll=%#x)" 446 " complete\n", DEVNAME(sc), link->target, xs->cmd->opcode, 447 curproc ? curproc->p_comm : "", xs->flags & SCSI_POLL)); 448 449 s = splbio(); 450 451 if (ISSET(xs->flags, SCSI_DATA_IN)) 452 error = sdmmc_mem_read_block(tgt->card, ccb->ccb_blockno, 453 xs->data, ccb->ccb_blockcnt * DEV_BSIZE); 454 else 455 error = sdmmc_mem_write_block(tgt->card, ccb->ccb_blockno, 456 xs->data, ccb->ccb_blockcnt * DEV_BSIZE); 457 458 if (error != 0) 459 xs->error = XS_DRIVER_STUFFUP; 460 461 sdmmc_done_xs(ccb); 462 splx(s); 463 } 464 465 void 466 sdmmc_done_xs(struct sdmmc_ccb *ccb) 467 { 468 struct scsi_xfer *xs = ccb->ccb_xs; 469 #ifdef SDMMC_DEBUG 470 struct scsi_link *link = xs->sc_link; 471 struct sdmmc_softc *sc = link->adapter_softc; 472 #endif 473 474 timeout_del(&xs->stimeout); 475 476 DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (error=%#x)" 477 " done\n", DEVNAME(sc), link->target, xs->cmd->opcode, 478 curproc ? curproc->p_comm : "", xs->error)); 479 480 xs->resid = 0; 481 482 if (ISSET(ccb->ccb_flags, SDMMC_CCB_F_ERR)) 483 xs->error = XS_DRIVER_STUFFUP; 484 485 scsi_done(xs); 486 } 487 488 void 489 sdmmc_stimeout(void *arg) 490 { 491 struct sdmmc_ccb *ccb = arg; 492 int s; 493 494 s = splbio(); 495 ccb->ccb_flags |= SDMMC_CCB_F_ERR; 496 if (sdmmc_task_pending(&ccb->ccb_task)) { 497 sdmmc_del_task(&ccb->ccb_task); 498 sdmmc_done_xs(ccb); 499 } 500 splx(s); 501 } 502 503 void 504 sdmmc_scsi_minphys(struct buf *bp, struct scsi_link *sl) 505 { 506 struct sdmmc_softc *sc = sl->adapter_softc; 507 struct sdmmc_scsi_softc *scbus = sc->sc_scsibus; 508 struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[sl->target]; 509 struct sdmmc_function *sf = tgt->card; 510 511 /* limit to max. transfer size supported by card/host */ 512 if (sc->sc_max_xfer != 0 && 513 bp->b_bcount > sf->csd.sector_size * sc->sc_max_xfer) 514 bp->b_bcount = sf->csd.sector_size * sc->sc_max_xfer; 515 516 minphys(bp); 517 } 518