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

Cache object: c22d60737131ba894e6f11e2cc637284


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