LCOV - code coverage report
Current view: top level - dev/sdmmc - sdmmc_scsi.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 301 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: sdmmc_scsi.c,v 1.42 2018/03/30 07:18:39 jmatthew 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/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             : #ifdef HIBERNATE
      36             : #include <sys/hibernate.h>
      37             : #include <sys/disk.h>
      38             : #include <sys/disklabel.h>
      39             : #include <sys/rwlock.h>
      40             : #endif
      41             : 
      42             : #define SDMMC_SCSIID_HOST       0x00
      43             : #define SDMMC_SCSIID_MAX        0x0f
      44             : 
      45             : #define SDMMC_SCSI_MAXCMDS      8
      46             : 
      47             : struct sdmmc_scsi_target {
      48             :         struct sdmmc_function *card;
      49             : };
      50             : 
      51             : struct sdmmc_ccb {
      52             :         struct sdmmc_scsi_softc *ccb_scbus;
      53             :         struct scsi_xfer *ccb_xs;
      54             :         int ccb_flags;
      55             : #define SDMMC_CCB_F_ERR         0x0001
      56             :         u_int32_t ccb_blockno;
      57             :         u_int32_t ccb_blockcnt;
      58             :         volatile enum {
      59             :                 SDMMC_CCB_FREE,
      60             :                 SDMMC_CCB_READY,
      61             :                 SDMMC_CCB_QUEUED
      62             :         } ccb_state;
      63             :         struct sdmmc_command ccb_cmd;
      64             :         struct sdmmc_task ccb_task;
      65             :         TAILQ_ENTRY(sdmmc_ccb) ccb_link;
      66             : };
      67             : 
      68             : TAILQ_HEAD(sdmmc_ccb_list, sdmmc_ccb);
      69             : 
      70             : struct sdmmc_scsi_softc {
      71             :         struct scsi_adapter sc_adapter;
      72             :         struct scsi_link sc_link;
      73             :         struct device *sc_child;
      74             :         struct sdmmc_scsi_target *sc_tgt;
      75             :         int sc_ntargets;
      76             :         struct sdmmc_ccb *sc_ccbs;              /* allocated ccbs */
      77             :         int             sc_nccbs;
      78             :         struct sdmmc_ccb_list sc_ccb_freeq;     /* free ccbs */
      79             :         struct sdmmc_ccb_list sc_ccb_runq;      /* queued ccbs */
      80             :         struct mutex sc_ccb_mtx;
      81             :         struct scsi_iopool sc_iopool;
      82             : };
      83             : 
      84             : int     sdmmc_alloc_ccbs(struct sdmmc_scsi_softc *, int);
      85             : void    sdmmc_free_ccbs(struct sdmmc_scsi_softc *);
      86             : void    *sdmmc_ccb_alloc(void *);
      87             : void    sdmmc_ccb_free(void *, void *);
      88             : 
      89             : void    sdmmc_scsi_cmd(struct scsi_xfer *);
      90             : void    sdmmc_inquiry(struct scsi_xfer *);
      91             : void    sdmmc_start_xs(struct sdmmc_softc *, struct sdmmc_ccb *);
      92             : void    sdmmc_complete_xs(void *);
      93             : void    sdmmc_done_xs(struct sdmmc_ccb *);
      94             : void    sdmmc_stimeout(void *);
      95             : void    sdmmc_scsi_minphys(struct buf *, struct scsi_link *);
      96             : 
      97             : #ifdef SDMMC_DEBUG
      98             : #define DPRINTF(s)      printf s
      99             : #else
     100             : #define DPRINTF(s)      /**/
     101             : #endif
     102             : 
     103             : void
     104           0 : sdmmc_scsi_attach(struct sdmmc_softc *sc)
     105             : {
     106           0 :         struct sdmmc_attach_args saa;
     107             :         struct sdmmc_scsi_softc *scbus;
     108             :         struct sdmmc_function *sf;
     109             : 
     110           0 :         rw_assert_wrlock(&sc->sc_lock);
     111             : 
     112           0 :         scbus = malloc(sizeof *scbus, M_DEVBUF, M_WAITOK | M_ZERO);
     113             : 
     114           0 :         scbus->sc_tgt = mallocarray(sizeof(*scbus->sc_tgt),
     115             :             (SDMMC_SCSIID_MAX+1), M_DEVBUF, M_WAITOK | M_ZERO);
     116             : 
     117             :         /*
     118             :          * Each card that sent us a CID in the identification stage
     119             :          * gets a SCSI ID > 0, whether it is a memory card or not.
     120             :          */
     121           0 :         scbus->sc_ntargets = 1;
     122           0 :         SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
     123           0 :                 if (scbus->sc_ntargets >= SDMMC_SCSIID_MAX+1)
     124             :                         break;
     125           0 :                 scbus->sc_tgt[scbus->sc_ntargets].card = sf;
     126           0 :                 scbus->sc_ntargets++;
     127             :         }
     128             : 
     129             :         /* Preallocate some CCBs and initialize the CCB lists. */
     130           0 :         if (sdmmc_alloc_ccbs(scbus, SDMMC_SCSI_MAXCMDS) != 0) {
     131           0 :                 printf("%s: can't allocate ccbs\n", sc->sc_dev.dv_xname);
     132           0 :                 goto free_sctgt;
     133             :         }
     134             : 
     135           0 :         sc->sc_scsibus = scbus;
     136             : 
     137           0 :         scbus->sc_adapter.scsi_cmd = sdmmc_scsi_cmd;
     138           0 :         scbus->sc_adapter.scsi_minphys = sdmmc_scsi_minphys;
     139             : 
     140           0 :         scbus->sc_link.adapter_target = SDMMC_SCSIID_HOST;
     141           0 :         scbus->sc_link.adapter_buswidth = scbus->sc_ntargets;
     142           0 :         scbus->sc_link.adapter_softc = sc;
     143           0 :         scbus->sc_link.luns = 1;
     144           0 :         scbus->sc_link.openings = 1;
     145           0 :         scbus->sc_link.adapter = &scbus->sc_adapter;
     146           0 :         scbus->sc_link.pool = &scbus->sc_iopool;
     147             : 
     148           0 :         bzero(&saa, sizeof(saa));
     149           0 :         saa.scsi_link = &scbus->sc_link;
     150             : 
     151           0 :         scbus->sc_child = config_found(&sc->sc_dev, &saa, scsiprint);
     152           0 :         if (scbus->sc_child == NULL) {
     153           0 :                 printf("%s: can't attach scsibus\n", sc->sc_dev.dv_xname);
     154             :                 goto free_ccbs;
     155             :         }
     156           0 :         return;
     157             : 
     158             :  free_ccbs:
     159           0 :         sc->sc_scsibus = NULL;
     160           0 :         sdmmc_free_ccbs(scbus);
     161             :  free_sctgt:
     162           0 :         free(scbus->sc_tgt, M_DEVBUF,
     163             :             sizeof(*scbus->sc_tgt) * (SDMMC_SCSIID_MAX+1));
     164           0 :         free(scbus, M_DEVBUF, sizeof *scbus);
     165           0 : }
     166             : 
     167             : void
     168           0 : sdmmc_scsi_detach(struct sdmmc_softc *sc)
     169             : {
     170             :         struct sdmmc_scsi_softc *scbus;
     171             :         struct sdmmc_ccb *ccb;
     172             :         int s;
     173             : 
     174           0 :         rw_assert_wrlock(&sc->sc_lock);
     175             : 
     176           0 :         scbus = sc->sc_scsibus;
     177           0 :         if (scbus == NULL)
     178           0 :                 return;
     179             : 
     180             :         /* Complete all open scsi xfers. */
     181           0 :         s = splbio();
     182           0 :         for (ccb = TAILQ_FIRST(&scbus->sc_ccb_runq); ccb != NULL;
     183           0 :              ccb = TAILQ_FIRST(&scbus->sc_ccb_runq))
     184           0 :                 sdmmc_stimeout(ccb);
     185           0 :         splx(s);
     186             : 
     187           0 :         if (scbus->sc_child != NULL)
     188           0 :                 config_detach(scbus->sc_child, DETACH_FORCE);
     189             : 
     190           0 :         if (scbus->sc_tgt != NULL)
     191           0 :                 free(scbus->sc_tgt, M_DEVBUF,
     192             :                     sizeof(*scbus->sc_tgt) * (SDMMC_SCSIID_MAX+1));
     193             : 
     194           0 :         sdmmc_free_ccbs(scbus);
     195           0 :         free(scbus, M_DEVBUF, sizeof *scbus);
     196           0 :         sc->sc_scsibus = NULL;
     197           0 : }
     198             : 
     199             : /*
     200             :  * CCB management
     201             :  */
     202             : 
     203             : int
     204           0 : sdmmc_alloc_ccbs(struct sdmmc_scsi_softc *scbus, int nccbs)
     205             : {
     206             :         struct sdmmc_ccb *ccb;
     207             :         int i;
     208             : 
     209           0 :         scbus->sc_ccbs = mallocarray(nccbs, sizeof(struct sdmmc_ccb),
     210             :             M_DEVBUF, M_NOWAIT);
     211           0 :         if (scbus->sc_ccbs == NULL)
     212           0 :                 return 1;
     213           0 :         scbus->sc_nccbs = nccbs;
     214             : 
     215           0 :         TAILQ_INIT(&scbus->sc_ccb_freeq);
     216           0 :         TAILQ_INIT(&scbus->sc_ccb_runq);
     217           0 :         mtx_init(&scbus->sc_ccb_mtx, IPL_BIO);
     218           0 :         scsi_iopool_init(&scbus->sc_iopool, scbus, sdmmc_ccb_alloc,
     219             :             sdmmc_ccb_free);
     220             : 
     221           0 :         for (i = 0; i < nccbs; i++) {
     222           0 :                 ccb = &scbus->sc_ccbs[i];
     223           0 :                 ccb->ccb_scbus = scbus;
     224           0 :                 ccb->ccb_state = SDMMC_CCB_FREE;
     225           0 :                 ccb->ccb_flags = 0;
     226           0 :                 ccb->ccb_xs = NULL;
     227             : 
     228           0 :                 TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link);
     229             :         }
     230           0 :         return 0;
     231           0 : }
     232             : 
     233             : void
     234           0 : sdmmc_free_ccbs(struct sdmmc_scsi_softc *scbus)
     235             : {
     236           0 :         if (scbus->sc_ccbs != NULL) {
     237           0 :                 free(scbus->sc_ccbs, M_DEVBUF,
     238           0 :                     scbus->sc_nccbs * sizeof(struct sdmmc_ccb));
     239           0 :                 scbus->sc_ccbs = NULL;
     240           0 :         }
     241           0 : }
     242             : 
     243             : void *
     244           0 : sdmmc_ccb_alloc(void *xscbus)
     245             : {
     246           0 :         struct sdmmc_scsi_softc *scbus = xscbus;
     247             :         struct sdmmc_ccb *ccb;
     248             : 
     249           0 :         mtx_enter(&scbus->sc_ccb_mtx);
     250           0 :         ccb = TAILQ_FIRST(&scbus->sc_ccb_freeq);
     251           0 :         if (ccb != NULL) {
     252           0 :                 TAILQ_REMOVE(&scbus->sc_ccb_freeq, ccb, ccb_link);
     253           0 :                 ccb->ccb_state = SDMMC_CCB_READY;
     254           0 :         }
     255           0 :         mtx_leave(&scbus->sc_ccb_mtx);
     256             : 
     257           0 :         return ccb;
     258             : }
     259             : 
     260             : void
     261           0 : sdmmc_ccb_free(void *xscbus, void *xccb)
     262             : {
     263           0 :         struct sdmmc_scsi_softc *scbus = xscbus;
     264           0 :         struct sdmmc_ccb *ccb = xccb;
     265             :         int s;
     266             : 
     267           0 :         s = splbio();
     268           0 :         if (ccb->ccb_state == SDMMC_CCB_QUEUED)
     269           0 :                 TAILQ_REMOVE(&scbus->sc_ccb_runq, ccb, ccb_link);
     270           0 :         splx(s);
     271             : 
     272           0 :         ccb->ccb_state = SDMMC_CCB_FREE;
     273           0 :         ccb->ccb_flags = 0;
     274           0 :         ccb->ccb_xs = NULL;
     275             : 
     276           0 :         mtx_enter(&scbus->sc_ccb_mtx);
     277           0 :         TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link);
     278           0 :         mtx_leave(&scbus->sc_ccb_mtx);
     279           0 : }
     280             : 
     281             : /*
     282             :  * SCSI command emulation
     283             :  */
     284             : 
     285             : /* XXX move to some sort of "scsi emulation layer". */
     286             : static void
     287           0 : sdmmc_scsi_decode_rw(struct scsi_xfer *xs, u_int32_t *blocknop,
     288             :     u_int32_t *blockcntp)
     289             : {
     290             :         struct scsi_rw *rw;
     291             :         struct scsi_rw_big *rwb;
     292             :         
     293           0 :         if (xs->cmdlen == 6) {
     294           0 :                 rw = (struct scsi_rw *)xs->cmd;
     295           0 :                 *blocknop = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff);
     296           0 :                 *blockcntp = rw->length ? rw->length : 0x100;
     297           0 :         } else {
     298           0 :                 rwb = (struct scsi_rw_big *)xs->cmd;
     299           0 :                 *blocknop = _4btol(rwb->addr);
     300           0 :                 *blockcntp = _2btol(rwb->length);
     301             :         }
     302           0 : }
     303             : 
     304             : void
     305           0 : sdmmc_scsi_cmd(struct scsi_xfer *xs)
     306             : {
     307           0 :         struct scsi_link *link = xs->sc_link;
     308           0 :         struct sdmmc_softc *sc = link->adapter_softc;
     309           0 :         struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
     310           0 :         struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
     311           0 :         struct scsi_read_cap_data rcd;
     312           0 :         u_int32_t blockno;
     313           0 :         u_int32_t blockcnt;
     314             :         struct sdmmc_ccb *ccb;
     315             : 
     316           0 :         if (link->target >= scbus->sc_ntargets || tgt->card == NULL ||
     317           0 :             link->lun != 0) {
     318             :                 DPRINTF(("%s: sdmmc_scsi_cmd: no target %d\n",
     319             :                     DEVNAME(sc), link->target));
     320             :                 /* XXX should be XS_SENSE and sense filled out */
     321           0 :                 xs->error = XS_DRIVER_STUFFUP;
     322           0 :                 scsi_done(xs);
     323           0 :                 return;
     324             :         }
     325             : 
     326             :         DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (poll=%#x)\n",
     327             :             DEVNAME(sc), link->target, xs->cmd->opcode, curproc ?
     328             :             curproc->p_p->ps_comm : "", xs->flags & SCSI_POLL));
     329             : 
     330           0 :         xs->error = XS_NOERROR;
     331             : 
     332           0 :         switch (xs->cmd->opcode) {
     333             :         case READ_COMMAND:
     334             :         case READ_BIG:
     335             :         case WRITE_COMMAND:
     336             :         case WRITE_BIG:
     337             :                 /* Deal with I/O outside the switch. */
     338             :                 break;
     339             : 
     340             :         case INQUIRY:
     341           0 :                 sdmmc_inquiry(xs);
     342           0 :                 return;
     343             : 
     344             :         case TEST_UNIT_READY:
     345             :         case START_STOP:
     346             :         case SYNCHRONIZE_CACHE:
     347           0 :                 scsi_done(xs);
     348           0 :                 return;
     349             : 
     350             :         case READ_CAPACITY:
     351           0 :                 bzero(&rcd, sizeof rcd);
     352           0 :                 _lto4b(tgt->card->csd.capacity - 1, rcd.addr);
     353           0 :                 _lto4b(tgt->card->csd.sector_size, rcd.length);
     354           0 :                 bcopy(&rcd, xs->data, MIN(xs->datalen, sizeof rcd));
     355           0 :                 scsi_done(xs);
     356           0 :                 return;
     357             : 
     358             :         default:
     359             :                 DPRINTF(("%s: unsupported scsi command %#x\n",
     360             :                     DEVNAME(sc), xs->cmd->opcode));
     361           0 :                 xs->error = XS_DRIVER_STUFFUP;
     362           0 :                 scsi_done(xs);
     363           0 :                 return;
     364             :         }
     365             : 
     366             :         /* A read or write operation. */
     367           0 :         sdmmc_scsi_decode_rw(xs, &blockno, &blockcnt);
     368             : 
     369           0 :         if (blockno >= tgt->card->csd.capacity ||
     370           0 :             blockno + blockcnt > tgt->card->csd.capacity) {
     371             :                 DPRINTF(("%s: out of bounds %u-%u >= %u\n", DEVNAME(sc),
     372             :                     blockno, blockcnt, tgt->card->csd.capacity));
     373           0 :                 xs->error = XS_DRIVER_STUFFUP;
     374           0 :                 scsi_done(xs);
     375           0 :                 return;
     376             :         }
     377             : 
     378           0 :         ccb = xs->io;
     379             : 
     380           0 :         ccb->ccb_xs = xs;
     381           0 :         ccb->ccb_blockcnt = blockcnt;
     382           0 :         ccb->ccb_blockno = blockno;
     383             : 
     384           0 :         sdmmc_start_xs(sc, ccb);
     385           0 : }
     386             : 
     387             : void
     388           0 : sdmmc_inquiry(struct scsi_xfer *xs)
     389             : {
     390           0 :         struct scsi_link *link = xs->sc_link;
     391           0 :         struct sdmmc_softc *sc = link->adapter_softc;
     392           0 :         struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
     393           0 :         struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
     394           0 :         struct scsi_inquiry_data inq;
     395           0 :         struct scsi_inquiry *cdb = (struct scsi_inquiry *)xs->cmd;
     396           0 :         char vendor[sizeof(inq.vendor) + 1];
     397           0 :         char product[sizeof(inq.product) + 1];
     398           0 :         char revision[sizeof(inq.revision) + 1];
     399             : 
     400           0 :         if (xs->cmdlen != sizeof(*cdb)) {
     401           0 :                 xs->error = XS_DRIVER_STUFFUP;
     402           0 :                 goto done;
     403             :         }
     404             : 
     405           0 :         if (ISSET(cdb->flags, SI_EVPD)) {
     406           0 :                 xs->error = XS_DRIVER_STUFFUP;
     407           0 :                 goto done;
     408             :         }
     409             : 
     410           0 :         memset(vendor, 0, sizeof(vendor));
     411           0 :         memset(product, 0, sizeof(product));
     412           0 :         memset(revision, 0, sizeof(revision));
     413           0 :         switch (tgt->card->cid.mid) {
     414             :         case 0x02:
     415             :         case 0x45:
     416           0 :                 strlcpy(vendor, "Sandisk", sizeof(vendor));
     417           0 :                 break;
     418             :         case 0x11:
     419           0 :                 strlcpy(vendor, "Toshiba", sizeof(vendor));
     420           0 :                 break;
     421             :         case 0x13:
     422           0 :                 strlcpy(vendor, "Micron", sizeof(vendor));
     423           0 :                 break;
     424             :         case 0x15:
     425           0 :                 strlcpy(vendor, "Samsung", sizeof(vendor));
     426           0 :                 break;
     427             :         case 0x70:
     428           0 :                 strlcpy(vendor, "Kingston", sizeof(vendor));
     429           0 :                 break;
     430             :         default:
     431           0 :                 strlcpy(vendor, "SD/MMC", sizeof(vendor));
     432           0 :                 break;
     433             :         }
     434           0 :         strlcpy(product, tgt->card->cid.pnm, sizeof(product));
     435           0 :         snprintf(revision, sizeof(revision), "%04X", tgt->card->cid.rev);
     436             : 
     437           0 :         memset(&inq, 0, sizeof inq);
     438           0 :         inq.device = T_DIRECT;
     439           0 :         inq.dev_qual2 = SID_REMOVABLE;
     440           0 :         inq.version = 2;
     441           0 :         inq.response_format = 2;
     442           0 :         inq.additional_length = 32;
     443           0 :         memcpy(inq.vendor, vendor, sizeof(inq.vendor));
     444           0 :         memcpy(inq.product, product, sizeof(inq.product));
     445           0 :         memcpy(inq.revision, revision, sizeof(inq.revision));
     446             : 
     447           0 :         memcpy(xs->data, &inq, MIN(xs->datalen, sizeof(inq)));
     448             : 
     449             : done:
     450           0 :         scsi_done(xs);
     451           0 : }
     452             : 
     453             : void
     454           0 : sdmmc_start_xs(struct sdmmc_softc *sc, struct sdmmc_ccb *ccb)
     455             : {
     456           0 :         struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
     457           0 :         struct scsi_xfer *xs = ccb->ccb_xs;
     458             :         int s;
     459             : 
     460           0 :         timeout_set(&xs->stimeout, sdmmc_stimeout, ccb);
     461           0 :         sdmmc_init_task(&ccb->ccb_task, sdmmc_complete_xs, ccb);
     462             : 
     463           0 :         s = splbio();
     464           0 :         TAILQ_INSERT_TAIL(&scbus->sc_ccb_runq, ccb, ccb_link);
     465           0 :         ccb->ccb_state = SDMMC_CCB_QUEUED;
     466           0 :         splx(s);
     467             : 
     468           0 :         if (ISSET(xs->flags, SCSI_POLL)) {
     469           0 :                 sdmmc_complete_xs(ccb);
     470           0 :                 return;
     471             :         }
     472             : 
     473           0 :         timeout_add_msec(&xs->stimeout, xs->timeout);
     474           0 :         sdmmc_add_task(sc, &ccb->ccb_task);
     475           0 : }
     476             : 
     477             : void
     478           0 : sdmmc_complete_xs(void *arg)
     479             : {
     480           0 :         struct sdmmc_ccb *ccb = arg;
     481           0 :         struct scsi_xfer *xs = ccb->ccb_xs;
     482           0 :         struct scsi_link *link = xs->sc_link;
     483           0 :         struct sdmmc_softc *sc = link->adapter_softc;
     484           0 :         struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
     485           0 :         struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
     486             :         int error;
     487             :         int s;
     488             : 
     489             :         DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (poll=%#x)"
     490             :             " complete\n", DEVNAME(sc), link->target, xs->cmd->opcode,
     491             :             curproc ? curproc->p_p->ps_comm : "", xs->flags & SCSI_POLL));
     492             : 
     493           0 :         s = splbio();
     494             : 
     495           0 :         if (ISSET(xs->flags, SCSI_DATA_IN))
     496           0 :                 error = sdmmc_mem_read_block(tgt->card, ccb->ccb_blockno,
     497             :                     xs->data, ccb->ccb_blockcnt * DEV_BSIZE);
     498             :         else
     499           0 :                 error = sdmmc_mem_write_block(tgt->card, ccb->ccb_blockno,
     500             :                     xs->data, ccb->ccb_blockcnt * DEV_BSIZE);
     501             : 
     502           0 :         if (error != 0)
     503           0 :                 xs->error = XS_DRIVER_STUFFUP;
     504             : 
     505           0 :         sdmmc_done_xs(ccb);
     506           0 :         splx(s);
     507           0 : }
     508             : 
     509             : void
     510           0 : sdmmc_done_xs(struct sdmmc_ccb *ccb)
     511             : {
     512           0 :         struct scsi_xfer *xs = ccb->ccb_xs;
     513             : #ifdef SDMMC_DEBUG
     514             :         struct scsi_link *link = xs->sc_link;
     515             :         struct sdmmc_softc *sc = link->adapter_softc;
     516             : #endif
     517             : 
     518           0 :         timeout_del(&xs->stimeout);
     519             : 
     520             :         DPRINTF(("%s: scsi cmd target=%d opcode=%#x proc=\"%s\" (error=%#x)"
     521             :             " done\n", DEVNAME(sc), link->target, xs->cmd->opcode,
     522             :             curproc ? curproc->p_p->ps_comm : "", xs->error));
     523             : 
     524           0 :         xs->resid = 0;
     525             : 
     526           0 :         if (ISSET(ccb->ccb_flags, SDMMC_CCB_F_ERR))
     527           0 :                 xs->error = XS_DRIVER_STUFFUP;
     528             : 
     529           0 :         scsi_done(xs);
     530           0 : }
     531             : 
     532             : void
     533           0 : sdmmc_stimeout(void *arg)
     534             : {
     535           0 :         struct sdmmc_ccb *ccb = arg;
     536             :         int s;
     537             : 
     538           0 :         s = splbio();
     539           0 :         ccb->ccb_flags |= SDMMC_CCB_F_ERR;
     540           0 :         if (sdmmc_task_pending(&ccb->ccb_task)) {
     541           0 :                 sdmmc_del_task(&ccb->ccb_task);
     542           0 :                 sdmmc_done_xs(ccb);
     543           0 :         }
     544           0 :         splx(s);
     545           0 : }
     546             : 
     547             : void
     548           0 : sdmmc_scsi_minphys(struct buf *bp, struct scsi_link *sl)
     549             : {
     550           0 :         struct sdmmc_softc *sc = sl->adapter_softc;
     551           0 :         struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
     552           0 :         struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[sl->target];
     553           0 :         struct sdmmc_function *sf = tgt->card;
     554             : 
     555             :         /* limit to max. transfer size supported by card/host */
     556           0 :         if (sc->sc_max_xfer != 0 &&
     557           0 :             bp->b_bcount > sf->csd.sector_size * sc->sc_max_xfer)
     558           0 :                 bp->b_bcount = sf->csd.sector_size * sc->sc_max_xfer;
     559             : 
     560           0 :         minphys(bp);
     561           0 : }
     562             : 
     563             : #ifdef HIBERNATE
     564             : int
     565           0 : sdmmc_scsi_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size,
     566             :     int op, void *page)
     567             : {
     568             :         struct {
     569             :                 struct sdmmc_softc sdmmc_sc;
     570             :                 struct sdmmc_function sdmmc_sf;
     571             :                 daddr_t poffset;
     572             :                 size_t psize;
     573             :                 struct sdmmc_function *orig_sf;
     574             :                 char chipset_softc[0];  /* size depends on the chipset layer */
     575           0 :         } *state = page;
     576             :         extern struct cfdriver sd_cd;
     577             :         struct device *disk, *scsibus, *chip, *sdmmc;
     578             :         struct scsibus_softc *bus_sc;
     579             :         struct sdmmc_scsi_softc *scsi_sc;
     580             :         struct scsi_link *link;
     581             :         struct sdmmc_function *sf;
     582             :         struct sdmmc_softc *sc;
     583             :         int error;
     584             : 
     585           0 :         switch (op) {
     586             :         case HIB_INIT:
     587             :                 /* find device (sdmmc_softc, sdmmc_function) */
     588           0 :                 disk = disk_lookup(&sd_cd, DISKUNIT(dev));
     589           0 :                 if (disk == NULL)
     590           0 :                         return (ENOTTY);
     591             : 
     592           0 :                 scsibus = disk->dv_parent;
     593           0 :                 sdmmc = scsibus->dv_parent;
     594           0 :                 chip = sdmmc->dv_parent;
     595             : 
     596           0 :                 bus_sc = (struct scsibus_softc *)scsibus;
     597             :                 scsi_sc = (struct sdmmc_scsi_softc *)scsibus;
     598             :                 sc = NULL;
     599           0 :                 SLIST_FOREACH(link, &bus_sc->sc_link_list, bus_list) {
     600           0 :                         if (link->device_softc == disk) {
     601           0 :                                 sc = (struct sdmmc_softc *)link->adapter_softc;
     602           0 :                                 scsi_sc = sc->sc_scsibus;
     603           0 :                                 sf = scsi_sc->sc_tgt[link->target].card;
     604           0 :                         }
     605             :                 }
     606           0 :                 if (sc == NULL || sf == NULL)
     607           0 :                         return (ENOTTY);
     608             : 
     609             :                 /* if the chipset doesn't do hibernate, bail out now */
     610           0 :                 sc = (struct sdmmc_softc *)sdmmc;
     611           0 :                 if (sc->sct->hibernate_init == NULL)
     612           0 :                         return (ENOTTY);
     613             : 
     614           0 :                 state->sdmmc_sc = *sc;
     615           0 :                 state->sdmmc_sf = *sf;
     616           0 :                 state->sdmmc_sf.sc = &state->sdmmc_sc;
     617             : 
     618             :                 /* pretend we own the lock */
     619           0 :                 state->sdmmc_sc.sc_lock.rwl_owner =
     620           0 :                     (((long)curproc) & ~RWLOCK_MASK) | RWLOCK_WRLOCK;
     621             : 
     622             :                 /* build chip layer fake softc */
     623           0 :                 error = state->sdmmc_sc.sct->hibernate_init(state->sdmmc_sc.sch,
     624           0 :                     &state->chipset_softc);
     625           0 :                 if (error)
     626           0 :                         return (error);
     627           0 :                 state->sdmmc_sc.sch = state->chipset_softc;
     628             : 
     629             :                 /* make sure we're talking to the right target */
     630           0 :                 state->orig_sf = sc->sc_card;
     631           0 :                 error = sdmmc_select_card(&state->sdmmc_sc, &state->sdmmc_sf);
     632           0 :                 if (error)
     633           0 :                         return (error);
     634             : 
     635           0 :                 state->poffset = blkno;
     636           0 :                 state->psize = size;
     637           0 :                 return (0);
     638             : 
     639             :         case HIB_W:
     640           0 :                 if (blkno > state->psize)
     641           0 :                         return (E2BIG);
     642           0 :                 return (sdmmc_mem_hibernate_write(&state->sdmmc_sf,
     643           0 :                     blkno + state->poffset, (u_char *)addr, size));
     644             : 
     645             :         case HIB_DONE:
     646             :                 /*
     647             :                  * bring the hardware state back into line with the real
     648             :                  * softc by operating on the fake one
     649             :                  */
     650           0 :                 return (sdmmc_select_card(&state->sdmmc_sc, state->orig_sf));
     651             :         }
     652             : 
     653           0 :         return (EINVAL);
     654           0 : }
     655             : 
     656             : #endif

Generated by: LCOV version 1.13