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/dev/sdio/sdiob.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  * Copyright (c) 2017 Ilya Bakulin.  All rights reserved.
    3  * Copyright (c) 2018-2019 The FreeBSD Foundation
    4  *
    5  * Portions of this software were developed by Björn Zeeb
    6  * under sponsorship from the FreeBSD Foundation.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  *
   29  * Portions of this software may have been developed with reference to
   30  * the SD Simplified Specification.  The following disclaimer may apply:
   31  *
   32  * The following conditions apply to the release of the simplified
   33  * specification ("Simplified Specification") by the SD Card Association and
   34  * the SD Group. The Simplified Specification is a subset of the complete SD
   35  * Specification which is owned by the SD Card Association and the SD
   36  * Group. This Simplified Specification is provided on a non-confidential
   37  * basis subject to the disclaimers below. Any implementation of the
   38  * Simplified Specification may require a license from the SD Card
   39  * Association, SD Group, SD-3C LLC or other third parties.
   40  *
   41  * Disclaimers:
   42  *
   43  * The information contained in the Simplified Specification is presented only
   44  * as a standard specification for SD Cards and SD Host/Ancillary products and
   45  * is provided "AS-IS" without any representations or warranties of any
   46  * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
   47  * Card Association for any damages, any infringements of patents or other
   48  * right of the SD Group, SD-3C LLC, the SD Card Association or any third
   49  * parties, which may result from its use. No license is granted by
   50  * implication, estoppel or otherwise under any patent or other rights of the
   51  * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
   52  * herein shall be construed as an obligation by the SD Group, the SD-3C LLC
   53  * or the SD Card Association to disclose or distribute any technical
   54  * information, know-how or other confidential information to any third party.
   55  */
   56 /*
   57  * Implements the (kernel specific) SDIO parts.
   58  * This will hide all cam(4) functionality from the SDIO driver implementations
   59  * which will just be newbus/device(9) and hence look like any other driver for,
   60  * e.g., PCI.
   61  * The sdiob(4) parts effetively "translate" between the two worlds "bridging"
   62  * messages from MMCCAM to newbus and back.
   63  */
   64 
   65 #include <sys/cdefs.h>
   66 __FBSDID("$FreeBSD$");
   67 
   68 #include "opt_cam.h"
   69 
   70 #include <sys/param.h>
   71 #include <sys/systm.h>
   72 #include <sys/types.h>
   73 #include <sys/kernel.h>
   74 #include <sys/bus.h>
   75 #include <sys/endian.h>
   76 #include <sys/lock.h>
   77 #include <sys/malloc.h>
   78 #include <sys/module.h>
   79 #include <sys/mutex.h>
   80 
   81 #include <cam/cam.h>
   82 #include <cam/cam_ccb.h>
   83 #include <cam/cam_queue.h>
   84 #include <cam/cam_periph.h>
   85 #include <cam/cam_xpt.h>
   86 #include <cam/cam_xpt_periph.h>
   87 #include <cam/cam_xpt_internal.h> /* for cam_path */
   88 #include <cam/cam_debug.h>
   89 
   90 #include <dev/mmc/mmcreg.h>
   91 
   92 #include <dev/sdio/sdiob.h>
   93 #include <dev/sdio/sdio_subr.h>
   94 
   95 #include "sdio_if.h"
   96 
   97 #ifdef DEBUG
   98 #define DPRINTF(...)            printf(__VA_ARGS__)
   99 #define DPRINTFDEV(_dev, ...)   device_printf((_dev), __VA_ARGS__)
  100 #else
  101 #define DPRINTF(...)
  102 #define DPRINTFDEV(_dev, ...)
  103 #endif
  104 
  105 struct sdiob_softc {
  106         uint32_t                        sdio_state;
  107 #define SDIO_STATE_DEAD                 0x0001
  108 #define SDIO_STATE_INITIALIZING         0x0002
  109 #define SDIO_STATE_READY                0x0004
  110         uint32_t                        nb_state;
  111 #define NB_STATE_DEAD                   0x0001
  112 #define NB_STATE_SIM_ADDED              0x0002
  113 #define NB_STATE_READY                  0x0004
  114 
  115         /* CAM side. */
  116         struct card_info                cardinfo;
  117         struct cam_periph               *periph;
  118         union ccb                       *ccb;
  119         struct task                     discover_task;
  120 
  121         /* Newbus side. */
  122         device_t                        dev;    /* Ourselves. */
  123         device_t                        child[8];
  124 };
  125 
  126 /* -------------------------------------------------------------------------- */
  127 /*
  128  * SDIO CMD52 and CM53 implementations along with wrapper functions for
  129  * read/write and a CAM periph helper function.
  130  * These are the backend implementations of the sdio_if.m framework talking
  131  * through CAM to sdhci.
  132  * Note: these functions are also called during early discovery stage when
  133  * we are not a device(9) yet. Hence they cannot always use device_printf()
  134  * to log errors and have to call CAM_DEBUG() during these early stages.
  135  */
  136 
  137 static int
  138 sdioerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
  139 {
  140 
  141         return (cam_periph_error(ccb, cam_flags, sense_flags));
  142 }
  143 
  144 /* CMD52: direct byte access. */
  145 static int
  146 sdiob_rw_direct_sc(struct sdiob_softc *sc, uint8_t fn, uint32_t addr, bool wr,
  147     uint8_t *val)
  148 {
  149         uint32_t arg, flags;
  150         int error;
  151 
  152         KASSERT((val != NULL), ("%s val passed as NULL\n", __func__));
  153 
  154         if (sc->ccb == NULL)
  155                 sc->ccb = xpt_alloc_ccb();
  156         else
  157                 memset(sc->ccb, 0, sizeof(*sc->ccb));
  158         xpt_setup_ccb(&sc->ccb->ccb_h, sc->periph->path, CAM_PRIORITY_NONE);
  159         CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_TRACE,
  160             ("%s(fn=%d, addr=%#02x, wr=%d, *val=%#02x)\n", __func__,
  161             fn, addr, wr, *val));
  162 
  163         flags = MMC_RSP_R5 | MMC_CMD_AC;
  164         arg = SD_IO_RW_FUNC(fn) | SD_IO_RW_ADR(addr);
  165         if (wr)
  166                 arg |= SD_IO_RW_WR | SD_IO_RW_RAW | SD_IO_RW_DAT(*val);
  167 
  168         cam_fill_mmcio(&sc->ccb->mmcio,
  169                 /*retries*/ 0,
  170                 /*cbfcnp*/ NULL,
  171                 /*flags*/ CAM_DIR_NONE,
  172                 /*mmc_opcode*/ SD_IO_RW_DIRECT,
  173                 /*mmc_arg*/ arg,
  174                 /*mmc_flags*/ flags,
  175                 /*mmc_data*/ 0,
  176                 /*timeout*/ sc->cardinfo.f[fn].timeout);
  177         error = cam_periph_runccb(sc->ccb, sdioerror, CAM_FLAG_NONE, 0, NULL);
  178         if (error != 0) {
  179                 if (sc->dev != NULL)
  180                         device_printf(sc->dev,
  181                             "%s: Failed to %s address %#10x error=%d\n",
  182                             __func__, (wr) ? "write" : "read", addr, error);
  183                 else
  184                         CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_INFO,
  185                             ("%s: Failed to %s address: %#10x error=%d\n",
  186                             __func__, (wr) ? "write" : "read", addr, error));
  187                 return (error);
  188         }
  189 
  190         /* TODO: Add handling of MMC errors */
  191         /* ccb->mmcio.cmd.error ? */
  192         if (wr == false)
  193                 *val = sc->ccb->mmcio.cmd.resp[0] & 0xff;
  194 
  195         return (0);
  196 }
  197 
  198 static int
  199 sdio_rw_direct(device_t dev, uint8_t fn, uint32_t addr, bool wr,
  200     uint8_t *val)
  201 {
  202         struct sdiob_softc *sc;
  203         int error;
  204 
  205         sc = device_get_softc(dev);
  206         cam_periph_lock(sc->periph);
  207         error = sdiob_rw_direct_sc(sc, fn, addr, wr, val);
  208         cam_periph_unlock(sc->periph);
  209         return (error);
  210 }
  211 
  212 static int
  213 sdiob_read_direct(device_t dev, uint8_t fn, uint32_t addr, uint8_t *val)
  214 {
  215         int error;
  216         uint8_t v;
  217 
  218         error = sdio_rw_direct(dev, fn, addr, false, &v);
  219         /* Be polite and do not touch the value on read error. */
  220         if (error == 0 && val != NULL)
  221                 *val = v;
  222         return (error);
  223 }
  224 
  225 static int
  226 sdiob_write_direct(device_t dev, uint8_t fn, uint32_t addr, uint8_t val)
  227 {
  228 
  229         return (sdio_rw_direct(dev, fn, addr, true, &val));
  230 }
  231 
  232 /*
  233  * CMD53: IO_RW_EXTENDED, read and write multiple I/O registers.
  234  * Increment false gets FIFO mode (single register address).
  235  */
  236 /*
  237  * A b_count of 0 means byte mode, b_count > 0 gets block mode.
  238  * A b_count of >= 512 would mean infinitive block transfer, which would become
  239  * b_count = 0, is not yet supported.
  240  * For b_count == 0, blksz is the len of bytes, otherwise it is the amount of
  241  * full sized blocks (you must not round the blocks up and leave the last one
  242  * partial!)
  243  * For byte mode, the maximum of blksz is the functions cur_blksize.
  244  * This function should ever only be called by sdio_rw_extended_sc()! 
  245  */
  246 static int
  247 sdiob_rw_extended_cam(struct sdiob_softc *sc, uint8_t fn, uint32_t addr,
  248     bool wr, uint8_t *buffer, bool incaddr, uint32_t b_count, uint16_t blksz)
  249 {
  250         struct mmc_data mmcd;
  251         uint32_t arg, cam_flags, flags, len;
  252         int error;
  253 
  254         if (sc->ccb == NULL)
  255                 sc->ccb = xpt_alloc_ccb();
  256         else
  257                 memset(sc->ccb, 0, sizeof(*sc->ccb));
  258         xpt_setup_ccb(&sc->ccb->ccb_h, sc->periph->path, CAM_PRIORITY_NONE);
  259         CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_TRACE,
  260             ("%s(fn=%d addr=%#0x wr=%d b_count=%u blksz=%u buf=%p incr=%d)\n",
  261             __func__, fn, addr, wr, b_count, blksz, buffer, incaddr));
  262 
  263         KASSERT((b_count <= 511), ("%s: infinitive block transfer not yet "
  264             "supported: b_count %u blksz %u, sc %p, fn %u, addr %#10x, %s, "
  265             "buffer %p, %s\n", __func__, b_count, blksz, sc, fn, addr,
  266             wr ? "wr" : "rd", buffer, incaddr ? "incaddr" : "fifo"));
  267         /* Blksz needs to be within bounds for both byte and block mode! */
  268         KASSERT((blksz <= sc->cardinfo.f[fn].cur_blksize), ("%s: blksz "
  269             "%u > bur_blksize %u, sc %p, fn %u, addr %#10x, %s, "
  270             "buffer %p, %s, b_count %u\n", __func__, blksz,
  271             sc->cardinfo.f[fn].cur_blksize, sc, fn, addr,
  272             wr ? "wr" : "rd", buffer, incaddr ? "incaddr" : "fifo",
  273             b_count));
  274         if (b_count == 0) {
  275                 /* Byte mode */
  276                 len = blksz;
  277                 if (blksz == 512)
  278                         blksz = 0;
  279                 arg = SD_IOE_RW_LEN(blksz);
  280         } else {
  281                 /* Block mode. */
  282 #ifdef __notyet__
  283                 if (b_count > 511) {
  284                         /* Infinitive block transfer. */
  285                         b_count = 0;
  286                 }
  287 #endif
  288                 len = b_count * blksz;
  289                 arg = SD_IOE_RW_BLK | SD_IOE_RW_LEN(b_count);
  290         }
  291 
  292         flags = MMC_RSP_R5 | MMC_CMD_ADTC;
  293         arg |= SD_IOE_RW_FUNC(fn) | SD_IOE_RW_ADR(addr);
  294         if (incaddr)
  295                 arg |= SD_IOE_RW_INCR;
  296 
  297         memset(&mmcd, 0, sizeof(mmcd));
  298         mmcd.data = buffer;
  299         mmcd.len = len;
  300         if (arg & SD_IOE_RW_BLK) {
  301                 /* XXX both should be known from elsewhere, aren't they? */
  302                 mmcd.block_size = blksz;
  303                 mmcd.block_count = b_count;
  304         }
  305 
  306         if (wr) {
  307                 arg |= SD_IOE_RW_WR;
  308                 cam_flags = CAM_DIR_OUT;
  309                 mmcd.flags = MMC_DATA_WRITE;
  310         } else {
  311                 cam_flags = CAM_DIR_IN;
  312                 mmcd.flags = MMC_DATA_READ;
  313         }
  314 #ifdef __notyet__
  315         if (b_count == 0) {
  316                 /* XXX-BZ TODO FIXME.  Cancel I/O: CCCR -> ASx */
  317                 /* Stop cmd. */
  318         }
  319 #endif
  320         cam_fill_mmcio(&sc->ccb->mmcio,
  321                 /*retries*/ 0,
  322                 /*cbfcnp*/ NULL,
  323                 /*flags*/ cam_flags,
  324                 /*mmc_opcode*/ SD_IO_RW_EXTENDED,
  325                 /*mmc_arg*/ arg,
  326                 /*mmc_flags*/ flags,
  327                 /*mmc_data*/ &mmcd,
  328                 /*timeout*/ sc->cardinfo.f[fn].timeout);
  329         if (arg & SD_IOE_RW_BLK) {
  330                 mmcd.flags |= MMC_DATA_BLOCK_SIZE;
  331                 if (b_count != 1)
  332                         sc->ccb->mmcio.cmd.data->flags |= MMC_DATA_MULTI;
  333         }
  334 
  335         /* Execute. */
  336         error = cam_periph_runccb(sc->ccb, sdioerror, CAM_FLAG_NONE, 0, NULL);
  337         if (error != 0) {
  338                 if (sc->dev != NULL)
  339                         device_printf(sc->dev,
  340                             "%s: Failed to %s address %#10x buffer %p size %u "
  341                             "%s b_count %u blksz %u error=%d\n",
  342                             __func__, (wr) ? "write to" : "read from", addr,
  343                             buffer, len, (incaddr) ? "incr" : "fifo",
  344                             b_count, blksz, error);
  345                 else
  346                         CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_INFO,
  347                             ("%s: Failed to %s address %#10x buffer %p size %u "
  348                             "%s b_count %u blksz %u error=%d\n",
  349                             __func__, (wr) ? "write to" : "read from", addr,
  350                             buffer, len, (incaddr) ? "incr" : "fifo",
  351                             b_count, blksz, error));
  352                 return (error);
  353         }
  354 
  355         /* TODO: Add handling of MMC errors */
  356         /* ccb->mmcio.cmd.error ? */
  357         error = sc->ccb->mmcio.cmd.resp[0] & 0xff;
  358         if (error != 0) {
  359                 if (sc->dev != NULL)
  360                         device_printf(sc->dev,
  361                             "%s: Failed to %s address %#10x buffer %p size %u "
  362                             "%s b_count %u blksz %u mmcio resp error=%d\n",
  363                             __func__, (wr) ? "write to" : "read from", addr,
  364                             buffer, len, (incaddr) ? "incr" : "fifo",
  365                             b_count, blksz, error);
  366                 else
  367                         CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_INFO,
  368                             ("%s: Failed to %s address %#10x buffer %p size %u "
  369                             "%s b_count %u blksz %u mmcio resp error=%d\n",
  370                             __func__, (wr) ? "write to" : "read from", addr,
  371                             buffer, len, (incaddr) ? "incr" : "fifo",
  372                             b_count, blksz, error));
  373         }
  374         return (error);
  375 }
  376 
  377 static int
  378 sdiob_rw_extended_sc(struct sdiob_softc *sc, uint8_t fn, uint32_t addr,
  379     bool wr, uint32_t size, uint8_t *buffer, bool incaddr)
  380 {
  381         int error;
  382         uint32_t len;
  383         uint32_t b_count;
  384 
  385         /*
  386          * If block mode is supported and we have at least 4 bytes to write and
  387          * the size is at least one block, then start doing blk transfers.
  388          */
  389         while (sc->cardinfo.support_multiblk &&
  390             size > 4 && size >= sc->cardinfo.f[fn].cur_blksize) {
  391                 b_count = size / sc->cardinfo.f[fn].cur_blksize;
  392                 KASSERT(b_count >= 1, ("%s: block count too small %u size %u "
  393                     "cur_blksize %u\n", __func__, b_count, size,
  394                     sc->cardinfo.f[fn].cur_blksize));
  395 
  396 #ifdef __notyet__
  397                 /* XXX support inifinite transfer with b_count = 0. */
  398 #else
  399                 if (b_count > 511)
  400                         b_count = 511;
  401 #endif
  402                 len = b_count * sc->cardinfo.f[fn].cur_blksize;
  403                 error = sdiob_rw_extended_cam(sc, fn, addr, wr, buffer, incaddr,
  404                     b_count, sc->cardinfo.f[fn].cur_blksize);
  405                 if (error != 0)
  406                         return (error);
  407 
  408                 size -= len;
  409                 buffer += len;
  410                 if (incaddr)
  411                         addr += len;
  412         }
  413 
  414         while (size > 0) {
  415                 len = MIN(size, sc->cardinfo.f[fn].cur_blksize);
  416 
  417                 error = sdiob_rw_extended_cam(sc, fn, addr, wr, buffer, incaddr,
  418                     0, len);
  419                 if (error != 0)
  420                         return (error);
  421 
  422                 /* Prepare for next iteration. */
  423                 size -= len;
  424                 buffer += len;
  425                 if (incaddr)
  426                         addr += len;
  427         }
  428 
  429         return (0);
  430 }
  431 
  432 static int
  433 sdiob_rw_extended(device_t dev, uint8_t fn, uint32_t addr, bool wr,
  434     uint32_t size, uint8_t *buffer, bool incaddr)
  435 {
  436         struct sdiob_softc *sc;
  437         int error;
  438 
  439         sc = device_get_softc(dev);
  440         cam_periph_lock(sc->periph);
  441         error = sdiob_rw_extended_sc(sc, fn, addr, wr, size, buffer, incaddr);
  442         cam_periph_unlock(sc->periph);
  443         return (error);
  444 }
  445 
  446 static int
  447 sdiob_read_extended(device_t dev, uint8_t fn, uint32_t addr, uint32_t size,
  448     uint8_t *buffer, bool incaddr)
  449 {
  450 
  451         return (sdiob_rw_extended(dev, fn, addr, false, size, buffer, incaddr));
  452 }
  453 
  454 static int
  455 sdiob_write_extended(device_t dev, uint8_t fn, uint32_t addr, uint32_t size,
  456     uint8_t *buffer, bool incaddr)
  457 {
  458 
  459         return (sdiob_rw_extended(dev, fn, addr, true, size, buffer, incaddr));
  460 }
  461 
  462 /* -------------------------------------------------------------------------- */
  463 /* Bus interface, ivars handling. */
  464 
  465 static int
  466 sdiob_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
  467 {
  468         struct sdiob_softc *sc;
  469         struct sdio_func *f;
  470 
  471         f = device_get_ivars(child);
  472         KASSERT(f != NULL, ("%s: dev %p child %p which %d, child ivars NULL\n",
  473             __func__, dev, child, which));
  474 
  475         switch (which) {
  476         case SDIOB_IVAR_SUPPORT_MULTIBLK:
  477                 sc = device_get_softc(dev);
  478                 KASSERT(sc != NULL, ("%s: dev %p child %p which %d, sc NULL\n",
  479                     __func__, dev, child, which));
  480                 *result = sc->cardinfo.support_multiblk;
  481                 break;
  482         case SDIOB_IVAR_FUNCTION:
  483                 *result = (uintptr_t)f;
  484                 break;
  485         case SDIOB_IVAR_FUNCNUM:
  486                 *result = f->fn;
  487                 break;
  488         case SDIOB_IVAR_CLASS:
  489                 *result = f->class;
  490                 break;
  491         case SDIOB_IVAR_VENDOR:
  492                 *result = f->vendor;
  493                 break;
  494         case SDIOB_IVAR_DEVICE:
  495                 *result = f->device;
  496                 break;
  497         case SDIOB_IVAR_DRVDATA:
  498                 *result = f->drvdata;
  499                 break;
  500         default:
  501                 return (ENOENT);
  502         }
  503         return (0);
  504 }
  505 
  506 static int
  507 sdiob_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
  508 {
  509         struct sdio_func *f;
  510 
  511         f = device_get_ivars(child);
  512         KASSERT(f != NULL, ("%s: dev %p child %p which %d, child ivars NULL\n",
  513             __func__, dev, child, which));
  514 
  515         switch (which) {
  516         case SDIOB_IVAR_SUPPORT_MULTIBLK:
  517         case SDIOB_IVAR_FUNCTION:
  518         case SDIOB_IVAR_FUNCNUM:
  519         case SDIOB_IVAR_CLASS:
  520         case SDIOB_IVAR_VENDOR:
  521         case SDIOB_IVAR_DEVICE:
  522                 return (EINVAL);        /* Disallowed. */
  523         case SDIOB_IVAR_DRVDATA:
  524                 f->drvdata = value;
  525                 break;
  526         default:
  527                 return (ENOENT);
  528         }
  529 
  530         return (0);
  531 }
  532 
  533 /* -------------------------------------------------------------------------- */
  534 /*
  535  * Newbus functions for ourselves to probe/attach/detach and become a proper
  536  * device(9).  Attach will also probe for child devices (another driver
  537  * implementing SDIO).
  538  */
  539 
  540 static int
  541 sdiob_probe(device_t dev)
  542 {
  543 
  544         device_set_desc(dev, "SDIO CAM-Newbus bridge");
  545         return (BUS_PROBE_DEFAULT);
  546 }
  547 
  548 static int
  549 sdiob_attach(device_t dev)
  550 {
  551         struct sdiob_softc *sc;
  552         int error, i;
  553 
  554         sc = device_get_softc(dev);
  555         if (sc == NULL)
  556                 return (ENXIO);
  557 
  558         /*
  559          * Now that we are a dev, create one child device per function,
  560          * initialize the backpointer, so we can pass them around and
  561          * call CAM operations on the parent, and also set the function
  562          * itself as ivars, so that we can query/update them.
  563          * Do this before any child gets a chance to attach.
  564          */
  565         for (i = 0; i < sc->cardinfo.num_funcs; i++) {
  566                 sc->child[i] = device_add_child(dev, NULL, -1);
  567                 if (sc->child[i] == NULL) {
  568                         device_printf(dev, "%s: failed to add child\n", __func__);
  569                         return (ENXIO);
  570                 }
  571                 sc->cardinfo.f[i].dev = sc->child[i];
  572 
  573                 /* Set the function as ivar to the child device. */
  574                 device_set_ivars(sc->child[i], &sc->cardinfo.f[i]);
  575         }
  576 
  577         /*
  578          * No one will ever attach to F0; we do the above to have a "device"
  579          * to talk to in a general way in the code.
  580          * Also do the probe/attach in a 2nd loop, so that all devices are
  581          * present as we do have drivers consuming more than one device/func
  582          * and might play "tricks" in order to do that assuming devices and
  583          * ivars are available for all.
  584          */
  585         for (i = 1; i < sc->cardinfo.num_funcs; i++) {
  586                 error = device_probe_and_attach(sc->child[i]);
  587                 if (error != 0 && bootverbose)
  588                         device_printf(dev, "%s: device_probe_and_attach(%p %s) "
  589                             "failed %d for function %d, no child yet\n",
  590                              __func__,
  591                              sc->child, device_get_nameunit(sc->child[i]),
  592                              error, i);
  593         }
  594 
  595         sc->nb_state = NB_STATE_READY;
  596 
  597         cam_periph_lock(sc->periph);
  598         xpt_announce_periph(sc->periph, NULL);
  599         cam_periph_unlock(sc->periph);
  600 
  601         return (0);
  602 }
  603 
  604 static int
  605 sdiob_detach(device_t dev)
  606 {
  607 
  608         /* XXX TODO? */
  609         return (EOPNOTSUPP);
  610 }
  611 
  612 /* -------------------------------------------------------------------------- */
  613 /*
  614  * driver(9) and device(9) "control plane".
  615  * This is what we use when we are making ourselves a device(9) in order to
  616  * provide a newbus interface again, as well as the implementation of the
  617  * SDIO interface.
  618  */
  619 
  620 static device_method_t sdiob_methods[] = {
  621         /* Device interface. */
  622         DEVMETHOD(device_probe,         sdiob_probe),
  623         DEVMETHOD(device_attach,        sdiob_attach),
  624         DEVMETHOD(device_detach,        sdiob_detach),
  625 
  626         /* Bus interface. */
  627         DEVMETHOD(bus_add_child,        bus_generic_add_child),
  628         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
  629         DEVMETHOD(bus_read_ivar,        sdiob_read_ivar),
  630         DEVMETHOD(bus_write_ivar,       sdiob_write_ivar),
  631 
  632         /* SDIO interface. */
  633         DEVMETHOD(sdio_read_direct,     sdiob_read_direct),
  634         DEVMETHOD(sdio_write_direct,    sdiob_write_direct),
  635         DEVMETHOD(sdio_read_extended,   sdiob_read_extended),
  636         DEVMETHOD(sdio_write_extended,  sdiob_write_extended),
  637 
  638         DEVMETHOD_END
  639 };
  640 
  641 static driver_t sdiob_driver = {
  642         SDIOB_NAME_S,
  643         sdiob_methods,
  644         0
  645 };
  646 
  647 /* -------------------------------------------------------------------------- */
  648 /*
  649  * CIS related.
  650  * Read card and function information and populate the cardinfo structure.
  651  */
  652 
  653 static int
  654 sdio_read_direct_sc(struct sdiob_softc *sc, uint8_t fn, uint32_t addr,
  655     uint8_t *val)
  656 {
  657         int error;
  658         uint8_t v;
  659 
  660         error = sdiob_rw_direct_sc(sc, fn, addr, false, &v);
  661         if (error == 0 && val != NULL)
  662                 *val = v;
  663         return (error);
  664 }
  665 
  666 static int
  667 sdio_func_read_cis(struct sdiob_softc *sc, uint8_t fn, uint32_t cis_addr)
  668 {
  669         char cis1_info_buf[256];
  670         char *cis1_info[4];
  671         int start, i, count, ret;
  672         uint32_t addr;
  673         uint8_t ch, tuple_id, tuple_len, tuple_count, v;
  674 
  675         /* If we encounter any read errors, abort and return. */
  676 #define ERR_OUT(ret)                                                    \
  677         if (ret != 0)                                                   \
  678                 goto err;
  679         ret = 0;
  680         /* Use to prevent infinite loop in case of parse errors. */
  681         tuple_count = 0;
  682         memset(cis1_info_buf, 0, 256);
  683         do {
  684                 addr = cis_addr;
  685                 ret = sdio_read_direct_sc(sc, 0, addr++, &tuple_id);
  686                 ERR_OUT(ret);
  687                 if (tuple_id == SD_IO_CISTPL_END)
  688                         break;
  689                 if (tuple_id == 0) {
  690                         cis_addr++;
  691                         continue;
  692                 }
  693                 ret = sdio_read_direct_sc(sc, 0, addr++, &tuple_len);
  694                 ERR_OUT(ret);
  695                 if (tuple_len == 0) {
  696                         CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_PERIPH,
  697                             ("%s: parse error: 0-length tuple %#02x\n",
  698                             __func__, tuple_id));
  699                         return (EIO);
  700                 }
  701 
  702                 switch (tuple_id) {
  703                 case SD_IO_CISTPL_VERS_1:
  704                         addr += 2;
  705                         for (count = 0, start = 0, i = 0;
  706                              (count < 4) && ((i + 4) < 256); i++) {
  707                                 ret = sdio_read_direct_sc(sc, 0, addr + i, &ch);
  708                                 ERR_OUT(ret);
  709                                 DPRINTF("%s: count=%d, start=%d, i=%d, got "
  710                                     "(%#02x)\n", __func__, count, start, i, ch);
  711                                 if (ch == 0xff)
  712                                         break;
  713                                 cis1_info_buf[i] = ch;
  714                                 if (ch == 0) {
  715                                         cis1_info[count] =
  716                                             cis1_info_buf + start;
  717                                         start = i + 1;
  718                                         count++;
  719                                 }
  720                         }
  721                         DPRINTF("Card info: ");
  722                         for (i=0; i < 4; i++)
  723                                 if (cis1_info[i])
  724                                         DPRINTF(" %s", cis1_info[i]);
  725                         DPRINTF("\n");
  726                         break;
  727                 case SD_IO_CISTPL_MANFID:
  728                         /* TPLMID_MANF */
  729                         ret = sdio_read_direct_sc(sc, 0, addr++, &v);
  730                         ERR_OUT(ret);
  731                         sc->cardinfo.f[fn].vendor = v;
  732                         ret = sdio_read_direct_sc(sc, 0, addr++, &v);
  733                         ERR_OUT(ret);
  734                         sc->cardinfo.f[fn].vendor |= (v << 8);
  735                         /* TPLMID_CARD */
  736                         ret = sdio_read_direct_sc(sc, 0, addr++, &v);
  737                         ERR_OUT(ret);
  738                         sc->cardinfo.f[fn].device = v;
  739                         ret = sdio_read_direct_sc(sc, 0, addr, &v);
  740                         ERR_OUT(ret);
  741                         sc->cardinfo.f[fn].device |= (v << 8);
  742                         break;
  743                 case SD_IO_CISTPL_FUNCID:
  744                         /* Not sure if we need to parse it? */
  745                         break;
  746                 case SD_IO_CISTPL_FUNCE:
  747                         if (tuple_len < 4) {
  748                                 printf("%s: FUNCE is too short: %d\n",
  749                                     __func__, tuple_len);
  750                                 break;
  751                         }
  752                         /* TPLFE_TYPE (Extended Data) */
  753                         ret = sdio_read_direct_sc(sc, 0, addr++, &v);
  754                         ERR_OUT(ret);
  755                         if (fn == 0) {
  756                                 if (v != 0x00)
  757                                         break;
  758                         } else {
  759                                 if (v != 0x01)
  760                                         break;
  761                                 addr += 0x0b;
  762                         }
  763                         ret = sdio_read_direct_sc(sc, 0, addr, &v);
  764                         ERR_OUT(ret);
  765                         sc->cardinfo.f[fn].max_blksize = v;
  766                         ret = sdio_read_direct_sc(sc, 0, addr+1, &v);
  767                         ERR_OUT(ret);
  768                         sc->cardinfo.f[fn].max_blksize |= (v << 8);
  769                         break;
  770                 default:
  771                         CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_PERIPH,
  772                             ("%s: Skipping fn %d tuple %d ID %#02x "
  773                             "len %#02x\n", __func__, fn, tuple_count,
  774                             tuple_id, tuple_len));
  775                 }
  776                 if (tuple_len == 0xff) {
  777                         /* Also marks the end of a tuple chain (E1 16.2) */
  778                         /* The tuple is valid, hence this going at the end. */
  779                         break;
  780                 }
  781                 cis_addr += 2 + tuple_len;
  782                 tuple_count++;
  783         } while (tuple_count < 20);
  784 err:
  785 #undef ERR_OUT
  786         return (ret);
  787 }
  788 
  789 static int
  790 sdio_get_common_cis_addr(struct sdiob_softc *sc, uint32_t *addr)
  791 {
  792         int error;
  793         uint32_t a;
  794         uint8_t val;
  795 
  796         error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CISPTR + 0, &val);
  797         if (error != 0)
  798                 goto err;
  799         a = val;
  800         error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CISPTR + 1, &val);
  801         if (error != 0)
  802                 goto err;
  803         a |= (val << 8);
  804         error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CISPTR + 2, &val);
  805         if (error != 0)
  806                 goto err;
  807         a |= (val << 16);
  808 
  809         if (a < SD_IO_CIS_START || a > SD_IO_CIS_START + SD_IO_CIS_SIZE) {
  810 err:
  811                 CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_PERIPH,
  812                     ("%s: bad CIS address: %#04x, error %d\n", __func__, a,
  813                     error));
  814         } else if (error == 0 && addr != NULL)
  815                 *addr = a;
  816 
  817         return (error);
  818 }
  819 
  820 static int
  821 sdiob_get_card_info(struct sdiob_softc *sc)
  822 {
  823         struct mmc_params *mmcp;
  824         uint32_t cis_addr, fbr_addr;
  825         int fn, error;
  826         uint8_t fn_max, val;
  827 
  828         error = sdio_get_common_cis_addr(sc, &cis_addr);
  829         if (error != 0)
  830                 return (-1);
  831 
  832         memset(&sc->cardinfo, 0, sizeof(sc->cardinfo));
  833 
  834         /* F0 must always be present. */
  835         fn = 0;
  836         error = sdio_func_read_cis(sc, fn, cis_addr);
  837         if (error != 0)
  838                 return (error);
  839         sc->cardinfo.num_funcs++;
  840         /* Read CCCR Card Capability. */
  841         error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CARDCAP, &val);
  842         if (error != 0)
  843                 return (error);
  844         sc->cardinfo.support_multiblk = (val & CCCR_CC_SMB) ? true : false;
  845         DPRINTF("%s: F%d: Vendor %#04x product %#04x max block size %d bytes "
  846             "support_multiblk %s\n",
  847             __func__, fn, sc->cardinfo.f[fn].vendor, sc->cardinfo.f[fn].device,
  848             sc->cardinfo.f[fn].max_blksize,
  849             sc->cardinfo.support_multiblk ? "yes" : "no");
  850 
  851         /* mmcp->sdio_func_count contains the number of functions w/o F0. */
  852         mmcp = &sc->ccb->ccb_h.path->device->mmc_ident_data;
  853         fn_max = MIN(mmcp->sdio_func_count + 1, nitems(sc->cardinfo.f));
  854         for (fn = 1; fn < fn_max; fn++) {
  855                 fbr_addr = SD_IO_FBR_START * fn + SD_IO_FBR_CIS_OFFSET;
  856 
  857                 error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val);
  858                 if (error != 0)
  859                         break;
  860                 cis_addr = val;
  861                 error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val);
  862                 if (error != 0)
  863                         break;
  864                 cis_addr |= (val << 8);
  865                 error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val);
  866                 if (error != 0)
  867                         break;
  868                 cis_addr |= (val << 16);
  869 
  870                 error = sdio_func_read_cis(sc, fn, cis_addr);
  871                 if (error != 0)
  872                         break;
  873 
  874                 /* Read the Standard SDIO Function Interface Code. */
  875                 fbr_addr = SD_IO_FBR_START * fn;
  876                 error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val);
  877                 if (error != 0)
  878                         break;
  879                 sc->cardinfo.f[fn].class = (val & 0x0f);
  880                 if (sc->cardinfo.f[fn].class == 0x0f) {
  881                         error = sdio_read_direct_sc(sc, 0, fbr_addr, &val);
  882                         if (error != 0)
  883                                 break;
  884                         sc->cardinfo.f[fn].class = val;
  885                 }
  886 
  887                 sc->cardinfo.f[fn].fn = fn;
  888                 sc->cardinfo.f[fn].cur_blksize = sc->cardinfo.f[fn].max_blksize;
  889                 sc->cardinfo.f[fn].retries = 0;
  890                 sc->cardinfo.f[fn].timeout = 5000;
  891 
  892                 DPRINTF("%s: F%d: Class %d Vendor %#04x product %#04x "
  893                     "max_blksize %d bytes\n", __func__, fn,
  894                     sc->cardinfo.f[fn].class,
  895                     sc->cardinfo.f[fn].vendor, sc->cardinfo.f[fn].device,
  896                     sc->cardinfo.f[fn].max_blksize);
  897                 if (sc->cardinfo.f[fn].vendor == 0) {
  898                         DPRINTF("%s: F%d doesn't exist\n", __func__, fn);
  899                         break;
  900                 }
  901                 sc->cardinfo.num_funcs++;
  902         }
  903         return (error);
  904 }
  905 
  906 /* -------------------------------------------------------------------------- */
  907 /*
  908  * CAM periph registration, allocation, and detached from that a discovery
  909  * task, which goes off reads cardinfo, and then adds ourselves to our SIM's
  910  * device adding the devclass and registering the driver.  This keeps the
  911  * newbus chain connected though we will talk CAM in the middle (until one
  912  * day CAM might be newbusyfied).
  913  */
  914 
  915 static int
  916 sdio_newbus_sim_add(struct sdiob_softc *sc)
  917 {
  918         device_t pdev;
  919         devclass_t bus_devclass;
  920         int error;
  921 
  922         /* Add ourselves to our parent (SIM) device. */
  923 
  924         /* Add ourselves to our parent. That way we can become a parent. */
  925         pdev = xpt_path_sim_device(sc->periph->path);
  926         KASSERT(pdev != NULL,
  927             ("%s: pdev is NULL, sc %p periph %p sim %p\n",
  928             __func__, sc, sc->periph, sc->periph->sim));
  929 
  930         if (sc->dev == NULL)
  931                 sc->dev = BUS_ADD_CHILD(pdev, 0, SDIOB_NAME_S, -1);
  932         if (sc->dev == NULL)
  933                 return (ENXIO);
  934         device_set_softc(sc->dev, sc);
  935 
  936         /*
  937          * Don't set description here; devclass_add_driver() ->
  938          * device_probe_child() -> device_set_driver() will nuke it again.
  939          */
  940         bus_devclass = device_get_devclass(pdev);
  941         if (bus_devclass == NULL) {
  942                 printf("%s: Failed to get devclass from %s.\n", __func__,
  943                     device_get_nameunit(pdev));
  944                 return (ENXIO);
  945         }
  946 
  947         bus_topo_lock();
  948         error = devclass_add_driver(bus_devclass, &sdiob_driver,
  949             BUS_PASS_DEFAULT, NULL);
  950         bus_topo_unlock();
  951         if (error != 0) {
  952                 printf("%s: Failed to add driver to devclass: %d.\n",
  953                     __func__, error);
  954                 return (error);
  955         }
  956 
  957         /* Done. */
  958         sc->nb_state = NB_STATE_SIM_ADDED;
  959 
  960         return (0);
  961 }
  962 
  963 static void
  964 sdiobdiscover(void *context, int pending)
  965 {
  966         struct cam_periph *periph;
  967         struct sdiob_softc *sc;
  968         int error;
  969 
  970         KASSERT(context != NULL, ("%s: context is NULL\n", __func__));
  971         periph = (struct cam_periph *)context;
  972         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s\n", __func__));
  973 
  974         /* Periph was held for us when this task was enqueued. */
  975         if ((periph->flags & CAM_PERIPH_INVALID) != 0) {
  976                 cam_periph_release(periph);
  977                 return;
  978         }
  979 
  980         sc = periph->softc;
  981         sc->sdio_state = SDIO_STATE_INITIALIZING;
  982 
  983         if (sc->ccb == NULL)
  984                 sc->ccb = xpt_alloc_ccb();
  985         else
  986                 memset(sc->ccb, 0, sizeof(*sc->ccb));
  987         xpt_setup_ccb(&sc->ccb->ccb_h, periph->path, CAM_PRIORITY_NONE);
  988 
  989         /*
  990          * Read CCCR and FBR of each function, get manufacturer and device IDs,
  991          * max block size, and whatever else we deem necessary.
  992          */
  993         cam_periph_lock(periph);
  994         error = sdiob_get_card_info(sc);
  995         if  (error == 0)
  996                 sc->sdio_state = SDIO_STATE_READY;
  997         else
  998                 sc->sdio_state = SDIO_STATE_DEAD;
  999         cam_periph_unlock(periph);
 1000 
 1001         if (error)
 1002                 return;
 1003 
 1004         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s: num_func %d\n",
 1005             __func__, sc->cardinfo.num_funcs));
 1006 
 1007         /*
 1008          * Now CAM portion of the driver has been initialized and
 1009          * we know VID/PID of all the functions on the card.
 1010          * Time to hook into the newbus.
 1011          */
 1012         error = sdio_newbus_sim_add(sc);
 1013         if (error != 0)
 1014                 sc->nb_state = NB_STATE_DEAD;
 1015 
 1016         return;
 1017 }
 1018 
 1019 /* Called at the end of cam_periph_alloc() for us to finish allocation. */
 1020 static cam_status
 1021 sdiobregister(struct cam_periph *periph, void *arg)
 1022 {
 1023         struct sdiob_softc *sc;
 1024         int error;
 1025 
 1026         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s: arg %p\n", __func__, arg));
 1027         if (arg == NULL) {
 1028                 printf("%s: no getdev CCB, can't register device pariph %p\n",
 1029                     __func__, periph);
 1030                 return(CAM_REQ_CMP_ERR);
 1031         }
 1032         if (xpt_path_sim_device(periph->path) == NULL) {
 1033                 printf("%s: no device_t for sim %p\n", __func__, periph->sim);
 1034                 return(CAM_REQ_CMP_ERR);
 1035         }
 1036 
 1037         sc = (struct sdiob_softc *) malloc(sizeof(*sc), M_DEVBUF,
 1038             M_NOWAIT|M_ZERO);
 1039         if (sc == NULL) {
 1040                 printf("%s: unable to allocate sc\n", __func__);
 1041                 return (CAM_REQ_CMP_ERR);
 1042         }
 1043         sc->sdio_state = SDIO_STATE_DEAD;
 1044         sc->nb_state = NB_STATE_DEAD;
 1045         TASK_INIT(&sc->discover_task, 0, sdiobdiscover, periph);
 1046 
 1047         /* Refcount until we are setup.  Can't block. */
 1048         error = cam_periph_hold(periph, PRIBIO);
 1049         if (error != 0) {
 1050                 printf("%s: lost periph during registration!\n", __func__);
 1051                 free(sc, M_DEVBUF);
 1052                 return(CAM_REQ_CMP_ERR);
 1053         }
 1054         periph->softc = sc;
 1055         sc->periph = periph;
 1056         cam_periph_unlock(periph);
 1057 
 1058         error = taskqueue_enqueue(taskqueue_thread, &sc->discover_task);
 1059 
 1060         cam_periph_lock(periph);
 1061         /* We will continue to hold a refcount for discover_task. */
 1062         /* cam_periph_unhold(periph); */
 1063 
 1064         xpt_schedule(periph, CAM_PRIORITY_XPT);
 1065 
 1066         return (CAM_REQ_CMP);
 1067 }
 1068 
 1069 static void
 1070 sdioboninvalidate(struct cam_periph *periph)
 1071 {
 1072 
 1073         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s:\n", __func__));
 1074 
 1075         return;
 1076 }
 1077 
 1078 static void
 1079 sdiobcleanup(struct cam_periph *periph)
 1080 {
 1081 
 1082         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s:\n", __func__));
 1083 
 1084         return;
 1085 }
 1086 
 1087 static void
 1088 sdiobstart(struct cam_periph *periph, union ccb *ccb)
 1089 {
 1090 
 1091         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s: ccb %p\n", __func__, ccb));
 1092 
 1093         return;
 1094 }
 1095 
 1096 static void
 1097 sdiobasync(void *softc, uint32_t code, struct cam_path *path, void *arg)
 1098 {
 1099         struct cam_periph *periph;
 1100         struct ccb_getdev *cgd;
 1101         cam_status status;
 1102 
 1103         periph = (struct cam_periph *)softc;
 1104 
 1105         CAM_DEBUG(path, CAM_DEBUG_TRACE, ("%s(code=%d)\n", __func__, code));
 1106         switch (code) {
 1107         case AC_FOUND_DEVICE:
 1108                 if (arg == NULL)
 1109                         break;
 1110                 cgd = (struct ccb_getdev *)arg;
 1111                 if (cgd->protocol != PROTO_MMCSD)
 1112                         break;
 1113 
 1114                 /* We do not support SD memory (Combo) Cards. */
 1115                 if ((path->device->mmc_ident_data.card_features &
 1116                     CARD_FEATURE_MEMORY)) {
 1117                         CAM_DEBUG(path, CAM_DEBUG_TRACE,
 1118                              ("Memory card, not interested\n"));
 1119                         break;
 1120                 }
 1121 
 1122                 /*
 1123                  * Allocate a peripheral instance for this device which starts
 1124                  * the probe process.
 1125                  */
 1126                 status = cam_periph_alloc(sdiobregister, sdioboninvalidate,
 1127                     sdiobcleanup, sdiobstart, SDIOB_NAME_S, CAM_PERIPH_BIO, path,
 1128                     sdiobasync, AC_FOUND_DEVICE, cgd);
 1129                 if (status != CAM_REQ_CMP && status != CAM_REQ_INPROG)
 1130                         CAM_DEBUG(path, CAM_DEBUG_PERIPH,
 1131                              ("%s: Unable to attach to new device due to "
 1132                              "status %#02x\n", __func__, status));
 1133                 break;
 1134         default:
 1135                 CAM_DEBUG(path, CAM_DEBUG_PERIPH,
 1136                      ("%s: cannot handle async code %#02x\n", __func__, code));
 1137                 cam_periph_async(periph, code, path, arg);
 1138                 break;
 1139         }
 1140 }
 1141 
 1142 static void
 1143 sdiobinit(void)
 1144 {
 1145         cam_status status;
 1146 
 1147         /*
 1148          * Register for new device notification.  We will be notified for all
 1149          * already existing ones.
 1150          */
 1151         status = xpt_register_async(AC_FOUND_DEVICE, sdiobasync, NULL, NULL);
 1152         if (status != CAM_REQ_CMP)
 1153                 printf("%s: Failed to attach async callback, statux %#02x",
 1154                     __func__, status);
 1155 }
 1156 
 1157 /* This function will allow unloading the KLD. */
 1158 static int
 1159 sdiobdeinit(void)
 1160 {
 1161 
 1162         return (EOPNOTSUPP);
 1163 }
 1164 
 1165 static struct periph_driver sdiobdriver =
 1166 {
 1167         .init =         sdiobinit,
 1168         .driver_name =  SDIOB_NAME_S,
 1169         .units =        TAILQ_HEAD_INITIALIZER(sdiobdriver.units),
 1170         .generation =   0,
 1171         .flags =        0,
 1172         .deinit =       sdiobdeinit,
 1173 };
 1174 
 1175 PERIPHDRIVER_DECLARE(SDIOB_NAME, sdiobdriver);
 1176 MODULE_VERSION(SDIOB_NAME, 1);

Cache object: 56cb3ce58bd8458c32997ace3df4068f


[ 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.