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