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