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/ow/ow.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) 2015 M. Warner Losh <imp@FreeBSD.org>
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice unmodified, this list of conditions, and the following
    9  *    disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24  */
   25 
   26 #include <sys/cdefs.h>
   27 __FBSDID("$FreeBSD$");
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/kernel.h>
   32 
   33 #include <sys/bus.h>
   34 #include <sys/errno.h>
   35 #include <sys/libkern.h>
   36 #include <sys/lock.h>
   37 #include <sys/malloc.h>
   38 #include <sys/module.h>
   39 #include <sys/mutex.h>
   40 #include <sys/sbuf.h>
   41 #include <sys/sysctl.h>
   42 
   43 #include <dev/ow/ow.h>
   44 #include <dev/ow/owll.h>
   45 #include <dev/ow/own.h>
   46 
   47 /*
   48  * lldev - link level device
   49  * ndev - network / transport device (this module)
   50  * pdev - presentation device (children of this module)
   51  */
   52 
   53 typedef int ow_enum_fn(device_t, device_t);
   54 typedef int ow_found_fn(device_t, romid_t);
   55 
   56 struct ow_softc
   57 {
   58         device_t        dev;            /* Newbus driver back pointer */
   59         struct mtx      mtx;            /* bus mutex */
   60         device_t        owner;          /* bus owner, if != NULL */
   61 };
   62 
   63 struct ow_devinfo
   64 {
   65         romid_t romid;
   66 };
   67 
   68 static int ow_acquire_bus(device_t ndev, device_t pdev, int how);
   69 static void ow_release_bus(device_t ndev, device_t pdev);
   70 
   71 #define OW_LOCK(_sc) mtx_lock(&(_sc)->mtx)
   72 #define OW_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
   73 #define OW_LOCK_DESTROY(_sc) mtx_destroy(&_sc->mtx)
   74 #define OW_ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED)
   75 #define OW_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->mtx, MA_NOTOWNED)
   76 
   77 static MALLOC_DEFINE(M_OW, "ow", "House keeping data for 1wire bus");
   78 
   79 static const struct ow_timing timing_regular_min = {
   80         .t_slot = 60,
   81         .t_low0 = 60,
   82         .t_low1 = 1,
   83         .t_release = 0,
   84         .t_rec = 1,
   85         .t_rdv = 15,            /* fixed */
   86         .t_rstl = 480,
   87         .t_rsth = 480,
   88         .t_pdl = 60,
   89         .t_pdh = 15,
   90         .t_lowr = 1,
   91 };
   92 
   93 static const struct ow_timing timing_regular_max = {
   94         .t_slot = 120,
   95         .t_low0 = 120,
   96         .t_low1 = 15,
   97         .t_release = 45,
   98         .t_rec = 960,           /* infinity */
   99         .t_rdv = 15,            /* fixed */
  100         .t_rstl = 960,          /* infinity */
  101         .t_rsth = 960,          /* infinity */
  102         .t_pdl = 240,           /* 60us to 240us */
  103         .t_pdh = 60,            /* 15us to 60us */
  104         .t_lowr = 15,           /* 1us */
  105 };
  106 
  107 static struct ow_timing timing_regular = {
  108         .t_slot = 60,           /*  60 <= t < 120 */
  109         .t_low0 = 60,           /*  60 <= t < t_slot < 120 */
  110         .t_low1 = 1,            /*   1 <= t < 15 */
  111         .t_release = 45,        /*   0 <= t < 45 */
  112         .t_rec = 15,            /*   1 <= t < inf */
  113         .t_rdv = 15,            /* t == 15 */
  114         .t_rstl = 480,          /* 480 <= t < inf */
  115         .t_rsth = 480,          /* 480 <= t < inf */
  116         .t_pdl = 60,            /*  60 <= t < 240 */
  117         .t_pdh = 60,            /*  15 <= t < 60 */
  118         .t_lowr = 1,            /*   1 <= t < 15 */
  119 };
  120 
  121 /* NB: Untested */
  122 static const struct ow_timing timing_overdrive_min = {
  123         .t_slot = 6,
  124         .t_low0 = 6,
  125         .t_low1 = 1,
  126         .t_release = 0,
  127         .t_rec = 1,
  128         .t_rdv = 2,             /* fixed */
  129         .t_rstl = 48,
  130         .t_rsth = 48,
  131         .t_pdl = 8,
  132         .t_pdh = 2,
  133         .t_lowr = 1,
  134 };
  135 
  136 static const struct ow_timing timing_overdrive_max = {
  137         .t_slot = 16,
  138         .t_low0 = 16,
  139         .t_low1 = 2,
  140         .t_release = 4,
  141         .t_rec = 960,           /* infinity */
  142         .t_rdv = 2,             /* fixed */
  143         .t_rstl = 80,
  144         .t_rsth = 960,          /* infinity */
  145         .t_pdl = 24,
  146         .t_pdh = 6,
  147         .t_lowr = 2,
  148 };
  149 
  150 static struct ow_timing timing_overdrive = {
  151         .t_slot = 11,           /* 6 <= t < 16 */
  152         .t_low0 = 6,            /* 6 <= t < t_slot < 16 */
  153         .t_low1 = 1,            /* 1 <= t < 2 */
  154         .t_release = 4,         /* 0 <= t < 4 */
  155         .t_rec = 1,             /* 1 <= t < inf */
  156         .t_rdv = 2,             /* t == 2 */
  157         .t_rstl = 48,           /* 48 <= t < 80 */
  158         .t_rsth = 48,           /* 48 <= t < inf */
  159         .t_pdl = 8,             /* 8 <= t < 24 */
  160         .t_pdh = 2,             /* 2 <= t < 6 */
  161         .t_lowr = 1,            /* 1 <= t < 2 */
  162 };
  163 
  164 SYSCTL_NODE(_hw, OID_AUTO, ow, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  165     "1-Wire protocol");
  166 SYSCTL_NODE(_hw_ow, OID_AUTO, regular, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  167     "Regular mode timings");
  168 SYSCTL_NODE(_hw_ow, OID_AUTO, overdrive, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  169     "Overdrive mode timings");
  170 
  171 #define _OW_TIMING_SYSCTL(mode, param)          \
  172     static int \
  173     sysctl_ow_timing_ ## mode ## _ ## param(SYSCTL_HANDLER_ARGS) \
  174     { \
  175             int val = timing_ ## mode.param; \
  176             int err; \
  177             err = sysctl_handle_int(oidp, &val, 0, req); \
  178             if (err != 0 || req->newptr == NULL) \
  179                 return (err); \
  180             if (val < timing_ ## mode ## _min.param) \
  181                 return (EINVAL); \
  182             else if (val >= timing_ ## mode ## _max.param) \
  183                 return (EINVAL); \
  184             timing_ ## mode.param = val; \
  185             return (0); \
  186     } \
  187 SYSCTL_PROC(_hw_ow_ ## mode, OID_AUTO, param, \
  188     CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int), \
  189     sysctl_ow_timing_ ## mode ## _ ## param, "I", \
  190     "1-Wire timing parameter in microseconds (-1 resets to default)")
  191 
  192 #define OW_TIMING_SYSCTL(param) \
  193     _OW_TIMING_SYSCTL(regular, param); \
  194     _OW_TIMING_SYSCTL(overdrive, param)
  195 
  196 OW_TIMING_SYSCTL(t_slot);
  197 OW_TIMING_SYSCTL(t_low0);
  198 OW_TIMING_SYSCTL(t_low1);
  199 OW_TIMING_SYSCTL(t_release);
  200 OW_TIMING_SYSCTL(t_rec);
  201 OW_TIMING_SYSCTL(t_rdv);
  202 OW_TIMING_SYSCTL(t_rstl);
  203 OW_TIMING_SYSCTL(t_rsth);
  204 OW_TIMING_SYSCTL(t_pdl);
  205 OW_TIMING_SYSCTL(t_pdh);
  206 OW_TIMING_SYSCTL(t_lowr);
  207 
  208 #undef _OW_TIMING_SYSCTL
  209 #undef OW_TIMING_SYSCTL
  210 
  211 static void
  212 ow_send_byte(device_t lldev, struct ow_timing *t, uint8_t byte)
  213 {
  214         int i;
  215 
  216         for (i = 0; i < 8; i++)
  217                 if (byte & (1 << i))
  218                         OWLL_WRITE_ONE(lldev, t);
  219                 else
  220                         OWLL_WRITE_ZERO(lldev, t);
  221 }
  222 
  223 static void
  224 ow_read_byte(device_t lldev, struct ow_timing *t, uint8_t *bytep)
  225 {
  226         int i;
  227         uint8_t byte = 0;
  228         int bit;
  229 
  230         for (i = 0; i < 8; i++) {
  231                 OWLL_READ_DATA(lldev, t, &bit);
  232                 byte |= bit << i;
  233         }
  234         *bytep = byte;
  235 }
  236 
  237 static int
  238 ow_send_command(device_t ndev, device_t pdev, struct ow_cmd *cmd)
  239 {
  240         int present, i, bit, tries;
  241         device_t lldev;
  242         struct ow_timing *t;
  243 
  244         lldev = device_get_parent(ndev);
  245 
  246         /*
  247          * Retry the reset a couple of times before giving up.
  248          */
  249         tries = 4;
  250         do {
  251                 OWLL_RESET_AND_PRESENCE(lldev, &timing_regular, &present);
  252                 if (present == 1)
  253                         device_printf(ndev, "Reset said no device on bus?.\n");
  254         } while (present == 1 && tries-- > 0);
  255         if (present == 1) {
  256                 device_printf(ndev, "Reset said the device wasn't there.\n");
  257                 return ENOENT;          /* No devices acked the RESET */
  258         }
  259         if (present == -1) {
  260                 device_printf(ndev, "Reset discovered bus wired wrong.\n");
  261                 return ENOENT;
  262         }
  263 
  264         for (i = 0; i < cmd->rom_len; i++)
  265                 ow_send_byte(lldev, &timing_regular, cmd->rom_cmd[i]);
  266         for (i = 0; i < cmd->rom_read_len; i++)
  267                 ow_read_byte(lldev, &timing_regular, cmd->rom_read + i);
  268         if (cmd->xpt_len) {
  269                 /*
  270                  * Per AN937, the reset pulse and ROM level are always
  271                  * done with the regular timings. Certain ROM commands
  272                  * put the device into overdrive mode for the remainder
  273                  * of the data transfer, which is why we have to pass the
  274                  * timings here. Commands that need to be handled like this
  275                  * are expected to be flagged by the client.
  276                  */
  277                 t = (cmd->flags & OW_FLAG_OVERDRIVE) ?
  278                     &timing_overdrive : &timing_regular;
  279                 for (i = 0; i < cmd->xpt_len; i++)
  280                         ow_send_byte(lldev, t, cmd->xpt_cmd[i]);
  281                 if (cmd->flags & OW_FLAG_READ_BIT) {
  282                         memset(cmd->xpt_read, 0, (cmd->xpt_read_len + 7) / 8);
  283                         for (i = 0; i < cmd->xpt_read_len; i++) {
  284                                 OWLL_READ_DATA(lldev, t, &bit);
  285                                 cmd->xpt_read[i / 8] |= bit << (i % 8);
  286                         }
  287                 } else {
  288                         for (i = 0; i < cmd->xpt_read_len; i++)
  289                                 ow_read_byte(lldev, t, cmd->xpt_read + i);
  290                 }
  291         }
  292         return 0;
  293 }
  294 
  295 static int
  296 ow_search_rom(device_t lldev, device_t dev)
  297 {
  298         struct ow_cmd cmd;
  299 
  300         memset(&cmd, 0, sizeof(cmd));
  301         cmd.rom_cmd[0] = SEARCH_ROM;
  302         cmd.rom_len = 1;
  303         return ow_send_command(lldev, dev, &cmd);
  304 }
  305 
  306 #if 0
  307 static int
  308 ow_alarm_search(device_t lldev, device_t dev)
  309 {
  310         struct ow_cmd cmd;
  311 
  312         memset(&cmd, 0, sizeof(cmd));
  313         cmd.rom_cmd[0] = ALARM_SEARCH;
  314         cmd.rom_len = 1;
  315         return ow_send_command(lldev, dev, &cmd);
  316 }
  317 #endif
  318 
  319 static int
  320 ow_add_child(device_t dev, romid_t romid)
  321 {
  322         struct ow_devinfo *di;
  323         device_t child;
  324 
  325         di = malloc(sizeof(*di), M_OW, M_WAITOK);
  326         di->romid = romid;
  327         child = device_add_child(dev, NULL, -1);
  328         if (child == NULL) {
  329                 free(di, M_OW);
  330                 return ENOMEM;
  331         }
  332         device_set_ivars(child, di);
  333         return (0);
  334 }
  335 
  336 static device_t
  337 ow_child_by_romid(device_t dev, romid_t romid)
  338 {
  339         device_t *children, retval, child;
  340         int nkid, i;
  341         struct ow_devinfo *di;
  342 
  343         if (device_get_children(dev, &children, &nkid) != 0)
  344                 return (NULL);
  345         retval = NULL;
  346         for (i = 0; i < nkid; i++) {
  347                 child = children[i];
  348                 di = device_get_ivars(child);
  349                 if (di->romid == romid) {
  350                         retval = child;
  351                         break;
  352                 }
  353         }
  354         free(children, M_TEMP);
  355 
  356         return (retval);
  357 }
  358 
  359 /*
  360  * CRC generator table -- taken from AN937 DOW CRC LOOKUP FUNCTION Table 2
  361  */
  362 const uint8_t ow_crc_table[] = {
  363         0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
  364         157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
  365         35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
  366         190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
  367         70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
  368         219, 133,103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
  369         101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
  370         248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
  371         140,210, 48, 110, 237, 179, 81, 15, 78, 16, 242,  172, 47, 113,147, 205,
  372         17, 79, 173, 243, 112, 46, 204, 146, 211,141, 111, 49, 178, 236, 14, 80,
  373         175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82,176, 238,
  374         50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
  375         202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
  376         87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
  377         233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
  378         116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
  379 };
  380 
  381 /*
  382  * Converted from DO_CRC page 131 ANN937
  383  */
  384 static uint8_t
  385 ow_crc(device_t ndev, device_t pdev, uint8_t *buffer, size_t len)
  386 {
  387         uint8_t crc = 0;
  388         int i;
  389 
  390         for (i = 0; i < len; i++)
  391                 crc = ow_crc_table[crc ^ buffer[i]];
  392         return crc;
  393 }
  394 
  395 static int
  396 ow_check_crc(romid_t romid)
  397 {
  398         return ow_crc(NULL, NULL, (uint8_t *)&romid, sizeof(romid)) == 0;
  399 }
  400 
  401 static int
  402 ow_device_found(device_t dev, romid_t romid)
  403 {
  404 
  405         /* XXX Move this up into enumerate? */
  406         /*
  407          * All valid ROM IDs have a valid CRC. Check that first.
  408          */
  409         if (!ow_check_crc(romid)) {
  410                 device_printf(dev, "Device romid %8D failed CRC.\n",
  411                     &romid, ":");
  412                 return EINVAL;
  413         }
  414 
  415         /*
  416          * If we've seen this child before, don't add a new one for it.
  417          */
  418         if (ow_child_by_romid(dev, romid) != NULL)
  419                 return 0;
  420 
  421         return ow_add_child(dev, romid);
  422 }
  423 
  424 static int
  425 ow_enumerate(device_t dev, ow_enum_fn *enumfp, ow_found_fn *foundfp)
  426 {
  427         device_t lldev = device_get_parent(dev);
  428         int first, second, i, dir, prior, last, err, retries;
  429         uint64_t probed, last_mask;
  430         int sanity = 10;
  431 
  432         prior = -1;
  433         last_mask = 0;
  434         retries = 0;
  435         last = -2;
  436         err = ow_acquire_bus(dev, dev, OWN_DONTWAIT);
  437         if (err != 0)
  438                 return err;
  439         while (last != -1) {
  440                 if (sanity-- < 0) {
  441                         printf("Reached the sanity limit\n");
  442                         return EIO;
  443                 }
  444 again:
  445                 probed = 0;
  446                 last = -1;
  447 
  448                 /*
  449                  * See AN397 section 5.II.C.3 for the algorithm (though a bit
  450                  * poorly stated). The search command forces each device to
  451                  * send ROM ID bits one at a time (first the bit, then the
  452                  * complement) the master (us) sends back a bit. If the
  453                  * device's bit doesn't match what we send back, that device
  454                  * stops sending bits back. So each time through we remember
  455                  * where we made the last decision (always 0). If there's a
  456                  * conflict there this time (and there will be in the absence
  457                  * of a hardware failure) we go with 1. This way, we prune the
  458                  * devices on the bus and wind up with a unique ROM. We know
  459                  * we're done when we detect no new conflicts. The same
  460                  * algorithm is used for devices in alarm state as well.
  461                  *
  462                  * In addition, experience has shown that sometimes devices
  463                  * stop responding in the middle of enumeration, so try this
  464                  * step again a few times when that happens. It is unclear if
  465                  * this is due to a nosiy electrical environment or some odd
  466                  * timing issue.
  467                  */
  468 
  469                 /*
  470                  * The enumeration command should be successfully sent, if not,
  471                  * we have big issues on the bus so punt. Lower layers report
  472                  * any unusual errors, so we don't need to here.
  473                  */
  474                 err = enumfp(dev, dev);
  475                 if (err != 0)
  476                         return (err);
  477 
  478                 for (i = 0; i < 64; i++) {
  479                         OWLL_READ_DATA(lldev, &timing_regular, &first);
  480                         OWLL_READ_DATA(lldev, &timing_regular, &second);
  481                         switch (first | second << 1) {
  482                         case 0: /* Conflict */
  483                                 if (i < prior)
  484                                         dir = (last_mask >> i) & 1;
  485                                 else
  486                                         dir = i == prior;
  487 
  488                                 if (dir == 0)
  489                                         last = i;
  490                                 break;
  491                         case 1: /* 1 then 0 -> 1 for all */
  492                                 dir = 1;
  493                                 break;
  494                         case 2: /* 0 then 1 -> 0 for all */
  495                                 dir = 0;
  496                                 break;
  497                         case 3:
  498                                 /*
  499                                  * No device responded. This is unexpected, but
  500                                  * experience has shown that on some platforms
  501                                  * we miss a timing window, or otherwise have
  502                                  * an issue. Start this step over. Since we've
  503                                  * not updated prior yet, we can just jump to
  504                                  * the top of the loop for a re-do of this step.
  505                                  */
  506                                 printf("oops, starting over\n");
  507                                 if (++retries > 5)
  508                                         return (EIO);
  509                                 goto again;
  510                         default: /* NOTREACHED */
  511                                 __assert_unreachable();
  512                         }
  513                         if (dir) {
  514                                 OWLL_WRITE_ONE(lldev, &timing_regular);
  515                                 probed |= 1ull << i;
  516                         } else {
  517                                 OWLL_WRITE_ZERO(lldev, &timing_regular);
  518                         }
  519                 }
  520                 retries = 0;
  521                 foundfp(dev, probed);
  522                 last_mask = probed;
  523                 prior = last;
  524         }
  525         ow_release_bus(dev, dev);
  526 
  527         return (0);
  528 }
  529 
  530 static int
  531 ow_probe(device_t dev)
  532 {
  533 
  534         device_set_desc(dev, "1 Wire Bus");
  535         return (BUS_PROBE_GENERIC);
  536 }
  537 
  538 static int
  539 ow_attach(device_t ndev)
  540 {
  541         struct ow_softc *sc;
  542 
  543         /*
  544          * Find all the devices on the bus. We don't probe / attach them in the
  545          * enumeration phase. We do this because we want to allow the probe /
  546          * attach routines of the child drivers to have as full an access to the
  547          * bus as possible. While we reset things before the next step of the
  548          * search (so it would likely be OK to allow access by the clients to
  549          * the bus), it is more conservative to find them all, then to do the
  550          * attach of the devices. This also allows the child devices to have
  551          * more knowledge of the bus. We also ignore errors from the enumeration
  552          * because they might happen after we've found a few devices.
  553          */
  554         sc = device_get_softc(ndev);
  555         sc->dev = ndev;
  556         mtx_init(&sc->mtx, device_get_nameunit(sc->dev), "ow", MTX_DEF);
  557         ow_enumerate(ndev, ow_search_rom, ow_device_found);
  558         return bus_generic_attach(ndev);
  559 }
  560 
  561 static int
  562 ow_detach(device_t ndev)
  563 {
  564         device_t *children, child;
  565         int nkid, i;
  566         struct ow_devinfo *di;
  567         struct ow_softc *sc;
  568 
  569         sc = device_get_softc(ndev);
  570         /*
  571          * detach all the children first. This is blocking until any threads
  572          * have stopped, etc.
  573          */
  574         bus_generic_detach(ndev);
  575 
  576         /*
  577          * We delete all the children, and free up the ivars 
  578          */
  579         if (device_get_children(ndev, &children, &nkid) != 0)
  580                 return ENOMEM;
  581         for (i = 0; i < nkid; i++) {
  582                 child = children[i];
  583                 di = device_get_ivars(child);
  584                 free(di, M_OW);
  585                 device_delete_child(ndev, child);
  586         }
  587         free(children, M_TEMP);
  588 
  589         OW_LOCK_DESTROY(sc);
  590         return 0;
  591 }
  592 
  593 static int
  594 ow_child_pnpinfo(device_t dev, device_t child, struct sbuf *sb)
  595 {
  596         struct ow_devinfo *di;
  597 
  598         di = device_get_ivars(child);
  599         sbuf_printf(sb, "romid=%8D", &di->romid, ":");
  600         return (0);
  601 }
  602 
  603 static int
  604 ow_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
  605 {
  606         struct ow_devinfo *di;
  607         romid_t **ptr;
  608 
  609         di = device_get_ivars(child);
  610         switch (which) {
  611         case OW_IVAR_FAMILY:
  612                 *result = di->romid & 0xff;
  613                 break;
  614         case OW_IVAR_ROMID:
  615                 ptr = (romid_t **)result;
  616                 *ptr = &di->romid;
  617                 break;
  618         default:
  619                 return EINVAL;
  620         }
  621 
  622         return 0;
  623 }
  624 
  625 static int
  626 ow_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
  627 {
  628 
  629         return EINVAL;
  630 }
  631 
  632 static int
  633 ow_print_child(device_t ndev, device_t pdev)
  634 {
  635         int retval = 0;
  636         struct ow_devinfo *di;
  637 
  638         di = device_get_ivars(pdev);
  639 
  640         retval += bus_print_child_header(ndev, pdev);
  641         retval += printf(" romid %8D", &di->romid, ":");
  642         retval += bus_print_child_footer(ndev, pdev);
  643 
  644         return retval;
  645 }
  646 
  647 static void
  648 ow_probe_nomatch(device_t ndev, device_t pdev)
  649 {
  650         struct ow_devinfo *di;
  651 
  652         di = device_get_ivars(pdev);
  653         device_printf(ndev, "romid %8D: no driver\n", &di->romid, ":");
  654 }
  655 
  656 static int
  657 ow_acquire_bus(device_t ndev, device_t pdev, int how)
  658 {
  659         struct ow_softc *sc;
  660 
  661         sc = device_get_softc(ndev);
  662         OW_ASSERT_UNLOCKED(sc);
  663         OW_LOCK(sc);
  664         if (sc->owner != NULL) {
  665                 if (sc->owner == pdev)
  666                         panic("%s: %s recursively acquiring the bus.\n",
  667                             device_get_nameunit(ndev),
  668                             device_get_nameunit(pdev));
  669                 if (how == OWN_DONTWAIT) {
  670                         OW_UNLOCK(sc);
  671                         return EWOULDBLOCK;
  672                 }
  673                 while (sc->owner != NULL)
  674                         mtx_sleep(sc, &sc->mtx, 0, "owbuswait", 0);
  675         }
  676         sc->owner = pdev;
  677         OW_UNLOCK(sc);
  678 
  679         return 0;
  680 }
  681 
  682 static void
  683 ow_release_bus(device_t ndev, device_t pdev)
  684 {
  685         struct ow_softc *sc;
  686 
  687         sc = device_get_softc(ndev);
  688         OW_ASSERT_UNLOCKED(sc);
  689         OW_LOCK(sc);
  690         if (sc->owner == NULL)
  691                 panic("%s: %s releasing unowned bus.", device_get_nameunit(ndev),
  692                     device_get_nameunit(pdev));
  693         if (sc->owner != pdev)
  694                 panic("%s: %s don't own the bus. %s does. game over.",
  695                     device_get_nameunit(ndev), device_get_nameunit(pdev),
  696                     device_get_nameunit(sc->owner));
  697         sc->owner = NULL;
  698         wakeup(sc);
  699         OW_UNLOCK(sc);
  700 }
  701 
  702 static device_method_t ow_methods[] = {
  703         /* Device interface */
  704         DEVMETHOD(device_probe,         ow_probe),
  705         DEVMETHOD(device_attach,        ow_attach),
  706         DEVMETHOD(device_detach,        ow_detach),
  707 
  708         /* Bus interface */
  709         DEVMETHOD(bus_child_pnpinfo,    ow_child_pnpinfo),
  710         DEVMETHOD(bus_read_ivar,        ow_read_ivar),
  711         DEVMETHOD(bus_write_ivar,       ow_write_ivar),
  712         DEVMETHOD(bus_print_child,      ow_print_child),
  713         DEVMETHOD(bus_probe_nomatch,    ow_probe_nomatch),
  714 
  715         /* One Wire Network/Transport layer interface */
  716         DEVMETHOD(own_send_command,     ow_send_command),
  717         DEVMETHOD(own_acquire_bus,      ow_acquire_bus),
  718         DEVMETHOD(own_release_bus,      ow_release_bus),
  719         DEVMETHOD(own_crc,              ow_crc),
  720         { 0, 0 }
  721 };
  722 
  723 static driver_t ow_driver = {
  724         "ow",
  725         ow_methods,
  726         sizeof(struct ow_softc),
  727 };
  728 
  729 DRIVER_MODULE(ow, owc, ow_driver, 0, 0);
  730 MODULE_VERSION(ow, 1);

Cache object: ac13bb1d83f9c2f4ca422b9f2f29afff


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