The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/cam/mmc/mmc_da.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2006 Bernd Walter <tisco@FreeBSD.org> All rights reserved.
    5  * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org> All rights reserved.
    6  * Copyright (c) 2015-2017 Ilya Bakulin <kibab@FreeBSD.org> All rights reserved.
    7  * Copyright (c) 2006 M. Warner Losh <imp@FreeBSD.org>
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer,
   14  *    without modification, immediately at the beginning of the file.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29  *
   30  * Some code derived from the sys/dev/mmc and sys/cam/ata
   31  * Thanks to Warner Losh <imp@FreeBSD.org>, Alexander Motin <mav@FreeBSD.org>
   32  * Bernd Walter <tisco@FreeBSD.org>, and other authors.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD$");
   37 
   38 //#include "opt_sdda.h"
   39 
   40 #include <sys/param.h>
   41 
   42 #ifdef _KERNEL
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/bio.h>
   46 #include <sys/sysctl.h>
   47 #include <sys/endian.h>
   48 #include <sys/taskqueue.h>
   49 #include <sys/lock.h>
   50 #include <sys/mutex.h>
   51 #include <sys/conf.h>
   52 #include <sys/devicestat.h>
   53 #include <sys/eventhandler.h>
   54 #include <sys/malloc.h>
   55 #include <sys/cons.h>
   56 #include <sys/proc.h>
   57 #include <sys/reboot.h>
   58 #include <geom/geom_disk.h>
   59 #include <machine/_inttypes.h>  /* for PRIu64 */
   60 #endif /* _KERNEL */
   61 
   62 #ifndef _KERNEL
   63 #include <stdio.h>
   64 #include <string.h>
   65 #endif /* _KERNEL */
   66 
   67 #include <cam/cam.h>
   68 #include <cam/cam_ccb.h>
   69 #include <cam/cam_queue.h>
   70 #include <cam/cam_periph.h>
   71 #include <cam/cam_sim.h>
   72 #include <cam/cam_xpt.h>
   73 #include <cam/cam_xpt_sim.h>
   74 #include <cam/cam_xpt_periph.h>
   75 #include <cam/cam_xpt_internal.h>
   76 #include <cam/cam_debug.h>
   77 
   78 #include <cam/mmc/mmc_all.h>
   79 
   80 #ifdef _KERNEL
   81 
   82 typedef enum {
   83         SDDA_FLAG_OPEN          = 0x0002,
   84         SDDA_FLAG_DIRTY         = 0x0004
   85 } sdda_flags;
   86 
   87 typedef enum {
   88         SDDA_STATE_INIT,
   89         SDDA_STATE_INVALID,
   90         SDDA_STATE_NORMAL,
   91         SDDA_STATE_PART_SWITCH,
   92 } sdda_state;
   93 
   94 #define SDDA_FMT_BOOT           "sdda%dboot"
   95 #define SDDA_FMT_GP             "sdda%dgp"
   96 #define SDDA_FMT_RPMB           "sdda%drpmb"
   97 #define SDDA_LABEL_ENH          "enh"
   98 
   99 #define SDDA_PART_NAMELEN       (16 + 1)
  100 
  101 struct sdda_softc;
  102 
  103 struct sdda_part {
  104         struct disk *disk;
  105         struct bio_queue_head bio_queue;
  106         sdda_flags flags;
  107         struct sdda_softc *sc;
  108         u_int cnt;
  109         u_int type;
  110         bool ro;
  111         char name[SDDA_PART_NAMELEN];
  112 };
  113 
  114 struct sdda_softc {
  115         int      outstanding_cmds;      /* Number of active commands */
  116         int      refcount;              /* Active xpt_action() calls */
  117         sdda_state state;
  118         struct mmc_data *mmcdata;
  119         struct cam_periph *periph;
  120 //      sdda_quirks quirks;
  121         struct task start_init_task;
  122         uint32_t raw_csd[4];
  123         uint8_t raw_ext_csd[512]; /* MMC only? */
  124         struct mmc_csd csd;
  125         struct mmc_cid cid;
  126         struct mmc_scr scr;
  127         /* Calculated from CSD */
  128         uint64_t sector_count;
  129         uint64_t mediasize;
  130 
  131         /* Calculated from CID */
  132         char card_id_string[64];/* Formatted CID info (serial, MFG, etc) */
  133         char card_sn_string[16];/* Formatted serial # for disk->d_ident */
  134         /* Determined from CSD + is highspeed card*/
  135         uint32_t card_f_max;
  136 
  137         /* Generic switch timeout */
  138         uint32_t cmd6_time;
  139         uint32_t timings;       /* Mask of bus timings supported */
  140         uint32_t vccq_120;      /* Mask of bus timings at VCCQ of 1.2 V */
  141         uint32_t vccq_180;      /* Mask of bus timings at VCCQ of 1.8 V */
  142         /* MMC partitions support */
  143         struct sdda_part *part[MMC_PART_MAX];
  144         uint8_t part_curr;      /* Partition currently switched to */
  145         uint8_t part_requested; /* What partition we're currently switching to */
  146         uint32_t part_time;     /* Partition switch timeout [us] */
  147         off_t enh_base;         /* Enhanced user data area slice base ... */
  148         off_t enh_size;         /* ... and size [bytes] */
  149         int log_count;
  150         struct timeval log_time;
  151 };
  152 
  153 static const char *mmc_errmsg[] =
  154 {
  155         "None",
  156         "Timeout",
  157         "Bad CRC",
  158         "Fifo",
  159         "Failed",
  160         "Invalid",
  161         "NO MEMORY"
  162 };
  163 
  164 #define ccb_bp          ppriv_ptr1
  165 
  166 static  disk_strategy_t sddastrategy;
  167 static  dumper_t        sddadump;
  168 static  periph_init_t   sddainit;
  169 static  void            sddaasync(void *callback_arg, u_int32_t code,
  170                                 struct cam_path *path, void *arg);
  171 static  periph_ctor_t   sddaregister;
  172 static  periph_dtor_t   sddacleanup;
  173 static  periph_start_t  sddastart;
  174 static  periph_oninv_t  sddaoninvalidate;
  175 static  void            sddadone(struct cam_periph *periph,
  176                                union ccb *done_ccb);
  177 static  int             sddaerror(union ccb *ccb, u_int32_t cam_flags,
  178                                 u_int32_t sense_flags);
  179 
  180 static int mmc_handle_reply(union ccb *ccb);
  181 static uint16_t get_rca(struct cam_periph *periph);
  182 static void sdda_start_init(void *context, union ccb *start_ccb);
  183 static void sdda_start_init_task(void *context, int pending);
  184 static void sdda_process_mmc_partitions(struct cam_periph *periph, union ccb *start_ccb);
  185 static uint32_t sdda_get_host_caps(struct cam_periph *periph, union ccb *ccb);
  186 static int mmc_select_card(struct cam_periph *periph, union ccb *ccb, uint32_t rca);
  187 static inline uint32_t mmc_get_sector_size(struct cam_periph *periph) {return MMC_SECTOR_SIZE;}
  188 
  189 static SYSCTL_NODE(_kern_cam, OID_AUTO, sdda, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  190     "CAM Direct Access Disk driver");
  191 
  192 static int sdda_mmcsd_compat = 1;
  193 SYSCTL_INT(_kern_cam_sdda, OID_AUTO, mmcsd_compat, CTLFLAG_RDTUN,
  194     &sdda_mmcsd_compat, 1, "Enable creation of mmcsd aliases.");
  195 
  196 /* TODO: actually issue GET_TRAN_SETTINGS to get R/O status */
  197 static inline bool sdda_get_read_only(struct cam_periph *periph, union ccb *start_ccb)
  198 {
  199 
  200         return (false);
  201 }
  202 
  203 static uint32_t mmc_get_spec_vers(struct cam_periph *periph);
  204 static uint64_t mmc_get_media_size(struct cam_periph *periph);
  205 static uint32_t mmc_get_cmd6_timeout(struct cam_periph *periph);
  206 static bool sdda_add_part(struct cam_periph *periph, u_int type,
  207     const char *name, u_int cnt, off_t media_size, bool ro);
  208 
  209 static struct periph_driver sddadriver =
  210 {
  211         sddainit, "sdda",
  212         TAILQ_HEAD_INITIALIZER(sddadriver.units), /* generation */ 0
  213 };
  214 
  215 PERIPHDRIVER_DECLARE(sdda, sddadriver);
  216 
  217 static MALLOC_DEFINE(M_SDDA, "sd_da", "sd_da buffers");
  218 
  219 static const int exp[8] = {
  220         1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
  221 };
  222 
  223 static const int mant[16] = {
  224         0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
  225 };
  226 
  227 static const int cur_min[8] = {
  228         500, 1000, 5000, 10000, 25000, 35000, 60000, 100000
  229 };
  230 
  231 static const int cur_max[8] = {
  232         1000, 5000, 10000, 25000, 35000, 45000, 800000, 200000
  233 };
  234 
  235 static uint16_t
  236 get_rca(struct cam_periph *periph) {
  237         return periph->path->device->mmc_ident_data.card_rca;
  238 }
  239 
  240 /*
  241  * Figure out if CCB execution resulted in error.
  242  * Look at both CAM-level errors and on MMC protocol errors.
  243  *
  244  * Return value is always MMC error.
  245 */
  246 static int
  247 mmc_handle_reply(union ccb *ccb)
  248 {
  249         KASSERT(ccb->ccb_h.func_code == XPT_MMC_IO,
  250             ("ccb %p: cannot handle non-XPT_MMC_IO errors, got func_code=%d",
  251                 ccb, ccb->ccb_h.func_code));
  252 
  253         /* CAM-level error should always correspond to MMC-level error */
  254         if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) &&
  255           (ccb->mmcio.cmd.error != MMC_ERR_NONE))
  256                 panic("CCB status is OK but MMC error != MMC_ERR_NONE");
  257 
  258         if (ccb->mmcio.cmd.error != MMC_ERR_NONE) {
  259                 xpt_print_path(ccb->ccb_h.path);
  260                 printf("CMD%d failed, err %d (%s)\n",
  261                   ccb->mmcio.cmd.opcode,
  262                   ccb->mmcio.cmd.error,
  263                   mmc_errmsg[ccb->mmcio.cmd.error]);
  264         }
  265         return (ccb->mmcio.cmd.error);
  266 }
  267 
  268 static uint32_t
  269 mmc_get_bits(uint32_t *bits, int bit_len, int start, int size)
  270 {
  271         const int i = (bit_len / 32) - (start / 32) - 1;
  272         const int shift = start & 31;
  273         uint32_t retval = bits[i] >> shift;
  274         if (size + shift > 32)
  275                 retval |= bits[i - 1] << (32 - shift);
  276         return (retval & ((1llu << size) - 1));
  277 }
  278 
  279 static void
  280 mmc_decode_csd_sd(uint32_t *raw_csd, struct mmc_csd *csd)
  281 {
  282         int v;
  283         int m;
  284         int e;
  285 
  286         memset(csd, 0, sizeof(*csd));
  287         csd->csd_structure = v = mmc_get_bits(raw_csd, 128, 126, 2);
  288 
  289         /* Common members between 1.0 and 2.0 */
  290         m = mmc_get_bits(raw_csd, 128, 115, 4);
  291         e = mmc_get_bits(raw_csd, 128, 112, 3);
  292         csd->tacc = (exp[e] * mant[m] + 9) / 10;
  293         csd->nsac = mmc_get_bits(raw_csd, 128, 104, 8) * 100;
  294         m = mmc_get_bits(raw_csd, 128, 99, 4);
  295         e = mmc_get_bits(raw_csd, 128, 96, 3);
  296         csd->tran_speed = exp[e] * 10000 * mant[m];
  297         csd->ccc = mmc_get_bits(raw_csd, 128, 84, 12);
  298         csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 128, 80, 4);
  299         csd->read_bl_partial = mmc_get_bits(raw_csd, 128, 79, 1);
  300         csd->write_blk_misalign = mmc_get_bits(raw_csd, 128, 78, 1);
  301         csd->read_blk_misalign = mmc_get_bits(raw_csd, 128, 77, 1);
  302         csd->dsr_imp = mmc_get_bits(raw_csd, 128, 76, 1);
  303         csd->erase_blk_en = mmc_get_bits(raw_csd, 128, 46, 1);
  304         csd->erase_sector = mmc_get_bits(raw_csd, 128, 39, 7) + 1;
  305         csd->wp_grp_size = mmc_get_bits(raw_csd, 128, 32, 7);
  306         csd->wp_grp_enable = mmc_get_bits(raw_csd, 128, 31, 1);
  307         csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 128, 26, 3);
  308         csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 128, 22, 4);
  309         csd->write_bl_partial = mmc_get_bits(raw_csd, 128, 21, 1);
  310 
  311         if (v == 0) {
  312                 csd->vdd_r_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 59, 3)];
  313                 csd->vdd_r_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 56, 3)];
  314                 csd->vdd_w_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 53, 3)];
  315                 csd->vdd_w_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 50, 3)];
  316                 m = mmc_get_bits(raw_csd, 128, 62, 12);
  317                 e = mmc_get_bits(raw_csd, 128, 47, 3);
  318                 csd->capacity = ((1 + m) << (e + 2)) * csd->read_bl_len;
  319         } else if (v == 1) {
  320                 csd->capacity = ((uint64_t)mmc_get_bits(raw_csd, 128, 48, 22) + 1) *
  321                     512 * 1024;
  322         } else
  323                 panic("unknown SD CSD version");
  324 }
  325 
  326 static void
  327 mmc_decode_csd_mmc(uint32_t *raw_csd, struct mmc_csd *csd)
  328 {
  329         int m;
  330         int e;
  331 
  332         memset(csd, 0, sizeof(*csd));
  333         csd->csd_structure = mmc_get_bits(raw_csd, 128, 126, 2);
  334         csd->spec_vers = mmc_get_bits(raw_csd, 128, 122, 4);
  335         m = mmc_get_bits(raw_csd, 128, 115, 4);
  336         e = mmc_get_bits(raw_csd, 128, 112, 3);
  337         csd->tacc = exp[e] * mant[m] + 9 / 10;
  338         csd->nsac = mmc_get_bits(raw_csd, 128, 104, 8) * 100;
  339         m = mmc_get_bits(raw_csd, 128, 99, 4);
  340         e = mmc_get_bits(raw_csd, 128, 96, 3);
  341         csd->tran_speed = exp[e] * 10000 * mant[m];
  342         csd->ccc = mmc_get_bits(raw_csd, 128, 84, 12);
  343         csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 128, 80, 4);
  344         csd->read_bl_partial = mmc_get_bits(raw_csd, 128, 79, 1);
  345         csd->write_blk_misalign = mmc_get_bits(raw_csd, 128, 78, 1);
  346         csd->read_blk_misalign = mmc_get_bits(raw_csd, 128, 77, 1);
  347         csd->dsr_imp = mmc_get_bits(raw_csd, 128, 76, 1);
  348         csd->vdd_r_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 59, 3)];
  349         csd->vdd_r_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 56, 3)];
  350         csd->vdd_w_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 53, 3)];
  351         csd->vdd_w_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 50, 3)];
  352         m = mmc_get_bits(raw_csd, 128, 62, 12);
  353         e = mmc_get_bits(raw_csd, 128, 47, 3);
  354         csd->capacity = ((1 + m) << (e + 2)) * csd->read_bl_len;
  355         csd->erase_blk_en = 0;
  356         csd->erase_sector = (mmc_get_bits(raw_csd, 128, 42, 5) + 1) *
  357             (mmc_get_bits(raw_csd, 128, 37, 5) + 1);
  358         csd->wp_grp_size = mmc_get_bits(raw_csd, 128, 32, 5);
  359         csd->wp_grp_enable = mmc_get_bits(raw_csd, 128, 31, 1);
  360         csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 128, 26, 3);
  361         csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 128, 22, 4);
  362         csd->write_bl_partial = mmc_get_bits(raw_csd, 128, 21, 1);
  363 }
  364 
  365 static void
  366 mmc_decode_cid_sd(uint32_t *raw_cid, struct mmc_cid *cid)
  367 {
  368         int i;
  369 
  370         /* There's no version info, so we take it on faith */
  371         memset(cid, 0, sizeof(*cid));
  372         cid->mid = mmc_get_bits(raw_cid, 128, 120, 8);
  373         cid->oid = mmc_get_bits(raw_cid, 128, 104, 16);
  374         for (i = 0; i < 5; i++)
  375                 cid->pnm[i] = mmc_get_bits(raw_cid, 128, 96 - i * 8, 8);
  376         cid->pnm[5] = 0;
  377         cid->prv = mmc_get_bits(raw_cid, 128, 56, 8);
  378         cid->psn = mmc_get_bits(raw_cid, 128, 24, 32);
  379         cid->mdt_year = mmc_get_bits(raw_cid, 128, 12, 8) + 2000;
  380         cid->mdt_month = mmc_get_bits(raw_cid, 128, 8, 4);
  381 }
  382 
  383 static void
  384 mmc_decode_cid_mmc(uint32_t *raw_cid, struct mmc_cid *cid)
  385 {
  386         int i;
  387 
  388         /* There's no version info, so we take it on faith */
  389         memset(cid, 0, sizeof(*cid));
  390         cid->mid = mmc_get_bits(raw_cid, 128, 120, 8);
  391         cid->oid = mmc_get_bits(raw_cid, 128, 104, 8);
  392         for (i = 0; i < 6; i++)
  393                 cid->pnm[i] = mmc_get_bits(raw_cid, 128, 96 - i * 8, 8);
  394         cid->pnm[6] = 0;
  395         cid->prv = mmc_get_bits(raw_cid, 128, 48, 8);
  396         cid->psn = mmc_get_bits(raw_cid, 128, 16, 32);
  397         cid->mdt_month = mmc_get_bits(raw_cid, 128, 12, 4);
  398         cid->mdt_year = mmc_get_bits(raw_cid, 128, 8, 4) + 1997;
  399 }
  400 
  401 static void
  402 mmc_format_card_id_string(struct sdda_softc *sc, struct mmc_params *mmcp)
  403 {
  404         char oidstr[8];
  405         uint8_t c1;
  406         uint8_t c2;
  407 
  408         /*
  409          * Format a card ID string for use by the mmcsd driver, it's what
  410          * appears between the <> in the following:
  411          * mmcsd0: 968MB <SD SD01G 8.0 SN 2686905 Mfg 08/2008 by 3 TN> at mmc0
  412          * 22.5MHz/4bit/128-block
  413          *
  414          * Also format just the card serial number, which the mmcsd driver will
  415          * use as the disk->d_ident string.
  416          *
  417          * The card_id_string in mmc_ivars is currently allocated as 64 bytes,
  418          * and our max formatted length is currently 55 bytes if every field
  419          * contains the largest value.
  420          *
  421          * Sometimes the oid is two printable ascii chars; when it's not,
  422          * format it as 0xnnnn instead.
  423          */
  424         c1 = (sc->cid.oid >> 8) & 0x0ff;
  425         c2 = sc->cid.oid & 0x0ff;
  426         if (c1 > 0x1f && c1 < 0x7f && c2 > 0x1f && c2 < 0x7f)
  427                 snprintf(oidstr, sizeof(oidstr), "%c%c", c1, c2);
  428         else
  429                 snprintf(oidstr, sizeof(oidstr), "0x%04x", sc->cid.oid);
  430         snprintf(sc->card_sn_string, sizeof(sc->card_sn_string),
  431             "%08X", sc->cid.psn);
  432         snprintf(sc->card_id_string, sizeof(sc->card_id_string),
  433                  "%s%s %s %d.%d SN %08X MFG %02d/%04d by %d %s",
  434                  mmcp->card_features & CARD_FEATURE_MMC ? "MMC" : "SD",
  435                  mmcp->card_features & CARD_FEATURE_SDHC ? "HC" : "",
  436                  sc->cid.pnm, sc->cid.prv >> 4, sc->cid.prv & 0x0f,
  437                  sc->cid.psn, sc->cid.mdt_month, sc->cid.mdt_year,
  438                  sc->cid.mid, oidstr);
  439 }
  440 
  441 static int
  442 sddaopen(struct disk *dp)
  443 {
  444         struct sdda_part *part;
  445         struct cam_periph *periph;
  446         struct sdda_softc *softc;
  447         int error;
  448 
  449         part = (struct sdda_part *)dp->d_drv1;
  450         softc = part->sc;
  451         periph = softc->periph;
  452         if (cam_periph_acquire(periph) != 0) {
  453                 return(ENXIO);
  454         }
  455 
  456         cam_periph_lock(periph);
  457         if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
  458                 cam_periph_unlock(periph);
  459                 cam_periph_release(periph);
  460                 return (error);
  461         }
  462 
  463         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sddaopen\n"));
  464 
  465         part->flags |= SDDA_FLAG_OPEN;
  466 
  467         cam_periph_unhold(periph);
  468         cam_periph_unlock(periph);
  469         return (0);
  470 }
  471 
  472 static int
  473 sddaclose(struct disk *dp)
  474 {
  475         struct sdda_part *part;
  476         struct  cam_periph *periph;
  477         struct  sdda_softc *softc;
  478 
  479         part = (struct sdda_part *)dp->d_drv1;
  480         softc = part->sc;
  481         periph = softc->periph;
  482         part->flags &= ~SDDA_FLAG_OPEN;
  483 
  484         cam_periph_lock(periph);
  485 
  486         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sddaclose\n"));
  487 
  488         while (softc->refcount != 0)
  489                 cam_periph_sleep(periph, &softc->refcount, PRIBIO, "sddaclose", 1);
  490         cam_periph_unlock(periph);
  491         cam_periph_release(periph);
  492         return (0);
  493 }
  494 
  495 static void
  496 sddaschedule(struct cam_periph *periph)
  497 {
  498         struct sdda_softc *softc = (struct sdda_softc *)periph->softc;
  499         struct sdda_part *part;
  500         struct bio *bp;
  501         int i;
  502 
  503         /* Check if we have more work to do. */
  504         /* Find partition that has outstanding commands. Prefer current partition. */
  505         bp = bioq_first(&softc->part[softc->part_curr]->bio_queue);
  506         if (bp == NULL) {
  507                 for (i = 0; i < MMC_PART_MAX; i++) {
  508                         if ((part = softc->part[i]) != NULL &&
  509                             (bp = bioq_first(&softc->part[i]->bio_queue)) != NULL)
  510                                 break;
  511                 }
  512         }
  513         if (bp != NULL) {
  514                 xpt_schedule(periph, CAM_PRIORITY_NORMAL);
  515         }
  516 }
  517 
  518 /*
  519  * Actually translate the requested transfer into one the physical driver
  520  * can understand.  The transfer is described by a buf and will include
  521  * only one physical transfer.
  522  */
  523 static void
  524 sddastrategy(struct bio *bp)
  525 {
  526         struct cam_periph *periph;
  527         struct sdda_part *part;
  528         struct sdda_softc *softc;
  529 
  530         part = (struct sdda_part *)bp->bio_disk->d_drv1;
  531         softc = part->sc;
  532         periph = softc->periph;
  533 
  534         cam_periph_lock(periph);
  535 
  536         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sddastrategy(%p)\n", bp));
  537 
  538         /*
  539          * If the device has been made invalid, error out
  540          */
  541         if ((periph->flags & CAM_PERIPH_INVALID) != 0) {
  542                 cam_periph_unlock(periph);
  543                 biofinish(bp, NULL, ENXIO);
  544                 return;
  545         }
  546 
  547         /*
  548          * Place it in the queue of disk activities for this disk
  549          */
  550         bioq_disksort(&part->bio_queue, bp);
  551 
  552         /*
  553          * Schedule ourselves for performing the work.
  554          */
  555         sddaschedule(periph);
  556         cam_periph_unlock(periph);
  557 
  558         return;
  559 }
  560 
  561 static void
  562 sddainit(void)
  563 {
  564         cam_status status;
  565 
  566         /*
  567          * Install a global async callback.  This callback will
  568          * receive async callbacks like "new device found".
  569          */
  570         status = xpt_register_async(AC_FOUND_DEVICE, sddaasync, NULL, NULL);
  571 
  572         if (status != CAM_REQ_CMP) {
  573                 printf("sdda: Failed to attach master async callback "
  574                        "due to status 0x%x!\n", status);
  575         }
  576 }
  577 
  578 /*
  579  * Callback from GEOM, called when it has finished cleaning up its
  580  * resources.
  581  */
  582 static void
  583 sddadiskgonecb(struct disk *dp)
  584 {
  585         struct cam_periph *periph;
  586         struct sdda_part *part;
  587 
  588         part = (struct sdda_part *)dp->d_drv1;
  589         periph = part->sc->periph;
  590         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sddadiskgonecb\n"));
  591 
  592         cam_periph_release(periph);
  593 }
  594 
  595 static void
  596 sddaoninvalidate(struct cam_periph *periph)
  597 {
  598         struct sdda_softc *softc;
  599         struct sdda_part *part;
  600 
  601         softc = (struct sdda_softc *)periph->softc;
  602 
  603         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sddaoninvalidate\n"));
  604 
  605         /*
  606          * De-register any async callbacks.
  607          */
  608         xpt_register_async(0, sddaasync, periph, periph->path);
  609 
  610         /*
  611          * Return all queued I/O with ENXIO.
  612          * XXX Handle any transactions queued to the card
  613          *     with XPT_ABORT_CCB.
  614          */
  615         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("bioq_flush start\n"));
  616         for (int i = 0; i < MMC_PART_MAX; i++) {
  617                 if ((part = softc->part[i]) != NULL) {
  618                         bioq_flush(&part->bio_queue, NULL, ENXIO);
  619                         disk_gone(part->disk);
  620                 }
  621         }
  622         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("bioq_flush end\n"));
  623 }
  624 
  625 static void
  626 sddacleanup(struct cam_periph *periph)
  627 {
  628         struct sdda_softc *softc;
  629         struct sdda_part *part;
  630         int i;
  631 
  632         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sddacleanup\n"));
  633         softc = (struct sdda_softc *)periph->softc;
  634 
  635         cam_periph_unlock(periph);
  636 
  637         for (i = 0; i < MMC_PART_MAX; i++) {
  638                 if ((part = softc->part[i]) != NULL) {
  639                         disk_destroy(part->disk);
  640                         free(part, M_DEVBUF);
  641                         softc->part[i] = NULL;
  642                 }
  643         }
  644         free(softc, M_DEVBUF);
  645         cam_periph_lock(periph);
  646 }
  647 
  648 static void
  649 sddaasync(void *callback_arg, u_int32_t code,
  650         struct cam_path *path, void *arg)
  651 {
  652         struct ccb_getdev cgd;
  653         struct cam_periph *periph;
  654 
  655         periph = (struct cam_periph *)callback_arg;
  656         CAM_DEBUG(path, CAM_DEBUG_TRACE, ("sddaasync(code=%d)\n", code));
  657         switch (code) {
  658         case AC_FOUND_DEVICE:
  659         {
  660                 CAM_DEBUG(path, CAM_DEBUG_TRACE, ("=> AC_FOUND_DEVICE\n"));
  661                 struct ccb_getdev *cgd;
  662                 cam_status status;
  663 
  664                 cgd = (struct ccb_getdev *)arg;
  665                 if (cgd == NULL)
  666                         break;
  667 
  668                 if (cgd->protocol != PROTO_MMCSD)
  669                         break;
  670 
  671                 if (!(path->device->mmc_ident_data.card_features & CARD_FEATURE_MEMORY)) {
  672                         CAM_DEBUG(path, CAM_DEBUG_TRACE, ("No memory on the card!\n"));
  673                         break;
  674                 }
  675 
  676                 /*
  677                  * Allocate a peripheral instance for
  678                  * this device and start the probe
  679                  * process.
  680                  */
  681                 status = cam_periph_alloc(sddaregister, sddaoninvalidate,
  682                                           sddacleanup, sddastart,
  683                                           "sdda", CAM_PERIPH_BIO,
  684                                           path, sddaasync,
  685                                           AC_FOUND_DEVICE, cgd);
  686 
  687                 if (status != CAM_REQ_CMP
  688                  && status != CAM_REQ_INPROG)
  689                         printf("sddaasync: Unable to attach to new device "
  690                                 "due to status 0x%x\n", status);
  691                 break;
  692         }
  693         case AC_GETDEV_CHANGED:
  694         {
  695                 CAM_DEBUG(path, CAM_DEBUG_TRACE, ("=> AC_GETDEV_CHANGED\n"));
  696                 memset(&cgd, 0, sizeof(cgd));
  697                 xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
  698                 cgd.ccb_h.func_code = XPT_GDEV_TYPE;
  699                 xpt_action((union ccb *)&cgd);
  700                 cam_periph_async(periph, code, path, arg);
  701                 break;
  702         }
  703         case AC_ADVINFO_CHANGED:
  704         {
  705                 uintptr_t buftype;
  706                 int i;
  707 
  708                 CAM_DEBUG(path, CAM_DEBUG_TRACE, ("=> AC_ADVINFO_CHANGED\n"));
  709                 buftype = (uintptr_t)arg;
  710                 if (buftype == CDAI_TYPE_PHYS_PATH) {
  711                         struct sdda_softc *softc;
  712                         struct sdda_part *part;
  713 
  714                         softc = periph->softc;
  715                         for (i = 0; i < MMC_PART_MAX; i++) {
  716                                 if ((part = softc->part[i]) != NULL) {
  717                                         disk_attr_changed(part->disk, "GEOM::physpath",
  718                                             M_NOWAIT);
  719                                 }
  720                         }
  721                 }
  722                 break;
  723         }
  724         default:
  725                 CAM_DEBUG(path, CAM_DEBUG_TRACE, ("=> default?!\n"));
  726                 cam_periph_async(periph, code, path, arg);
  727                 break;
  728         }
  729 }
  730 
  731 static int
  732 sddagetattr(struct bio *bp)
  733 {
  734         struct cam_periph *periph;
  735         struct sdda_softc *softc;
  736         struct sdda_part *part;
  737         int ret;
  738 
  739         part = (struct sdda_part *)bp->bio_disk->d_drv1;
  740         softc = part->sc;
  741         periph = softc->periph;
  742         cam_periph_lock(periph);
  743         ret = xpt_getattr(bp->bio_data, bp->bio_length, bp->bio_attribute,
  744             periph->path);
  745         cam_periph_unlock(periph);
  746         if (ret == 0)
  747                 bp->bio_completed = bp->bio_length;
  748         return (ret);
  749 }
  750 
  751 static cam_status
  752 sddaregister(struct cam_periph *periph, void *arg)
  753 {
  754         struct sdda_softc *softc;
  755         struct ccb_getdev *cgd;
  756 
  757         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sddaregister\n"));
  758         cgd = (struct ccb_getdev *)arg;
  759         if (cgd == NULL) {
  760                 printf("sddaregister: no getdev CCB, can't register device\n");
  761                 return (CAM_REQ_CMP_ERR);
  762         }
  763 
  764         softc = (struct sdda_softc *)malloc(sizeof(*softc), M_DEVBUF,
  765             M_NOWAIT|M_ZERO);
  766         if (softc == NULL) {
  767                 printf("sddaregister: Unable to probe new device. "
  768                     "Unable to allocate softc\n");
  769                 return (CAM_REQ_CMP_ERR);
  770         }
  771 
  772         softc->state = SDDA_STATE_INIT;
  773         softc->mmcdata =
  774                 (struct mmc_data *)malloc(sizeof(struct mmc_data), M_DEVBUF, M_NOWAIT|M_ZERO);
  775         if (softc->mmcdata == NULL) {
  776                 printf("sddaregister: Unable to probe new device. "
  777                     "Unable to allocate mmcdata\n");
  778                 free(softc, M_DEVBUF);
  779                 return (CAM_REQ_CMP_ERR);
  780         }
  781         periph->softc = softc;
  782         softc->periph = periph;
  783 
  784         xpt_schedule(periph, CAM_PRIORITY_XPT);
  785         TASK_INIT(&softc->start_init_task, 0, sdda_start_init_task, periph);
  786         taskqueue_enqueue(taskqueue_thread, &softc->start_init_task);
  787 
  788         return (CAM_REQ_CMP);
  789 }
  790 
  791 static int
  792 mmc_exec_app_cmd(struct cam_periph *periph, union ccb *ccb,
  793         struct mmc_command *cmd) {
  794         int err;
  795 
  796         /* Send APP_CMD first */
  797         memset(&ccb->mmcio.cmd, 0, sizeof(struct mmc_command));
  798         memset(&ccb->mmcio.stop, 0, sizeof(struct mmc_command));
  799         cam_fill_mmcio(&ccb->mmcio,
  800                        /*retries*/ 0,
  801                        /*cbfcnp*/ NULL,
  802                        /*flags*/ CAM_DIR_NONE,
  803                        /*mmc_opcode*/ MMC_APP_CMD,
  804                        /*mmc_arg*/ get_rca(periph) << 16,
  805                        /*mmc_flags*/ MMC_RSP_R1 | MMC_CMD_AC,
  806                        /*mmc_data*/ NULL,
  807                        /*timeout*/ 0);
  808 
  809         cam_periph_runccb(ccb, sddaerror, CAM_FLAG_NONE, /*sense_flags*/0, NULL);
  810         err = mmc_handle_reply(ccb);
  811         if (err != 0)
  812                 return (err);
  813         if (!(ccb->mmcio.cmd.resp[0] & R1_APP_CMD))
  814                 return (EIO);
  815 
  816         /* Now exec actual command */
  817         int flags = 0;
  818         if (cmd->data != NULL) {
  819                 ccb->mmcio.cmd.data = cmd->data;
  820                 if (cmd->data->flags & MMC_DATA_READ)
  821                         flags |= CAM_DIR_IN;
  822                 if (cmd->data->flags & MMC_DATA_WRITE)
  823                         flags |= CAM_DIR_OUT;
  824         } else flags = CAM_DIR_NONE;
  825 
  826         cam_fill_mmcio(&ccb->mmcio,
  827                        /*retries*/ 0,
  828                        /*cbfcnp*/ NULL,
  829                        /*flags*/ flags,
  830                        /*mmc_opcode*/ cmd->opcode,
  831                        /*mmc_arg*/ cmd->arg,
  832                        /*mmc_flags*/ cmd->flags,
  833                        /*mmc_data*/ cmd->data,
  834                        /*timeout*/ 0);
  835 
  836         cam_periph_runccb(ccb, sddaerror, CAM_FLAG_NONE, /*sense_flags*/0, NULL);
  837         err = mmc_handle_reply(ccb);
  838         if (err != 0)
  839                 return (err);
  840         memcpy(cmd->resp, ccb->mmcio.cmd.resp, sizeof(cmd->resp));
  841         cmd->error = ccb->mmcio.cmd.error;
  842 
  843         return (0);
  844 }
  845 
  846 static int
  847 mmc_app_get_scr(struct cam_periph *periph, union ccb *ccb, uint32_t *rawscr) {
  848         int err;
  849         struct mmc_command cmd;
  850         struct mmc_data d;
  851 
  852         memset(&cmd, 0, sizeof(cmd));
  853         memset(&d, 0, sizeof(d));
  854 
  855         memset(rawscr, 0, 8);
  856         cmd.opcode = ACMD_SEND_SCR;
  857         cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
  858         cmd.arg = 0;
  859 
  860         d.data = rawscr;
  861         d.len = 8;
  862         d.flags = MMC_DATA_READ;
  863         cmd.data = &d;
  864 
  865         err = mmc_exec_app_cmd(periph, ccb, &cmd);
  866         rawscr[0] = be32toh(rawscr[0]);
  867         rawscr[1] = be32toh(rawscr[1]);
  868         return (err);
  869 }
  870 
  871 static int
  872 mmc_send_ext_csd(struct cam_periph *periph, union ccb *ccb,
  873                  uint8_t *rawextcsd, size_t buf_len) {
  874         int err;
  875         struct mmc_data d;
  876 
  877         KASSERT(buf_len == 512, ("Buffer for ext csd must be 512 bytes"));
  878         memset(&d, 0, sizeof(d));
  879         d.data = rawextcsd;
  880         d.len = buf_len;
  881         d.flags = MMC_DATA_READ;
  882         memset(d.data, 0, d.len);
  883 
  884         cam_fill_mmcio(&ccb->mmcio,
  885                        /*retries*/ 0,
  886                        /*cbfcnp*/ NULL,
  887                        /*flags*/ CAM_DIR_IN,
  888                        /*mmc_opcode*/ MMC_SEND_EXT_CSD,
  889                        /*mmc_arg*/ 0,
  890                        /*mmc_flags*/ MMC_RSP_R1 | MMC_CMD_ADTC,
  891                        /*mmc_data*/ &d,
  892                        /*timeout*/ 0);
  893 
  894         cam_periph_runccb(ccb, sddaerror, CAM_FLAG_NONE, /*sense_flags*/0, NULL);
  895         err = mmc_handle_reply(ccb);
  896         return (err);
  897 }
  898 
  899 static void
  900 mmc_app_decode_scr(uint32_t *raw_scr, struct mmc_scr *scr)
  901 {
  902         unsigned int scr_struct;
  903 
  904         memset(scr, 0, sizeof(*scr));
  905 
  906         scr_struct = mmc_get_bits(raw_scr, 64, 60, 4);
  907         if (scr_struct != 0) {
  908                 printf("Unrecognised SCR structure version %d\n",
  909                     scr_struct);
  910                 return;
  911         }
  912         scr->sda_vsn = mmc_get_bits(raw_scr, 64, 56, 4);
  913         scr->bus_widths = mmc_get_bits(raw_scr, 64, 48, 4);
  914 }
  915 
  916 static inline void
  917 mmc_switch_fill_mmcio(union ccb *ccb,
  918     uint8_t set, uint8_t index, uint8_t value, u_int timeout)
  919 {
  920         int arg = (MMC_SWITCH_FUNC_WR << 24) |
  921             (index << 16) |
  922             (value << 8) |
  923             set;
  924 
  925         cam_fill_mmcio(&ccb->mmcio,
  926                        /*retries*/ 0,
  927                        /*cbfcnp*/ NULL,
  928                        /*flags*/ CAM_DIR_NONE,
  929                        /*mmc_opcode*/ MMC_SWITCH_FUNC,
  930                        /*mmc_arg*/ arg,
  931                        /*mmc_flags*/ MMC_RSP_R1B | MMC_CMD_AC,
  932                        /*mmc_data*/ NULL,
  933                        /*timeout*/ timeout);
  934 }
  935 
  936 static int
  937 mmc_select_card(struct cam_periph *periph, union ccb *ccb, uint32_t rca)
  938 {
  939         int flags, err;
  940 
  941         flags = (rca ? MMC_RSP_R1B : MMC_RSP_NONE) | MMC_CMD_AC;
  942         cam_fill_mmcio(&ccb->mmcio,
  943                        /*retries*/ 0,
  944                        /*cbfcnp*/ NULL,
  945                        /*flags*/ CAM_DIR_IN,
  946                        /*mmc_opcode*/ MMC_SELECT_CARD,
  947                        /*mmc_arg*/ rca << 16,
  948                        /*mmc_flags*/ flags,
  949                        /*mmc_data*/ NULL,
  950                        /*timeout*/ 0);
  951 
  952         cam_periph_runccb(ccb, sddaerror, CAM_FLAG_NONE, /*sense_flags*/0, NULL);
  953         err = mmc_handle_reply(ccb);
  954         return (err);
  955 }
  956 
  957 static int
  958 mmc_switch(struct cam_periph *periph, union ccb *ccb,
  959     uint8_t set, uint8_t index, uint8_t value, u_int timeout)
  960 {
  961         int err;
  962 
  963         mmc_switch_fill_mmcio(ccb, set, index, value, timeout);
  964         cam_periph_runccb(ccb, sddaerror, CAM_FLAG_NONE, /*sense_flags*/0, NULL);
  965         err = mmc_handle_reply(ccb);
  966         return (err);
  967 }
  968 
  969 static uint32_t
  970 mmc_get_spec_vers(struct cam_periph *periph) {
  971         struct sdda_softc *softc = (struct sdda_softc *)periph->softc;
  972 
  973         return (softc->csd.spec_vers);
  974 }
  975 
  976 static uint64_t
  977 mmc_get_media_size(struct cam_periph *periph) {
  978         struct sdda_softc *softc = (struct sdda_softc *)periph->softc;
  979 
  980         return (softc->mediasize);
  981 }
  982 
  983 static uint32_t
  984 mmc_get_cmd6_timeout(struct cam_periph *periph)
  985 {
  986         struct sdda_softc *softc = (struct sdda_softc *)periph->softc;
  987 
  988         if (mmc_get_spec_vers(periph) >= 6)
  989                 return (softc->raw_ext_csd[EXT_CSD_GEN_CMD6_TIME] * 10);
  990         return (500 * 1000);
  991 }
  992 
  993 static int
  994 mmc_sd_switch(struct cam_periph *periph, union ccb *ccb,
  995               uint8_t mode, uint8_t grp, uint8_t value,
  996               uint8_t *res) {
  997         struct mmc_data mmc_d;
  998         uint32_t arg;
  999         int err;
 1000 
 1001         memset(res, 0, 64);
 1002         memset(&mmc_d, 0, sizeof(mmc_d));
 1003         mmc_d.len = 64;
 1004         mmc_d.data = res;
 1005         mmc_d.flags = MMC_DATA_READ;
 1006 
 1007         arg = mode << 31;                       /* 0 - check, 1 - set */
 1008         arg |= 0x00FFFFFF;
 1009         arg &= ~(0xF << (grp * 4));
 1010         arg |= value << (grp * 4);
 1011 
 1012         cam_fill_mmcio(&ccb->mmcio,
 1013                        /*retries*/ 0,
 1014                        /*cbfcnp*/ NULL,
 1015                        /*flags*/ CAM_DIR_IN,
 1016                        /*mmc_opcode*/ SD_SWITCH_FUNC,
 1017                        /*mmc_arg*/ arg,
 1018                        /*mmc_flags*/ MMC_RSP_R1 | MMC_CMD_ADTC,
 1019                        /*mmc_data*/ &mmc_d,
 1020                        /*timeout*/ 0);
 1021 
 1022         cam_periph_runccb(ccb, sddaerror, CAM_FLAG_NONE, /*sense_flags*/0, NULL);
 1023         err = mmc_handle_reply(ccb);
 1024         return (err);
 1025 }
 1026 
 1027 static int
 1028 mmc_set_timing(struct cam_periph *periph,
 1029                union ccb *ccb,
 1030                enum mmc_bus_timing timing)
 1031 {
 1032         u_char switch_res[64];
 1033         int err;
 1034         uint8_t value;
 1035         struct sdda_softc *softc = (struct sdda_softc *)periph->softc;
 1036         struct mmc_params *mmcp = &periph->path->device->mmc_ident_data;
 1037 
 1038         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
 1039                   ("mmc_set_timing(timing=%d)", timing));
 1040         switch (timing) {
 1041         case bus_timing_normal:
 1042                 value = 0;
 1043                 break;
 1044         case bus_timing_hs:
 1045                 value = 1;
 1046                 break;
 1047         default:
 1048                 return (MMC_ERR_INVALID);
 1049         }
 1050         if (mmcp->card_features & CARD_FEATURE_MMC) {
 1051                 err = mmc_switch(periph, ccb, EXT_CSD_CMD_SET_NORMAL,
 1052                     EXT_CSD_HS_TIMING, value, softc->cmd6_time);
 1053         } else {
 1054                 err = mmc_sd_switch(periph, ccb, SD_SWITCH_MODE_SET, SD_SWITCH_GROUP1, value, switch_res);
 1055         }
 1056 
 1057         /* Set high-speed timing on the host */
 1058         struct ccb_trans_settings_mmc *cts;
 1059         cts = &ccb->cts.proto_specific.mmc;
 1060         ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
 1061         ccb->ccb_h.flags = CAM_DIR_NONE;
 1062         ccb->ccb_h.retry_count = 0;
 1063         ccb->ccb_h.timeout = 100;
 1064         ccb->ccb_h.cbfcnp = NULL;
 1065         cts->ios.timing = timing;
 1066         cts->ios_valid = MMC_BT;
 1067         xpt_action(ccb);
 1068 
 1069         return (err);
 1070 }
 1071 
 1072 static void
 1073 sdda_start_init_task(void *context, int pending) {
 1074         union ccb *new_ccb;
 1075         struct cam_periph *periph;
 1076 
 1077         periph = (struct cam_periph *)context;
 1078         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sdda_start_init_task\n"));
 1079         new_ccb = xpt_alloc_ccb();
 1080         xpt_setup_ccb(&new_ccb->ccb_h, periph->path,
 1081                       CAM_PRIORITY_NONE);
 1082 
 1083         cam_periph_lock(periph);
 1084         cam_periph_hold(periph, PRIBIO|PCATCH);
 1085         sdda_start_init(context, new_ccb);
 1086         cam_periph_unhold(periph);
 1087         cam_periph_unlock(periph);
 1088         xpt_free_ccb(new_ccb);
 1089 }
 1090 
 1091 static void
 1092 sdda_set_bus_width(struct cam_periph *periph, union ccb *ccb, int width) {
 1093         struct sdda_softc *softc = (struct sdda_softc *)periph->softc;
 1094         struct mmc_params *mmcp = &periph->path->device->mmc_ident_data;
 1095         int err;
 1096 
 1097         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sdda_set_bus_width\n"));
 1098 
 1099         /* First set for the card, then for the host */
 1100         if (mmcp->card_features & CARD_FEATURE_MMC) {
 1101                 uint8_t value;
 1102                 switch (width) {
 1103                 case bus_width_1:
 1104                         value = EXT_CSD_BUS_WIDTH_1;
 1105                         break;
 1106                 case bus_width_4:
 1107                         value = EXT_CSD_BUS_WIDTH_4;
 1108                         break;
 1109                 case bus_width_8:
 1110                         value = EXT_CSD_BUS_WIDTH_8;
 1111                         break;
 1112                 default:
 1113                         panic("Invalid bus width %d", width);
 1114                 }
 1115                 err = mmc_switch(periph, ccb, EXT_CSD_CMD_SET_NORMAL,
 1116                     EXT_CSD_BUS_WIDTH, value, softc->cmd6_time);
 1117         } else {
 1118                 /* For SD cards we send ACMD6 with the required bus width in arg */
 1119                 struct mmc_command cmd;
 1120                 memset(&cmd, 0, sizeof(struct mmc_command));
 1121                 cmd.opcode = ACMD_SET_BUS_WIDTH;
 1122                 cmd.arg = width;
 1123                 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 1124                 err = mmc_exec_app_cmd(periph, ccb, &cmd);
 1125         }
 1126 
 1127         if (err != MMC_ERR_NONE) {
 1128                 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Error %d when setting bus width on the card\n", err));
 1129                 return;
 1130         }
 1131         /* Now card is done, set the host to the same width */
 1132         struct ccb_trans_settings_mmc *cts;
 1133         cts = &ccb->cts.proto_specific.mmc;
 1134         ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
 1135         ccb->ccb_h.flags = CAM_DIR_NONE;
 1136         ccb->ccb_h.retry_count = 0;
 1137         ccb->ccb_h.timeout = 100;
 1138         ccb->ccb_h.cbfcnp = NULL;
 1139         cts->ios.bus_width = width;
 1140         cts->ios_valid = MMC_BW;
 1141         xpt_action(ccb);
 1142 }
 1143 
 1144 static inline const char
 1145 *part_type(u_int type)
 1146 {
 1147 
 1148         switch (type) {
 1149         case EXT_CSD_PART_CONFIG_ACC_RPMB:
 1150                 return ("RPMB");
 1151         case EXT_CSD_PART_CONFIG_ACC_DEFAULT:
 1152                 return ("default");
 1153         case EXT_CSD_PART_CONFIG_ACC_BOOT0:
 1154                 return ("boot0");
 1155         case EXT_CSD_PART_CONFIG_ACC_BOOT1:
 1156                 return ("boot1");
 1157         case EXT_CSD_PART_CONFIG_ACC_GP0:
 1158         case EXT_CSD_PART_CONFIG_ACC_GP1:
 1159         case EXT_CSD_PART_CONFIG_ACC_GP2:
 1160         case EXT_CSD_PART_CONFIG_ACC_GP3:
 1161                 return ("general purpose");
 1162         default:
 1163                 return ("(unknown type)");
 1164         }
 1165 }
 1166 
 1167 static inline const char
 1168 *bus_width_str(enum mmc_bus_width w)
 1169 {
 1170 
 1171         switch (w) {
 1172         case bus_width_1:
 1173                 return ("1-bit");
 1174         case bus_width_4:
 1175                 return ("4-bit");
 1176         case bus_width_8:
 1177                 return ("8-bit");
 1178         default:
 1179                 __assert_unreachable();
 1180         }
 1181 }
 1182 
 1183 static uint32_t
 1184 sdda_get_host_caps(struct cam_periph *periph, union ccb *ccb)
 1185 {
 1186         struct ccb_trans_settings_mmc *cts;
 1187 
 1188         cts = &ccb->cts.proto_specific.mmc;
 1189 
 1190         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
 1191         ccb->ccb_h.flags = CAM_DIR_NONE;
 1192         ccb->ccb_h.retry_count = 0;
 1193         ccb->ccb_h.timeout = 100;
 1194         ccb->ccb_h.cbfcnp = NULL;
 1195         xpt_action(ccb);
 1196 
 1197         if (ccb->ccb_h.status != CAM_REQ_CMP)
 1198                 panic("Cannot get host caps");
 1199         return (cts->host_caps);
 1200 }
 1201 
 1202 static uint32_t
 1203 sdda_get_max_data(struct cam_periph *periph, union ccb *ccb)
 1204 {
 1205         struct ccb_trans_settings_mmc *cts;
 1206 
 1207         cts = &ccb->cts.proto_specific.mmc;
 1208         memset(cts, 0, sizeof(struct ccb_trans_settings_mmc));
 1209 
 1210         ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
 1211         ccb->ccb_h.flags = CAM_DIR_NONE;
 1212         ccb->ccb_h.retry_count = 0;
 1213         ccb->ccb_h.timeout = 100;
 1214         ccb->ccb_h.cbfcnp = NULL;
 1215         xpt_action(ccb);
 1216 
 1217         if (ccb->ccb_h.status != CAM_REQ_CMP)
 1218                 panic("Cannot get host max data");
 1219         KASSERT(cts->host_max_data != 0, ("host_max_data == 0?!"));
 1220         return (cts->host_max_data);
 1221 }
 1222 
 1223 static void
 1224 sdda_start_init(void *context, union ccb *start_ccb)
 1225 {
 1226         struct cam_periph *periph = (struct cam_periph *)context;
 1227         struct ccb_trans_settings_mmc *cts;
 1228         uint32_t host_caps;
 1229         uint32_t sec_count;
 1230         int err;
 1231         int host_f_max;
 1232         uint8_t card_type;
 1233 
 1234         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sdda_start_init\n"));
 1235         /* periph was held for us when this task was enqueued */
 1236         if ((periph->flags & CAM_PERIPH_INVALID) != 0) {
 1237                 cam_periph_release(periph);
 1238                 return;
 1239         }
 1240 
 1241         struct sdda_softc *softc = (struct sdda_softc *)periph->softc;
 1242         struct mmc_params *mmcp = &periph->path->device->mmc_ident_data;
 1243         struct cam_ed *device = periph->path->device;
 1244 
 1245         if (mmcp->card_features & CARD_FEATURE_MMC) {
 1246                 mmc_decode_csd_mmc(mmcp->card_csd, &softc->csd);
 1247                 mmc_decode_cid_mmc(mmcp->card_cid, &softc->cid);
 1248                 if (mmc_get_spec_vers(periph) >= 4) {
 1249                         err = mmc_send_ext_csd(periph, start_ccb,
 1250                                                (uint8_t *)&softc->raw_ext_csd,
 1251                                                sizeof(softc->raw_ext_csd));
 1252                         if (err != 0) {
 1253                                 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH,
 1254                                     ("Cannot read EXT_CSD, err %d", err));
 1255                                 return;
 1256                         }
 1257                 }
 1258         } else {
 1259                 mmc_decode_csd_sd(mmcp->card_csd, &softc->csd);
 1260                 mmc_decode_cid_sd(mmcp->card_cid, &softc->cid);
 1261         }
 1262 
 1263         softc->sector_count = softc->csd.capacity / MMC_SECTOR_SIZE;
 1264         softc->mediasize = softc->csd.capacity;
 1265         softc->cmd6_time = mmc_get_cmd6_timeout(periph);
 1266 
 1267         /* MMC >= 4.x have EXT_CSD that has its own opinion about capacity */
 1268         if (mmc_get_spec_vers(periph) >= 4) {
 1269                 sec_count = softc->raw_ext_csd[EXT_CSD_SEC_CNT] +
 1270                     (softc->raw_ext_csd[EXT_CSD_SEC_CNT + 1] << 8) +
 1271                     (softc->raw_ext_csd[EXT_CSD_SEC_CNT + 2] << 16) +
 1272                     (softc->raw_ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
 1273                 if (sec_count != 0) {
 1274                         softc->sector_count = sec_count;
 1275                         softc->mediasize = softc->sector_count * MMC_SECTOR_SIZE;
 1276                         /* FIXME: there should be a better name for this option...*/
 1277                         mmcp->card_features |= CARD_FEATURE_SDHC;
 1278                 }
 1279         }
 1280         CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH,
 1281             ("Capacity: %"PRIu64", sectors: %"PRIu64"\n",
 1282                 softc->mediasize,
 1283                 softc->sector_count));
 1284         mmc_format_card_id_string(softc, mmcp);
 1285 
 1286         /* Update info for CAM */
 1287         device->serial_num_len = strlen(softc->card_sn_string);
 1288         device->serial_num = (u_int8_t *)malloc((device->serial_num_len + 1),
 1289             M_CAMXPT, M_NOWAIT);
 1290         strlcpy(device->serial_num, softc->card_sn_string, device->serial_num_len + 1);
 1291 
 1292         device->device_id_len = strlen(softc->card_id_string);
 1293         device->device_id = (u_int8_t *)malloc((device->device_id_len + 1),
 1294             M_CAMXPT, M_NOWAIT);
 1295         strlcpy(device->device_id, softc->card_id_string, device->device_id_len + 1);
 1296 
 1297         strlcpy(mmcp->model, softc->card_id_string, sizeof(mmcp->model));
 1298 
 1299         /* Set the clock frequency that the card can handle */
 1300         cts = &start_ccb->cts.proto_specific.mmc;
 1301 
 1302         /* First, get the host's max freq */
 1303         start_ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
 1304         start_ccb->ccb_h.flags = CAM_DIR_NONE;
 1305         start_ccb->ccb_h.retry_count = 0;
 1306         start_ccb->ccb_h.timeout = 100;
 1307         start_ccb->ccb_h.cbfcnp = NULL;
 1308         xpt_action(start_ccb);
 1309 
 1310         if (start_ccb->ccb_h.status != CAM_REQ_CMP)
 1311                 panic("Cannot get max host freq");
 1312         host_f_max = cts->host_f_max;
 1313         host_caps = cts->host_caps;
 1314         if (cts->ios.bus_width != bus_width_1)
 1315                 panic("Bus width in ios is not 1-bit");
 1316 
 1317         /* Now check if the card supports High-speed */
 1318         softc->card_f_max = softc->csd.tran_speed;
 1319 
 1320         if (host_caps & MMC_CAP_HSPEED) {
 1321                 /* Find out if the card supports High speed timing */
 1322                 if (mmcp->card_features & CARD_FEATURE_SD20) {
 1323                         /* Get and decode SCR */
 1324                         uint32_t rawscr[2];
 1325                         uint8_t res[64];
 1326                         if (mmc_app_get_scr(periph, start_ccb, rawscr)) {
 1327                                 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Cannot get SCR\n"));
 1328                                 goto finish_hs_tests;
 1329                         }
 1330                         mmc_app_decode_scr(rawscr, &softc->scr);
 1331 
 1332                         if ((softc->scr.sda_vsn >= 1) && (softc->csd.ccc & (1<<10))) {
 1333                                 mmc_sd_switch(periph, start_ccb, SD_SWITCH_MODE_CHECK,
 1334                                               SD_SWITCH_GROUP1, SD_SWITCH_NOCHANGE, res);
 1335                                 if (res[13] & 2) {
 1336                                         CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Card supports HS\n"));
 1337                                         softc->card_f_max = SD_HS_MAX;
 1338                                 }
 1339 
 1340                                 /*
 1341                                  * We deselect then reselect the card here.  Some cards
 1342                                  * become unselected and timeout with the above two
 1343                                  * commands, although the state tables / diagrams in the
 1344                                  * standard suggest they go back to the transfer state.
 1345                                  * Other cards don't become deselected, and if we
 1346                                  * attempt to blindly re-select them, we get timeout
 1347                                  * errors from some controllers.  So we deselect then
 1348                                  * reselect to handle all situations.
 1349                                  */
 1350                                 mmc_select_card(periph, start_ccb, 0);
 1351                                 mmc_select_card(periph, start_ccb, get_rca(periph));
 1352                         } else {
 1353                                 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Not trying the switch\n"));
 1354                                 goto finish_hs_tests;
 1355                         }
 1356                 }
 1357 
 1358                 if (mmcp->card_features & CARD_FEATURE_MMC && mmc_get_spec_vers(periph) >= 4) {
 1359                         card_type = softc->raw_ext_csd[EXT_CSD_CARD_TYPE];
 1360                         if (card_type & EXT_CSD_CARD_TYPE_HS_52)
 1361                                 softc->card_f_max = MMC_TYPE_HS_52_MAX;
 1362                         else if (card_type & EXT_CSD_CARD_TYPE_HS_26)
 1363                                 softc->card_f_max = MMC_TYPE_HS_26_MAX;
 1364                         if ((card_type & EXT_CSD_CARD_TYPE_DDR_52_1_2V) != 0 &&
 1365                             (host_caps & MMC_CAP_SIGNALING_120) != 0) {
 1366                                 setbit(&softc->timings, bus_timing_mmc_ddr52);
 1367                                 setbit(&softc->vccq_120, bus_timing_mmc_ddr52);
 1368                                 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Card supports DDR52 at 1.2V\n"));
 1369                         }
 1370                         if ((card_type & EXT_CSD_CARD_TYPE_DDR_52_1_8V) != 0 &&
 1371                             (host_caps & MMC_CAP_SIGNALING_180) != 0) {
 1372                                 setbit(&softc->timings, bus_timing_mmc_ddr52);
 1373                                 setbit(&softc->vccq_180, bus_timing_mmc_ddr52);
 1374                                 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Card supports DDR52 at 1.8V\n"));
 1375                         }
 1376                         if ((card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) != 0 &&
 1377                             (host_caps & MMC_CAP_SIGNALING_120) != 0) {
 1378                                 setbit(&softc->timings, bus_timing_mmc_hs200);
 1379                                 setbit(&softc->vccq_120, bus_timing_mmc_hs200);
 1380                                 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Card supports HS200 at 1.2V\n"));
 1381                         }
 1382                         if ((card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) != 0 &&
 1383                             (host_caps & MMC_CAP_SIGNALING_180) != 0) {
 1384                                 setbit(&softc->timings, bus_timing_mmc_hs200);
 1385                                 setbit(&softc->vccq_180, bus_timing_mmc_hs200);
 1386                                 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Card supports HS200 at 1.8V\n"));
 1387                         }
 1388                 }
 1389         }
 1390         int f_max;
 1391 finish_hs_tests:
 1392         f_max = min(host_f_max, softc->card_f_max);
 1393         CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Set SD freq to %d MHz (min out of host f=%d MHz and card f=%d MHz)\n", f_max  / 1000000, host_f_max / 1000000, softc->card_f_max / 1000000));
 1394 
 1395         /* Enable high-speed timing on the card */
 1396         if (f_max > 25000000) {
 1397                 err = mmc_set_timing(periph, start_ccb, bus_timing_hs);
 1398                 if (err != MMC_ERR_NONE) {
 1399                         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("Cannot switch card to high-speed mode"));
 1400                         f_max = 25000000;
 1401                 }
 1402         }
 1403         /* If possible, set lower-level signaling */
 1404         enum mmc_bus_timing timing;
 1405         /* FIXME: MMCCAM supports max. bus_timing_mmc_ddr52 at the moment. */
 1406         for (timing = bus_timing_mmc_ddr52; timing > bus_timing_normal; timing--) {
 1407                 if (isset(&softc->vccq_120, timing)) {
 1408                         /* Set VCCQ = 1.2V */
 1409                         start_ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
 1410                         start_ccb->ccb_h.flags = CAM_DIR_NONE;
 1411                         start_ccb->ccb_h.retry_count = 0;
 1412                         start_ccb->ccb_h.timeout = 100;
 1413                         start_ccb->ccb_h.cbfcnp = NULL;
 1414                         cts->ios.vccq = vccq_120;
 1415                         cts->ios_valid = MMC_VCCQ;
 1416                         xpt_action(start_ccb);
 1417                         break;
 1418                 } else if (isset(&softc->vccq_180, timing)) {
 1419                         /* Set VCCQ = 1.8V */
 1420                         start_ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
 1421                         start_ccb->ccb_h.flags = CAM_DIR_NONE;
 1422                         start_ccb->ccb_h.retry_count = 0;
 1423                         start_ccb->ccb_h.timeout = 100;
 1424                         start_ccb->ccb_h.cbfcnp = NULL;
 1425                         cts->ios.vccq = vccq_180;
 1426                         cts->ios_valid = MMC_VCCQ;
 1427                         xpt_action(start_ccb);
 1428                         break;
 1429                 } else {
 1430                         /* Set VCCQ = 3.3V */
 1431                         start_ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
 1432                         start_ccb->ccb_h.flags = CAM_DIR_NONE;
 1433                         start_ccb->ccb_h.retry_count = 0;
 1434                         start_ccb->ccb_h.timeout = 100;
 1435                         start_ccb->ccb_h.cbfcnp = NULL;
 1436                         cts->ios.vccq = vccq_330;
 1437                         cts->ios_valid = MMC_VCCQ;
 1438                         xpt_action(start_ccb);
 1439                         break;
 1440                 }
 1441         }
 1442 
 1443         /* Set frequency on the controller */
 1444         start_ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
 1445         start_ccb->ccb_h.flags = CAM_DIR_NONE;
 1446         start_ccb->ccb_h.retry_count = 0;
 1447         start_ccb->ccb_h.timeout = 100;
 1448         start_ccb->ccb_h.cbfcnp = NULL;
 1449         cts->ios.clock = f_max;
 1450         cts->ios_valid = MMC_CLK;
 1451         xpt_action(start_ccb);
 1452 
 1453         /* Set bus width */
 1454         enum mmc_bus_width desired_bus_width = bus_width_1;
 1455         enum mmc_bus_width max_host_bus_width =
 1456                 (host_caps & MMC_CAP_8_BIT_DATA ? bus_width_8 :
 1457                  host_caps & MMC_CAP_4_BIT_DATA ? bus_width_4 : bus_width_1);
 1458         enum mmc_bus_width max_card_bus_width = bus_width_1;
 1459         if (mmcp->card_features & CARD_FEATURE_SD20 &&
 1460             softc->scr.bus_widths & SD_SCR_BUS_WIDTH_4)
 1461                 max_card_bus_width = bus_width_4;
 1462         /*
 1463          * Unlike SD, MMC cards don't have any information about supported bus width...
 1464          * So we need to perform read/write test to find out the width.
 1465          */
 1466         /* TODO: figure out bus width for MMC; use 8-bit for now (to test on BBB) */
 1467         if (mmcp->card_features & CARD_FEATURE_MMC)
 1468                 max_card_bus_width = bus_width_8;
 1469 
 1470         desired_bus_width = min(max_host_bus_width, max_card_bus_width);
 1471         CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH,
 1472                   ("Set bus width to %s (min of host %s and card %s)\n",
 1473                    bus_width_str(desired_bus_width),
 1474                    bus_width_str(max_host_bus_width),
 1475                    bus_width_str(max_card_bus_width)));
 1476         sdda_set_bus_width(periph, start_ccb, desired_bus_width);
 1477 
 1478         softc->state = SDDA_STATE_NORMAL;
 1479 
 1480         cam_periph_unhold(periph);
 1481         /* MMC partitions support */
 1482         if (mmcp->card_features & CARD_FEATURE_MMC && mmc_get_spec_vers(periph) >= 4) {
 1483                 sdda_process_mmc_partitions(periph, start_ccb);
 1484         } else if (mmcp->card_features & CARD_FEATURE_MEMORY) {
 1485                 /* For SD[HC] cards, just add one partition that is the whole card */
 1486                 if (sdda_add_part(periph, 0, "sdda",
 1487                     periph->unit_number,
 1488                     mmc_get_media_size(periph),
 1489                     sdda_get_read_only(periph, start_ccb)) == false)
 1490                         return;
 1491                 softc->part_curr = 0;
 1492         }
 1493         cam_periph_hold(periph, PRIBIO|PCATCH);
 1494 
 1495         xpt_announce_periph(periph, softc->card_id_string);
 1496         /*
 1497          * Add async callbacks for bus reset and bus device reset calls.
 1498          * I don't bother checking if this fails as, in most cases,
 1499          * the system will function just fine without them and the only
 1500          * alternative would be to not attach the device on failure.
 1501          */
 1502         xpt_register_async(AC_LOST_DEVICE | AC_GETDEV_CHANGED |
 1503             AC_ADVINFO_CHANGED, sddaasync, periph, periph->path);
 1504 }
 1505 
 1506 static bool
 1507 sdda_add_part(struct cam_periph *periph, u_int type, const char *name,
 1508     u_int cnt, off_t media_size, bool ro)
 1509 {
 1510         struct sdda_softc *sc = (struct sdda_softc *)periph->softc;
 1511         struct sdda_part *part;
 1512         struct ccb_pathinq cpi;
 1513 
 1514         CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH,
 1515             ("Partition type '%s', size %ju %s\n",
 1516             part_type(type),
 1517             media_size,
 1518             ro ? "(read-only)" : ""));
 1519 
 1520         part = sc->part[type] = malloc(sizeof(*part), M_DEVBUF,
 1521             M_NOWAIT | M_ZERO);
 1522         if (part == NULL) {
 1523                 printf("Cannot add partition for sdda\n");
 1524                 return (false);
 1525         }
 1526 
 1527         part->cnt = cnt;
 1528         part->type = type;
 1529         part->ro = ro;
 1530         part->sc = sc;
 1531         snprintf(part->name, sizeof(part->name), name, periph->unit_number);
 1532 
 1533         /*
 1534          * Due to the nature of RPMB partition it doesn't make much sense
 1535          * to add it as a disk. It would be more appropriate to create a
 1536          * userland tool to operate on the partition or leverage the existing
 1537          * tools from sysutils/mmc-utils.
 1538          */
 1539         if (type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
 1540                 /* TODO: Create device, assign IOCTL handler */
 1541                 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH,
 1542                     ("Don't know what to do with RPMB partitions yet\n"));
 1543                 return (false);
 1544         }
 1545 
 1546         bioq_init(&part->bio_queue);
 1547 
 1548         bzero(&cpi, sizeof(cpi));
 1549         xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NONE);
 1550         cpi.ccb_h.func_code = XPT_PATH_INQ;
 1551         xpt_action((union ccb *)&cpi);
 1552 
 1553         /*
 1554          * Register this media as a disk
 1555          */
 1556         (void)cam_periph_hold(periph, PRIBIO);
 1557         cam_periph_unlock(periph);
 1558 
 1559         part->disk = disk_alloc();
 1560         part->disk->d_rotation_rate = DISK_RR_NON_ROTATING;
 1561         part->disk->d_devstat = devstat_new_entry(part->name,
 1562             cnt, MMC_SECTOR_SIZE,
 1563             DEVSTAT_ALL_SUPPORTED,
 1564             DEVSTAT_TYPE_DIRECT | XPORT_DEVSTAT_TYPE(cpi.transport),
 1565             DEVSTAT_PRIORITY_DISK);
 1566 
 1567         part->disk->d_open = sddaopen;
 1568         part->disk->d_close = sddaclose;
 1569         part->disk->d_strategy = sddastrategy;
 1570         if (cam_sim_pollable(periph->sim))
 1571                 part->disk->d_dump = sddadump;
 1572         part->disk->d_getattr = sddagetattr;
 1573         part->disk->d_gone = sddadiskgonecb;
 1574         part->disk->d_name = part->name;
 1575         part->disk->d_drv1 = part;
 1576         part->disk->d_maxsize =
 1577             MIN(maxphys, sdda_get_max_data(periph,
 1578                     (union ccb *)&cpi) * mmc_get_sector_size(periph));
 1579         part->disk->d_unit = cnt;
 1580         part->disk->d_flags = 0;
 1581         strlcpy(part->disk->d_descr, sc->card_id_string,
 1582             MIN(sizeof(part->disk->d_descr), sizeof(sc->card_id_string)));
 1583         strlcpy(part->disk->d_ident, sc->card_sn_string,
 1584             MIN(sizeof(part->disk->d_ident), sizeof(sc->card_sn_string)));
 1585         part->disk->d_hba_vendor = cpi.hba_vendor;
 1586         part->disk->d_hba_device = cpi.hba_device;
 1587         part->disk->d_hba_subvendor = cpi.hba_subvendor;
 1588         part->disk->d_hba_subdevice = cpi.hba_subdevice;
 1589         snprintf(part->disk->d_attachment, sizeof(part->disk->d_attachment),
 1590             "%s%d", cpi.dev_name, cpi.unit_number);
 1591 
 1592         part->disk->d_sectorsize = mmc_get_sector_size(periph);
 1593         part->disk->d_mediasize = media_size;
 1594         part->disk->d_stripesize = 0;
 1595         part->disk->d_fwsectors = 0;
 1596         part->disk->d_fwheads = 0;
 1597 
 1598         if (sdda_mmcsd_compat)
 1599                 disk_add_alias(part->disk, "mmcsd");
 1600 
 1601         /*
 1602          * Acquire a reference to the periph before we register with GEOM.
 1603          * We'll release this reference once GEOM calls us back (via
 1604          * sddadiskgonecb()) telling us that our provider has been freed.
 1605          */
 1606         if (cam_periph_acquire(periph) != 0) {
 1607                 xpt_print(periph->path, "%s: lost periph during "
 1608                     "registration!\n", __func__);
 1609                 cam_periph_lock(periph);
 1610                 return (false);
 1611         }
 1612         disk_create(part->disk, DISK_VERSION);
 1613         cam_periph_lock(periph);
 1614         cam_periph_unhold(periph);
 1615 
 1616         return (true);
 1617 }
 1618 
 1619 /*
 1620  * For MMC cards, process EXT_CSD and add partitions that are supported by
 1621  * this device.
 1622  */
 1623 static void
 1624 sdda_process_mmc_partitions(struct cam_periph *periph, union ccb *ccb)
 1625 {
 1626         struct sdda_softc *sc = (struct sdda_softc *)periph->softc;
 1627         struct mmc_params *mmcp = &periph->path->device->mmc_ident_data;
 1628         off_t erase_size, sector_size, size, wp_size;
 1629         int i;
 1630         const uint8_t *ext_csd;
 1631         uint8_t rev;
 1632         bool comp, ro;
 1633 
 1634         ext_csd = sc->raw_ext_csd;
 1635 
 1636         /*
 1637          * Enhanced user data area and general purpose partitions are only
 1638          * supported in revision 1.4 (EXT_CSD_REV == 4) and later, the RPMB
 1639          * partition in revision 1.5 (MMC v4.41, EXT_CSD_REV == 5) and later.
 1640          */
 1641         rev = ext_csd[EXT_CSD_REV];
 1642 
 1643         /*
 1644          * Ignore user-creatable enhanced user data area and general purpose
 1645          * partitions partitions as long as partitioning hasn't been finished.
 1646          */
 1647         comp = (ext_csd[EXT_CSD_PART_SET] & EXT_CSD_PART_SET_COMPLETED) != 0;
 1648 
 1649         /*
 1650          * Add enhanced user data area slice, unless it spans the entirety of
 1651          * the user data area.  The enhanced area is of a multiple of high
 1652          * capacity write protect groups ((ERASE_GRP_SIZE + HC_WP_GRP_SIZE) *
 1653          * 512 KB) and its offset given in either sectors or bytes, depending
 1654          * on whether it's a high capacity device or not.
 1655          * NB: The slicer and its slices need to be registered before adding
 1656          *     the disk for the corresponding user data area as re-tasting is
 1657          *     racy.
 1658          */
 1659         sector_size = mmc_get_sector_size(periph);
 1660         size = ext_csd[EXT_CSD_ENH_SIZE_MULT] +
 1661                 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 1] << 8) +
 1662                 (ext_csd[EXT_CSD_ENH_SIZE_MULT + 2] << 16);
 1663         if (rev >= 4 && comp == TRUE && size > 0 &&
 1664             (ext_csd[EXT_CSD_PART_SUPPORT] &
 1665                 EXT_CSD_PART_SUPPORT_ENH_ATTR_EN) != 0 &&
 1666             (ext_csd[EXT_CSD_PART_ATTR] & (EXT_CSD_PART_ATTR_ENH_USR)) != 0) {
 1667                 erase_size = ext_csd[EXT_CSD_ERASE_GRP_SIZE] * 1024 *
 1668                         MMC_SECTOR_SIZE;
 1669                 wp_size = ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
 1670                 size *= erase_size * wp_size;
 1671                 if (size != mmc_get_media_size(periph) * sector_size) {
 1672                         sc->enh_size = size;
 1673                         sc->enh_base = (ext_csd[EXT_CSD_ENH_START_ADDR] +
 1674                             (ext_csd[EXT_CSD_ENH_START_ADDR + 1] << 8) +
 1675                             (ext_csd[EXT_CSD_ENH_START_ADDR + 2] << 16) +
 1676                             (ext_csd[EXT_CSD_ENH_START_ADDR + 3] << 24)) *
 1677                                 ((mmcp->card_features & CARD_FEATURE_SDHC) ? 1: MMC_SECTOR_SIZE);
 1678                 } else
 1679                         CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH,
 1680                             ("enhanced user data area spans entire device"));
 1681         }
 1682 
 1683         /*
 1684          * Add default partition.  This may be the only one or the user
 1685          * data area in case partitions are supported.
 1686          */
 1687         ro = sdda_get_read_only(periph, ccb);
 1688         sdda_add_part(periph, EXT_CSD_PART_CONFIG_ACC_DEFAULT, "sdda",
 1689             periph->unit_number, mmc_get_media_size(periph), ro);
 1690         sc->part_curr = EXT_CSD_PART_CONFIG_ACC_DEFAULT;
 1691 
 1692         if (mmc_get_spec_vers(periph) < 3)
 1693                 return;
 1694 
 1695         /* Belatedly announce enhanced user data slice. */
 1696         if (sc->enh_size != 0) {
 1697                 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH,
 1698                     ("enhanced user data area off 0x%jx size %ju bytes\n",
 1699                         sc->enh_base, sc->enh_size));
 1700         }
 1701 
 1702         /*
 1703          * Determine partition switch timeout (provided in units of 10 ms)
 1704          * and ensure it's at least 300 ms as some eMMC chips lie.
 1705          */
 1706         sc->part_time = max(ext_csd[EXT_CSD_PART_SWITCH_TO] * 10 * 1000,
 1707             300 * 1000);
 1708 
 1709         /* Add boot partitions, which are of a fixed multiple of 128 KB. */
 1710         size = ext_csd[EXT_CSD_BOOT_SIZE_MULT] * MMC_BOOT_RPMB_BLOCK_SIZE;
 1711         if (size > 0 && (sdda_get_host_caps(periph, ccb) & MMC_CAP_BOOT_NOACC) == 0) {
 1712                 sdda_add_part(periph, EXT_CSD_PART_CONFIG_ACC_BOOT0,
 1713                     SDDA_FMT_BOOT, 0, size,
 1714                     ro | ((ext_csd[EXT_CSD_BOOT_WP_STATUS] &
 1715                     EXT_CSD_BOOT_WP_STATUS_BOOT0_MASK) != 0));
 1716                 sdda_add_part(periph, EXT_CSD_PART_CONFIG_ACC_BOOT1,
 1717                     SDDA_FMT_BOOT, 1, size,
 1718                     ro | ((ext_csd[EXT_CSD_BOOT_WP_STATUS] &
 1719                     EXT_CSD_BOOT_WP_STATUS_BOOT1_MASK) != 0));
 1720         }
 1721 
 1722         /* Add RPMB partition, which also is of a fixed multiple of 128 KB. */
 1723         size = ext_csd[EXT_CSD_RPMB_MULT] * MMC_BOOT_RPMB_BLOCK_SIZE;
 1724         if (rev >= 5 && size > 0)
 1725                 sdda_add_part(periph, EXT_CSD_PART_CONFIG_ACC_RPMB,
 1726                     SDDA_FMT_RPMB, 0, size, ro);
 1727 
 1728         if (rev <= 3 || comp == FALSE)
 1729                 return;
 1730 
 1731         /*
 1732          * Add general purpose partitions, which are of a multiple of high
 1733          * capacity write protect groups, too.
 1734          */
 1735         if ((ext_csd[EXT_CSD_PART_SUPPORT] & EXT_CSD_PART_SUPPORT_EN) != 0) {
 1736                 erase_size = ext_csd[EXT_CSD_ERASE_GRP_SIZE] * 1024 *
 1737                         MMC_SECTOR_SIZE;
 1738                 wp_size = ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
 1739                 for (i = 0; i < MMC_PART_GP_MAX; i++) {
 1740                         size = ext_csd[EXT_CSD_GP_SIZE_MULT + i * 3] +
 1741                                 (ext_csd[EXT_CSD_GP_SIZE_MULT + i * 3 + 1] << 8) +
 1742                                 (ext_csd[EXT_CSD_GP_SIZE_MULT + i * 3 + 2] << 16);
 1743                         if (size == 0)
 1744                                 continue;
 1745                         sdda_add_part(periph, EXT_CSD_PART_CONFIG_ACC_GP0 + i,
 1746                             SDDA_FMT_GP, i, size * erase_size * wp_size, ro);
 1747                 }
 1748         }
 1749 }
 1750 
 1751 /*
 1752  * We cannot just call mmc_switch() since it will sleep, and we are in
 1753  * GEOM context and cannot sleep. Instead, create an MMCIO request to switch
 1754  * partitions and send it to h/w, and upon completion resume processing
 1755  * the I/O queue.
 1756  * This function cannot fail, instead check switch errors in sddadone().
 1757  */
 1758 static void
 1759 sdda_init_switch_part(struct cam_periph *periph, union ccb *start_ccb,
 1760     uint8_t part)
 1761 {
 1762         struct sdda_softc *sc = (struct sdda_softc *)periph->softc;
 1763         uint8_t value;
 1764 
 1765         KASSERT(part < MMC_PART_MAX, ("%s: invalid partition index", __func__));
 1766         sc->part_requested = part;
 1767 
 1768         value = (sc->raw_ext_csd[EXT_CSD_PART_CONFIG] &
 1769             ~EXT_CSD_PART_CONFIG_ACC_MASK) | part;
 1770 
 1771         mmc_switch_fill_mmcio(start_ccb, EXT_CSD_CMD_SET_NORMAL,
 1772             EXT_CSD_PART_CONFIG, value, sc->part_time);
 1773         start_ccb->ccb_h.cbfcnp = sddadone;
 1774 
 1775         sc->outstanding_cmds++;
 1776         cam_periph_unlock(periph);
 1777         xpt_action(start_ccb);
 1778         cam_periph_lock(periph);
 1779 }
 1780 
 1781 /* Called with periph lock held! */
 1782 static void
 1783 sddastart(struct cam_periph *periph, union ccb *start_ccb)
 1784 {
 1785         struct bio *bp;
 1786         struct sdda_softc *softc = (struct sdda_softc *)periph->softc;
 1787         struct sdda_part *part;
 1788         struct mmc_params *mmcp = &periph->path->device->mmc_ident_data;
 1789         uint8_t part_index;
 1790 
 1791         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sddastart\n"));
 1792 
 1793         if (softc->state != SDDA_STATE_NORMAL) {
 1794                 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("device is not in SDDA_STATE_NORMAL yet\n"));
 1795                 xpt_release_ccb(start_ccb);
 1796                 return;
 1797         }
 1798 
 1799         /* Find partition that has outstanding commands.  Prefer current partition. */
 1800         part_index = softc->part_curr;
 1801         part = softc->part[softc->part_curr];
 1802         bp = bioq_first(&part->bio_queue);
 1803         if (bp == NULL) {
 1804                 for (part_index = 0; part_index < MMC_PART_MAX; part_index++) {
 1805                         if ((part = softc->part[part_index]) != NULL &&
 1806                             (bp = bioq_first(&softc->part[part_index]->bio_queue)) != NULL)
 1807                                 break;
 1808                 }
 1809         }
 1810         if (bp == NULL) {
 1811                 xpt_release_ccb(start_ccb);
 1812                 return;
 1813         }
 1814         if (part_index != softc->part_curr) {
 1815                 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH,
 1816                     ("Partition  %d -> %d\n", softc->part_curr, part_index));
 1817                 /*
 1818                  * According to section "6.2.2 Command restrictions" of the eMMC
 1819                  * specification v5.1, CMD19/CMD21 aren't allowed to be used with
 1820                  * RPMB partitions.  So we pause re-tuning along with triggering
 1821                  * it up-front to decrease the likelihood of re-tuning becoming
 1822                  * necessary while accessing an RPMB partition.  Consequently, an
 1823                  * RPMB partition should immediately be switched away from again
 1824                  * after an access in order to allow for re-tuning to take place
 1825                  * anew.
 1826                  */
 1827                 /* TODO: pause retune if switching to RPMB partition */
 1828                 softc->state = SDDA_STATE_PART_SWITCH;
 1829                 sdda_init_switch_part(periph, start_ccb, part_index);
 1830                 return;
 1831         }
 1832 
 1833         bioq_remove(&part->bio_queue, bp);
 1834 
 1835         switch (bp->bio_cmd) {
 1836         case BIO_WRITE:
 1837                 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("BIO_WRITE\n"));
 1838                 part->flags |= SDDA_FLAG_DIRTY;
 1839                 /* FALLTHROUGH */
 1840         case BIO_READ:
 1841         {
 1842                 struct ccb_mmcio *mmcio;
 1843                 uint64_t blockno = bp->bio_pblkno;
 1844                 uint16_t count = bp->bio_bcount / MMC_SECTOR_SIZE;
 1845                 uint16_t opcode;
 1846 
 1847                 if (bp->bio_cmd == BIO_READ)
 1848                         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("BIO_READ\n"));
 1849                 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
 1850                     ("Block %"PRIu64" cnt %u\n", blockno, count));
 1851 
 1852                 /* Construct new MMC command */
 1853                 if (bp->bio_cmd == BIO_READ) {
 1854                         if (count > 1)
 1855                                 opcode = MMC_READ_MULTIPLE_BLOCK;
 1856                         else
 1857                                 opcode = MMC_READ_SINGLE_BLOCK;
 1858                 } else {
 1859                         if (count > 1)
 1860                                 opcode = MMC_WRITE_MULTIPLE_BLOCK;
 1861                         else
 1862                                 opcode = MMC_WRITE_BLOCK;
 1863                 }
 1864 
 1865                 start_ccb->ccb_h.func_code = XPT_MMC_IO;
 1866                 start_ccb->ccb_h.flags = (bp->bio_cmd == BIO_READ ? CAM_DIR_IN : CAM_DIR_OUT);
 1867                 start_ccb->ccb_h.retry_count = 0;
 1868                 start_ccb->ccb_h.timeout = 15 * 1000;
 1869                 start_ccb->ccb_h.cbfcnp = sddadone;
 1870 
 1871                 mmcio = &start_ccb->mmcio;
 1872                 mmcio->cmd.opcode = opcode;
 1873                 mmcio->cmd.arg = blockno;
 1874                 if (!(mmcp->card_features & CARD_FEATURE_SDHC))
 1875                         mmcio->cmd.arg <<= 9;
 1876 
 1877                 mmcio->cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
 1878                 mmcio->cmd.data = softc->mmcdata;
 1879                 memset(mmcio->cmd.data, 0, sizeof(struct mmc_data));
 1880                 mmcio->cmd.data->data = bp->bio_data;
 1881                 mmcio->cmd.data->len = MMC_SECTOR_SIZE * count;
 1882                 mmcio->cmd.data->flags = (bp->bio_cmd == BIO_READ ? MMC_DATA_READ : MMC_DATA_WRITE);
 1883                 /* Direct h/w to issue CMD12 upon completion */
 1884                 if (count > 1) {
 1885                         mmcio->cmd.data->flags |= MMC_DATA_MULTI;
 1886                         mmcio->stop.opcode = MMC_STOP_TRANSMISSION;
 1887                         mmcio->stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
 1888                         mmcio->stop.arg = 0;
 1889                 }
 1890 
 1891                 break;
 1892         }
 1893         case BIO_FLUSH:
 1894                 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("BIO_FLUSH\n"));
 1895                 sddaschedule(periph);
 1896                 break;
 1897         case BIO_DELETE:
 1898                 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("BIO_DELETE\n"));
 1899                 sddaschedule(periph);
 1900                 break;
 1901         default:
 1902                 biofinish(bp, NULL, EOPNOTSUPP);
 1903                 xpt_release_ccb(start_ccb);
 1904                 return;
 1905         }
 1906         start_ccb->ccb_h.ccb_bp = bp;
 1907         softc->outstanding_cmds++;
 1908         softc->refcount++;
 1909         cam_periph_unlock(periph);
 1910         xpt_action(start_ccb);
 1911         cam_periph_lock(periph);
 1912 
 1913         /* May have more work to do, so ensure we stay scheduled */
 1914         sddaschedule(periph);
 1915 }
 1916 
 1917 static void
 1918 sddadone(struct cam_periph *periph, union ccb *done_ccb)
 1919 {
 1920         struct bio *bp;
 1921         struct sdda_softc *softc;
 1922         struct ccb_mmcio *mmcio;
 1923         struct cam_path *path;
 1924         uint32_t card_status;
 1925         int error = 0;
 1926 
 1927         softc = (struct sdda_softc *)periph->softc;
 1928         mmcio = &done_ccb->mmcio;
 1929         path = done_ccb->ccb_h.path;
 1930 
 1931         CAM_DEBUG(path, CAM_DEBUG_TRACE, ("sddadone\n"));
 1932         if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1933                 CAM_DEBUG(path, CAM_DEBUG_TRACE, ("Error!!!\n"));
 1934                 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1935                         cam_release_devq(path,
 1936                             /*relsim_flags*/0,
 1937                             /*reduction*/0,
 1938                             /*timeout*/0,
 1939                             /*getcount_only*/0);
 1940                 error = EIO;
 1941         } else {
 1942                 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1943                         panic("REQ_CMP with QFRZN");
 1944                 error = 0;
 1945         }
 1946 
 1947         card_status = mmcio->cmd.resp[0];
 1948         CAM_DEBUG(path, CAM_DEBUG_TRACE,
 1949             ("Card status: %08x\n", R1_STATUS(card_status)));
 1950         CAM_DEBUG(path, CAM_DEBUG_TRACE,
 1951             ("Current state: %d\n", R1_CURRENT_STATE(card_status)));
 1952 
 1953         /* Process result of switching MMC partitions */
 1954         if (softc->state == SDDA_STATE_PART_SWITCH) {
 1955                 CAM_DEBUG(path, CAM_DEBUG_TRACE,
 1956                     ("Completing partition switch to %d\n",
 1957                     softc->part_requested));
 1958                 softc->outstanding_cmds--;
 1959                 /* Complete partition switch */
 1960                 softc->state = SDDA_STATE_NORMAL;
 1961                 if (error != 0) {
 1962                         /* TODO: Unpause retune if accessing RPMB */
 1963                         xpt_release_ccb(done_ccb);
 1964                         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 1965                         return;
 1966                 }
 1967 
 1968                 softc->raw_ext_csd[EXT_CSD_PART_CONFIG] =
 1969                     (softc->raw_ext_csd[EXT_CSD_PART_CONFIG] &
 1970                         ~EXT_CSD_PART_CONFIG_ACC_MASK) | softc->part_requested;
 1971                 /* TODO: Unpause retune if accessing RPMB */
 1972                 softc->part_curr = softc->part_requested;
 1973                 xpt_release_ccb(done_ccb);
 1974 
 1975                 /* Return to processing BIO requests */
 1976                 xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 1977                 return;
 1978         }
 1979 
 1980         bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
 1981         bp->bio_error = error;
 1982         if (error != 0) {
 1983                 bp->bio_resid = bp->bio_bcount;
 1984                 bp->bio_flags |= BIO_ERROR;
 1985         } else {
 1986                 /* XXX: How many bytes remaining? */
 1987                 bp->bio_resid = 0;
 1988                 if (bp->bio_resid > 0)
 1989                         bp->bio_flags |= BIO_ERROR;
 1990         }
 1991 
 1992         softc->outstanding_cmds--;
 1993         xpt_release_ccb(done_ccb);
 1994         /*
 1995          * Release the periph refcount taken in sddastart() for each CCB.
 1996          */
 1997         KASSERT(softc->refcount >= 1, ("sddadone softc %p refcount %d", softc, softc->refcount));
 1998         softc->refcount--;
 1999         biodone(bp);
 2000 }
 2001 
 2002 static int
 2003 sddaerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
 2004 {
 2005         return(cam_periph_error(ccb, cam_flags, sense_flags));
 2006 }
 2007 
 2008 static int
 2009 sddadump(void *arg, void *virtual, off_t offset, size_t length)
 2010 {
 2011         struct ccb_mmcio mmcio;
 2012         struct disk *dp;
 2013         struct sdda_part *part;
 2014         struct sdda_softc *softc;
 2015         struct cam_periph *periph;
 2016         struct mmc_params *mmcp;
 2017         uint16_t count;
 2018         uint16_t opcode;
 2019         int error;
 2020 
 2021         dp = arg;
 2022         part = dp->d_drv1;
 2023         softc = part->sc;
 2024         periph = softc->periph;
 2025         mmcp = &periph->path->device->mmc_ident_data;
 2026 
 2027         if (softc->state != SDDA_STATE_NORMAL)
 2028                 return (ENXIO);
 2029 
 2030         count = length / MMC_SECTOR_SIZE;
 2031         if (count == 0)
 2032                 return (0);
 2033 
 2034         if (softc->part[softc->part_curr] != part)
 2035                 return (EIO);   /* TODO implement polled partition switch */
 2036 
 2037         memset(&mmcio, 0, sizeof(mmcio));
 2038         xpt_setup_ccb(&mmcio.ccb_h, periph->path, CAM_PRIORITY_NORMAL); /* XXX needed? */
 2039 
 2040         mmcio.ccb_h.func_code = XPT_MMC_IO;
 2041         mmcio.ccb_h.flags = CAM_DIR_OUT;
 2042         mmcio.ccb_h.retry_count = 0;
 2043         mmcio.ccb_h.timeout = 15 * 1000;
 2044 
 2045         if (count > 1)
 2046                 opcode = MMC_WRITE_MULTIPLE_BLOCK;
 2047         else
 2048                 opcode = MMC_WRITE_BLOCK;
 2049         mmcio.cmd.opcode = opcode;
 2050         mmcio.cmd.arg = offset / MMC_SECTOR_SIZE;
 2051         if (!(mmcp->card_features & CARD_FEATURE_SDHC))
 2052                 mmcio.cmd.arg <<= 9;
 2053 
 2054         mmcio.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
 2055         mmcio.cmd.data = softc->mmcdata;
 2056         memset(mmcio.cmd.data, 0, sizeof(struct mmc_data));
 2057         mmcio.cmd.data->data = virtual;
 2058         mmcio.cmd.data->len = MMC_SECTOR_SIZE * count;
 2059         mmcio.cmd.data->flags = MMC_DATA_WRITE;
 2060 
 2061         /* Direct h/w to issue CMD12 upon completion */
 2062         if (count > 1) {
 2063                 mmcio.cmd.data->flags |= MMC_DATA_MULTI;
 2064                 mmcio.stop.opcode = MMC_STOP_TRANSMISSION;
 2065                 mmcio.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
 2066                 mmcio.stop.arg = 0;
 2067         }
 2068 
 2069         error = cam_periph_runccb((union ccb *)&mmcio, cam_periph_error,
 2070             0, SF_NO_RECOVERY | SF_NO_RETRY, NULL);
 2071         if (error != 0)
 2072                 printf("Aborting dump due to I/O error.\n");
 2073         return (error);
 2074 }
 2075 
 2076 #endif /* _KERNEL */

Cache object: 470c010ba3f919eb974f26add67245f6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.