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