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/utopia/utopia.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) 2003
    3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
    4  *      All rights reserved.
    5  *
    6  * Author: Hartmut Brandt <harti@freebsd.org>
    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 AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: releng/9.0/sys/dev/utopia/utopia.c 174318 2007-12-05 19:32:59Z philip $");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/unistd.h>
   36 #include <sys/kernel.h>
   37 #include <sys/kthread.h>
   38 #include <sys/proc.h>
   39 #include <sys/bus.h>
   40 #include <sys/malloc.h>
   41 #include <sys/module.h>
   42 #include <sys/sysctl.h>
   43 #include <sys/lock.h>
   44 #include <sys/mutex.h>
   45 #include <sys/socket.h>
   46 
   47 #include <net/if.h>
   48 #include <net/if_var.h>
   49 #include <net/if_media.h>
   50 #include <net/if_atm.h>
   51 
   52 #include <dev/utopia/suni.h>
   53 #include <dev/utopia/idtphy.h>
   54 #include <dev/utopia/utopia.h>
   55 #include <dev/utopia/utopia_priv.h>
   56 
   57 /* known chips */
   58 extern const struct utopia_chip utopia_chip_idt77155;
   59 extern const struct utopia_chip utopia_chip_idt77105;
   60 extern const struct utopia_chip utopia_chip_lite;
   61 extern const struct utopia_chip utopia_chip_ultra;
   62 extern const struct utopia_chip utopia_chip_622;
   63 
   64 /*
   65  * Global list of all registered interfaces
   66  */
   67 static struct mtx utopia_list_mtx;
   68 static LIST_HEAD(, utopia) utopia_list = LIST_HEAD_INITIALIZER(utopia_list);
   69 
   70 #define UTP_RLOCK_LIST()        mtx_lock(&utopia_list_mtx)
   71 #define UTP_RUNLOCK_LIST()      mtx_unlock(&utopia_list_mtx)
   72 #define UTP_WLOCK_LIST()        mtx_lock(&utopia_list_mtx)
   73 #define UTP_WUNLOCK_LIST()      mtx_unlock(&utopia_list_mtx)
   74 
   75 #define UTP_LOCK(UTP)           mtx_lock((UTP)->lock)
   76 #define UTP_UNLOCK(UTP)         mtx_unlock((UTP)->lock)
   77 #define UTP_LOCK_ASSERT(UTP)    mtx_assert((UTP)->lock, MA_OWNED)
   78 
   79 static struct proc *utopia_kproc;
   80 
   81 static void utopia_dump(struct utopia *) __unused;
   82 
   83 /*
   84  * Read a multi-register value.
   85  */
   86 uint32_t
   87 utopia_update(struct utopia *utp, u_int reg, u_int nreg, uint32_t mask)
   88 {
   89         int err;
   90         u_int n;
   91         uint8_t regs[4];
   92         uint32_t val;
   93 
   94         n = nreg;
   95         if ((err = UTP_READREGS(utp, reg, regs, &n)) != 0) {
   96 #ifdef DIAGNOSTIC
   97                 printf("%s: register read error %s(%u,%u): %d\n", __func__,
   98                     utp->chip->name, reg, nreg, err);
   99 #endif
  100                 return (0);
  101         }
  102         if (n < nreg) {
  103 #ifdef DIAGNOSTIC
  104                 printf("%s: got only %u regs %s(%u,%u): %d\n", __func__, n,
  105                     utp->chip->name, reg, nreg, err);
  106 #endif
  107                 return (0);
  108         }
  109         val = 0;
  110         for (n = nreg; n > 0; n--) {
  111                 val <<= 8;
  112                 val |= regs[n - 1];
  113         }
  114         return (val & mask);
  115 }
  116 
  117 /*
  118  * Debugging - dump all registers.
  119  */
  120 static void
  121 utopia_dump(struct utopia *utp)
  122 {
  123         uint8_t regs[256];
  124         u_int n = 256, i;
  125         int err;
  126 
  127         if ((err = UTP_READREGS(utp, 0, regs, &n)) != 0) {
  128                 printf("UTOPIA reg read error %d\n", err);
  129                 return;
  130         }
  131         for (i = 0; i < n; i++) {
  132                 if (i % 16 == 0)
  133                         printf("%02x:", i);
  134                 if (i % 16 == 8)
  135                         printf(" ");
  136                 printf(" %02x", regs[i]);
  137                 if (i % 16 == 15)
  138                         printf("\n");
  139         }
  140         if (i % 16 != 0)
  141                 printf("\n");
  142 }
  143 
  144 /*
  145  * Update the carrier status
  146  */
  147 void
  148 utopia_check_carrier(struct utopia *utp, u_int carr_ok)
  149 {
  150         int old;
  151 
  152         old = utp->carrier;
  153         if (carr_ok) {
  154                 /* carrier */
  155                 utp->carrier = UTP_CARR_OK;
  156                 if (old != UTP_CARR_OK) {
  157                         if_printf(utp->ifatm->ifp, "carrier detected\n");
  158                         ATMEV_SEND_IFSTATE_CHANGED(utp->ifatm, 1);
  159                 }
  160         } else {
  161                 /* no carrier */
  162                 utp->carrier = UTP_CARR_LOST;
  163                 if (old == UTP_CARR_OK) {
  164                         if_printf(utp->ifatm->ifp, "carrier lost\n");
  165                         ATMEV_SEND_IFSTATE_CHANGED(utp->ifatm, 0);
  166                 }
  167         }
  168 }
  169 
  170 static int
  171 unknown_inval(struct utopia *utp, int what __unused)
  172 {
  173 
  174         return (EINVAL);
  175 }
  176 
  177 static int
  178 unknown_reset(struct utopia *utp __unused)
  179 {
  180         return (EIO);
  181 }
  182 
  183 static int
  184 unknown_update_carrier(struct utopia *utp)
  185 {
  186         utp->carrier = UTP_CARR_UNKNOWN;
  187         return (0);
  188 }
  189 
  190 static int
  191 unknown_set_loopback(struct utopia *utp __unused, u_int mode __unused)
  192 {
  193         return (EINVAL);
  194 }
  195 
  196 static void
  197 unknown_intr(struct utopia *utp __unused)
  198 {
  199 }
  200 
  201 static void
  202 unknown_update_stats(struct utopia *utp __unused)
  203 {
  204 }
  205 
  206 static const struct utopia_chip utopia_chip_unknown = {
  207         UTP_TYPE_UNKNOWN,
  208         "unknown",
  209         0,
  210         unknown_reset,
  211         unknown_inval,
  212         unknown_inval,
  213         unknown_inval,
  214         unknown_update_carrier,
  215         unknown_set_loopback,
  216         unknown_intr,
  217         unknown_update_stats,
  218 };
  219 
  220 /*
  221  * Callbacks for the ifmedia infrastructure.
  222  */
  223 static int
  224 utopia_media_change(struct ifnet *ifp)
  225 {
  226         struct ifatm *ifatm = IFP2IFATM(ifp);
  227         struct utopia *utp = ifatm->phy;
  228         int error = 0;
  229 
  230         UTP_LOCK(utp);
  231         if (utp->chip->type != UTP_TYPE_UNKNOWN && utp->state & UTP_ST_ACTIVE) {
  232                 if (utp->media->ifm_media & IFM_ATM_SDH) {
  233                         if (!(utp->state & UTP_ST_SDH))
  234                                 error = utopia_set_sdh(utp, 1);
  235                 } else {
  236                         if (utp->state & UTP_ST_SDH)
  237                                 error = utopia_set_sdh(utp, 0);
  238                 }
  239                 if (utp->media->ifm_media & IFM_ATM_UNASSIGNED) {
  240                         if (!(utp->state & UTP_ST_UNASS))
  241                                 error = utopia_set_unass(utp, 1);
  242                 } else {
  243                         if (utp->state & UTP_ST_UNASS)
  244                                 error = utopia_set_unass(utp, 0);
  245                 }
  246                 if (utp->media->ifm_media & IFM_ATM_NOSCRAMB) {
  247                         if (!(utp->state & UTP_ST_NOSCRAMB))
  248                                 error = utopia_set_noscramb(utp, 1);
  249                 } else {
  250                         if (utp->state & UTP_ST_NOSCRAMB)
  251                                 error = utopia_set_noscramb(utp, 0);
  252                 }
  253         } else
  254                 error = EIO;
  255         UTP_UNLOCK(utp);
  256         return (error);
  257 }
  258 
  259 /*
  260  * Look at the carrier status.
  261  */
  262 static void
  263 utopia_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
  264 {
  265         struct utopia *utp = IFP2IFATM(ifp)->phy;
  266 
  267         UTP_LOCK(utp);
  268         if (utp->chip->type != UTP_TYPE_UNKNOWN && utp->state & UTP_ST_ACTIVE) {
  269                 ifmr->ifm_active = IFM_ATM | utp->ifatm->mib.media;
  270 
  271                 switch (utp->carrier) {
  272 
  273                   case UTP_CARR_OK:
  274                         ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
  275                         break;
  276 
  277                   case UTP_CARR_LOST:
  278                         ifmr->ifm_status = IFM_AVALID;
  279                         break;
  280 
  281                   default:
  282                         ifmr->ifm_status = 0;
  283                         break;
  284                 }
  285                 if (utp->state & UTP_ST_SDH) {
  286                         ifmr->ifm_active |= IFM_ATM_SDH;
  287                         ifmr->ifm_current |= IFM_ATM_SDH;
  288                 }
  289                 if (utp->state & UTP_ST_UNASS) {
  290                         ifmr->ifm_active |= IFM_ATM_UNASSIGNED;
  291                         ifmr->ifm_current |= IFM_ATM_UNASSIGNED;
  292                 }
  293                 if (utp->state & UTP_ST_NOSCRAMB) {
  294                         ifmr->ifm_active |= IFM_ATM_NOSCRAMB;
  295                         ifmr->ifm_current |= IFM_ATM_NOSCRAMB;
  296                 }
  297         } else {
  298                 ifmr->ifm_active = 0;
  299                 ifmr->ifm_status = 0;
  300         }
  301         UTP_UNLOCK(utp);
  302 }
  303 
  304 /*
  305  * Initialize media from the mib
  306  */
  307 void
  308 utopia_init_media(struct utopia *utp)
  309 {
  310 
  311         ifmedia_removeall(utp->media);
  312         ifmedia_add(utp->media, IFM_ATM | utp->ifatm->mib.media, 0, NULL);
  313         ifmedia_set(utp->media, IFM_ATM | utp->ifatm->mib.media);
  314 }
  315 
  316 /*
  317  * Reset all media
  318  */
  319 void
  320 utopia_reset_media(struct utopia *utp)
  321 {
  322 
  323         ifmedia_removeall(utp->media);
  324 }
  325 
  326 /*
  327  * This is called by the driver as soon as the SUNI registers are accessible.
  328  * This may be either in the attach routine or the init routine of the driver.
  329  */
  330 int
  331 utopia_start(struct utopia *utp)
  332 {
  333         uint8_t reg;
  334         int err;
  335         u_int n = 1;
  336 
  337         /*
  338          * Try to find out what chip we have
  339          */
  340         if ((err = UTP_READREGS(utp, SUNI_REGO_MRESET, &reg, &n)) != 0)
  341                 return (err);
  342 
  343         switch (reg & SUNI_REGM_MRESET_TYPE) {
  344 
  345           case SUNI_REGM_MRESET_TYPE_622:
  346                 utp->chip = &utopia_chip_622;
  347                 break;
  348 
  349           case SUNI_REGM_MRESET_TYPE_LITE:
  350                 /* this may be either a SUNI LITE or a IDT77155 *
  351                  * Read register 0x70. The SUNI doesn't have it */
  352                 n = 1;
  353                 if ((err = UTP_READREGS(utp, IDTPHY_REGO_RBER, &reg, &n)) != 0)
  354                         return (err);
  355                 if ((reg & ~IDTPHY_REGM_RBER_RESV) ==
  356                     (IDTPHY_REGM_RBER_FAIL | IDTPHY_REGM_RBER_WARN))
  357                         utp->chip = &utopia_chip_idt77155;
  358                 else
  359                         utp->chip = &utopia_chip_lite;
  360                 break;
  361 
  362           case SUNI_REGM_MRESET_TYPE_ULTRA:
  363                 utp->chip = &utopia_chip_ultra;
  364                 break;
  365 
  366           default:
  367                 if (reg == (IDTPHY_REGM_MCR_DRIC | IDTPHY_REGM_MCR_EI))
  368                         utp->chip = &utopia_chip_idt77105;
  369                 else {
  370                         if_printf(utp->ifatm->ifp,
  371                             "unknown ATM-PHY chip %#x\n", reg);
  372                         utp->chip = &utopia_chip_unknown;
  373                 }
  374                 break;
  375         }
  376         utp->state |= UTP_ST_ACTIVE;
  377         return (0);
  378 }
  379 
  380 /*
  381  * Stop the chip
  382  */
  383 void
  384 utopia_stop(struct utopia *utp)
  385 {
  386         utp->state &= ~UTP_ST_ACTIVE;
  387 }
  388 
  389 /*
  390  * Handle the sysctls
  391  */
  392 static int
  393 utopia_sysctl_regs(SYSCTL_HANDLER_ARGS)
  394 {
  395         struct utopia *utp = (struct utopia *)arg1;
  396         int error;
  397         u_int n;
  398         uint8_t *val;
  399         uint8_t new[3];
  400 
  401         if ((n = utp->chip->nregs) == 0)
  402                 return (EIO);
  403         val = malloc(sizeof(uint8_t) * n, M_TEMP, M_WAITOK);
  404 
  405         UTP_LOCK(utp);
  406         error = UTP_READREGS(utp, 0, val, &n);
  407         UTP_UNLOCK(utp);
  408 
  409         if (error) {
  410                 free(val, M_TEMP);
  411                 return (error);
  412         }
  413 
  414         error = SYSCTL_OUT(req, val, sizeof(uint8_t) * n);
  415         free(val, M_TEMP);
  416         if (error != 0 || req->newptr == NULL)
  417                 return (error);
  418 
  419         error = SYSCTL_IN(req, new, sizeof(new));
  420         if (error)
  421                 return (error);
  422 
  423         UTP_LOCK(utp);
  424         error = UTP_WRITEREG(utp, new[0], new[1], new[2]);
  425         UTP_UNLOCK(utp);
  426 
  427         return (error);
  428 }
  429 
  430 static int
  431 utopia_sysctl_stats(SYSCTL_HANDLER_ARGS)
  432 {
  433         struct utopia *utp = (struct utopia *)arg1;
  434         void *val;
  435         int error;
  436 
  437         val = malloc(sizeof(utp->stats), M_TEMP, M_WAITOK);
  438 
  439         UTP_LOCK(utp);
  440         bcopy(&utp->stats, val, sizeof(utp->stats));
  441         if (req->newptr != NULL)
  442                 bzero((char *)&utp->stats + sizeof(utp->stats.version),
  443                     sizeof(utp->stats) - sizeof(utp->stats.version));
  444         UTP_UNLOCK(utp);
  445 
  446         error = SYSCTL_OUT(req, val, sizeof(utp->stats));
  447         if (error && req->newptr != NULL)
  448                 bcopy(val, &utp->stats, sizeof(utp->stats));
  449         free(val, M_TEMP);
  450 
  451         /* ignore actual new value */
  452 
  453         return (error);
  454 }
  455 
  456 /*
  457  * Handle the loopback sysctl
  458  */
  459 static int
  460 utopia_sysctl_loopback(SYSCTL_HANDLER_ARGS)
  461 {
  462         struct utopia *utp = (struct utopia *)arg1;
  463         int error;
  464         u_int loopback;
  465 
  466         error = SYSCTL_OUT(req, &utp->loopback, sizeof(u_int));
  467         if (error != 0 || req->newptr == NULL)
  468                 return (error);
  469 
  470         error = SYSCTL_IN(req, &loopback, sizeof(u_int));
  471         if (error)
  472                 return (error);
  473 
  474         UTP_LOCK(utp);
  475         error = utopia_set_loopback(utp, loopback);
  476         UTP_UNLOCK(utp);
  477 
  478         return (error);
  479 }
  480 
  481 /*
  482  * Handle the type sysctl
  483  */
  484 static int
  485 utopia_sysctl_type(SYSCTL_HANDLER_ARGS)
  486 {
  487         struct utopia *utp = (struct utopia *)arg1;
  488 
  489         return (SYSCTL_OUT(req, &utp->chip->type, sizeof(utp->chip->type)));
  490 }
  491 
  492 /*
  493  * Handle the name sysctl
  494  */
  495 static int
  496 utopia_sysctl_name(SYSCTL_HANDLER_ARGS)
  497 {
  498         struct utopia *utp = (struct utopia *)arg1;
  499 
  500         return (SYSCTL_OUT(req, utp->chip->name, strlen(utp->chip->name) + 1));
  501 }
  502 
  503 /*
  504  * Initialize the state. This is called from the drivers attach
  505  * function. The mutex must be already initialized.
  506  */
  507 int
  508 utopia_attach(struct utopia *utp, struct ifatm *ifatm, struct ifmedia *media,
  509     struct mtx *lock, struct sysctl_ctx_list *ctx,
  510     struct sysctl_oid_list *children, const struct utopia_methods *m)
  511 {
  512 
  513         bzero(utp, sizeof(*utp));
  514         utp->ifatm = ifatm;
  515         utp->methods = m;
  516         utp->media = media;
  517         utp->lock = lock;
  518         utp->chip = &utopia_chip_unknown;
  519         utp->stats.version = 1;
  520 
  521         ifmedia_init(media,
  522             IFM_ATM_SDH | IFM_ATM_UNASSIGNED | IFM_ATM_NOSCRAMB,
  523             utopia_media_change, utopia_media_status);
  524 
  525         if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_regs",
  526             CTLFLAG_RW | CTLTYPE_OPAQUE, utp, 0, utopia_sysctl_regs, "S",
  527             "phy registers") == NULL)
  528                 return (-1);
  529 
  530         if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_loopback",
  531             CTLFLAG_RW | CTLTYPE_UINT, utp, 0, utopia_sysctl_loopback, "IU",
  532             "phy loopback mode") == NULL)
  533                 return (-1);
  534 
  535         if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_type",
  536             CTLFLAG_RD | CTLTYPE_UINT, utp, 0, utopia_sysctl_type, "IU",
  537             "phy type") == NULL)
  538                 return (-1);
  539 
  540         if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_name",
  541             CTLFLAG_RD | CTLTYPE_STRING, utp, 0, utopia_sysctl_name, "A",
  542             "phy name") == NULL)
  543                 return (-1);
  544 
  545         if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_stats",
  546             CTLFLAG_RW | CTLTYPE_OPAQUE, utp, 0, utopia_sysctl_stats, "S",
  547             "phy statistics") == NULL)
  548                 return (-1);
  549 
  550         if (SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "phy_state",
  551             CTLFLAG_RD, &utp->state, 0, "phy state") == NULL)
  552                 return (-1);
  553 
  554         if (SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "phy_carrier",
  555             CTLFLAG_RD, &utp->carrier, 0, "phy carrier") == NULL)
  556                 return (-1);
  557 
  558         UTP_WLOCK_LIST();
  559         LIST_INSERT_HEAD(&utopia_list, utp, link);
  560         UTP_WUNLOCK_LIST();
  561 
  562         utp->state |= UTP_ST_ATTACHED;
  563         return (0);
  564 }
  565 
  566 /*
  567  * Detach. We set a flag here, wakeup the daemon and let him do it.
  568  * Here we need the lock for synchronisation with the daemon.
  569  */
  570 void
  571 utopia_detach(struct utopia *utp)
  572 {
  573 
  574         UTP_LOCK_ASSERT(utp);
  575         if (utp->state & UTP_ST_ATTACHED) {
  576                 utp->state |= UTP_ST_DETACH;
  577                 while (utp->state & UTP_ST_DETACH) {
  578                         wakeup(&utopia_list);
  579                         msleep(utp, utp->lock, PZERO, "utopia_detach", hz);
  580                 }
  581         }
  582 }
  583 
  584 /*
  585  * The carrier state kernel proc for those adapters that do not interrupt.
  586  *
  587  * We assume, that utopia_attach can safely add a new utopia while we are going
  588  * through the list without disturbing us (we lock the list while getting
  589  * the address of the first element, adding is always done at the head).
  590  * Removing is entirely handled here.
  591  */
  592 static void
  593 utopia_daemon(void *arg __unused)
  594 {
  595         struct utopia *utp, *next;
  596 
  597         UTP_RLOCK_LIST();
  598         while (utopia_kproc != NULL) {
  599                 utp = LIST_FIRST(&utopia_list);
  600                 UTP_RUNLOCK_LIST();
  601 
  602                 while (utp != NULL) {
  603                         mtx_lock(&Giant);       /* XXX depend on MPSAFE */
  604                         UTP_LOCK(utp);
  605                         next = LIST_NEXT(utp, link);
  606                         if (utp->state & UTP_ST_DETACH) {
  607                                 LIST_REMOVE(utp, link);
  608                                 utp->state &= ~UTP_ST_DETACH;
  609                                 wakeup_one(utp);
  610                         } else if (utp->state & UTP_ST_ACTIVE) {
  611                                 if (utp->flags & UTP_FL_POLL_CARRIER)
  612                                         utopia_update_carrier(utp);
  613                                 utopia_update_stats(utp);
  614                         }
  615                         UTP_UNLOCK(utp);
  616                         mtx_unlock(&Giant);     /* XXX depend on MPSAFE */
  617                         utp = next;
  618                 }
  619 
  620                 UTP_RLOCK_LIST();
  621                 msleep(&utopia_list, &utopia_list_mtx, PZERO, "*idle*", hz);
  622         }
  623         wakeup_one(&utopia_list);
  624         UTP_RUNLOCK_LIST();
  625         kproc_exit(0);
  626 }
  627 
  628 /*
  629  * Module initialisation
  630  */
  631 static int
  632 utopia_mod_init(module_t mod, int what, void *arg)
  633 {
  634         int err;
  635         struct proc *kp;
  636 
  637         switch (what) {
  638 
  639           case MOD_LOAD:
  640                 mtx_init(&utopia_list_mtx, "utopia list mutex", NULL, MTX_DEF);
  641                 err = kproc_create(utopia_daemon, NULL, &utopia_kproc,
  642                     RFHIGHPID, 0, "utopia");
  643                 if (err != 0) {
  644                         printf("cannot created utopia thread %d\n", err);
  645                         return (err);
  646                 }
  647                 break;
  648 
  649           case MOD_UNLOAD:
  650                 UTP_WLOCK_LIST();
  651                 if ((kp = utopia_kproc) != NULL) {
  652                         utopia_kproc = NULL;
  653                         wakeup_one(&utopia_list);
  654                         PROC_LOCK(kp);
  655                         UTP_WUNLOCK_LIST();
  656                         msleep(kp, &kp->p_mtx, PWAIT, "utopia_destroy", 0);
  657                         PROC_UNLOCK(kp);
  658                 } else
  659                         UTP_WUNLOCK_LIST();
  660                 mtx_destroy(&utopia_list_mtx);
  661                 break;
  662           default:
  663                 return (EOPNOTSUPP);
  664         }
  665         return (0);
  666 }
  667 
  668 static moduledata_t utopia_mod = {
  669         "utopia",
  670         utopia_mod_init,
  671         0
  672 };
  673                 
  674 DECLARE_MODULE(utopia, utopia_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
  675 MODULE_VERSION(utopia, 1);

Cache object: 989a53bdf857ff1efebac4e2747c59fb


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