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/hotplug.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 /*      $OpenBSD: hotplug.c,v 1.22 2022/07/02 08:50:41 visa Exp $       */
    2 /*
    3  * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
    4  *
    5  * Permission to use, copy, modify, and distribute this software for any
    6  * purpose with or without fee is hereby granted, provided that the above
    7  * copyright notice and this permission notice appear in all copies.
    8  *
    9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   16  */
   17 
   18 /*
   19  * Device attachment and detachment notifications.
   20  */
   21 
   22 #include <sys/param.h>
   23 #include <sys/systm.h>
   24 #include <sys/device.h>
   25 #include <sys/fcntl.h>
   26 #include <sys/hotplug.h>
   27 #include <sys/ioctl.h>
   28 #include <sys/vnode.h>
   29 
   30 #define HOTPLUG_MAXEVENTS       64
   31 
   32 static int opened;
   33 static struct hotplug_event evqueue[HOTPLUG_MAXEVENTS];
   34 static int evqueue_head, evqueue_tail, evqueue_count;
   35 static struct selinfo hotplug_sel;
   36 
   37 void filt_hotplugrdetach(struct knote *);
   38 int  filt_hotplugread(struct knote *, long);
   39 
   40 const struct filterops hotplugread_filtops = {
   41         .f_flags        = FILTEROP_ISFD,
   42         .f_attach       = NULL,
   43         .f_detach       = filt_hotplugrdetach,
   44         .f_event        = filt_hotplugread,
   45 };
   46 
   47 #define EVQUEUE_NEXT(p) (p == HOTPLUG_MAXEVENTS - 1 ? 0 : p + 1)
   48 
   49 
   50 int hotplug_put_event(struct hotplug_event *);
   51 int hotplug_get_event(struct hotplug_event *);
   52 
   53 void hotplugattach(int);
   54 
   55 void
   56 hotplugattach(int count)
   57 {
   58         opened = 0;
   59         evqueue_head = 0;
   60         evqueue_tail = 0;
   61         evqueue_count = 0;
   62 }
   63 
   64 void
   65 hotplug_device_attach(enum devclass class, char *name)
   66 {
   67         struct hotplug_event he;
   68 
   69         he.he_type = HOTPLUG_DEVAT;
   70         he.he_devclass = class;
   71         strlcpy(he.he_devname, name, sizeof(he.he_devname));
   72         hotplug_put_event(&he);
   73 }
   74 
   75 void
   76 hotplug_device_detach(enum devclass class, char *name)
   77 {
   78         struct hotplug_event he;
   79 
   80         he.he_type = HOTPLUG_DEVDT;
   81         he.he_devclass = class;
   82         strlcpy(he.he_devname, name, sizeof(he.he_devname));
   83         hotplug_put_event(&he);
   84 }
   85 
   86 int
   87 hotplug_put_event(struct hotplug_event *he)
   88 {
   89         if (evqueue_count == HOTPLUG_MAXEVENTS && opened) {
   90                 printf("hotplug: event lost, queue full\n");
   91                 return (1);
   92         }
   93 
   94         evqueue[evqueue_head] = *he;
   95         evqueue_head = EVQUEUE_NEXT(evqueue_head);
   96         if (evqueue_count == HOTPLUG_MAXEVENTS)
   97                 evqueue_tail = EVQUEUE_NEXT(evqueue_tail);
   98         else 
   99                 evqueue_count++;
  100         wakeup(&evqueue);
  101         selwakeup(&hotplug_sel);
  102         return (0);
  103 }
  104 
  105 int
  106 hotplug_get_event(struct hotplug_event *he)
  107 {
  108         int s;
  109 
  110         if (evqueue_count == 0)
  111                 return (1);
  112 
  113         s = splbio();
  114         *he = evqueue[evqueue_tail];
  115         evqueue_tail = EVQUEUE_NEXT(evqueue_tail);
  116         evqueue_count--;
  117         splx(s);
  118         return (0);
  119 }
  120 
  121 int
  122 hotplugopen(dev_t dev, int flag, int mode, struct proc *p)
  123 {
  124         if (minor(dev) != 0)
  125                 return (ENXIO);
  126         if ((flag & FWRITE))
  127                 return (EPERM);
  128         if (opened)
  129                 return (EBUSY);
  130         opened = 1;
  131         return (0);
  132 }
  133 
  134 int
  135 hotplugclose(dev_t dev, int flag, int mode, struct proc *p)
  136 {
  137         struct hotplug_event he;
  138 
  139         while (hotplug_get_event(&he) == 0)
  140                 continue;
  141         opened = 0;
  142         return (0);
  143 }
  144 
  145 int
  146 hotplugread(dev_t dev, struct uio *uio, int flags)
  147 {
  148         struct hotplug_event he;
  149         int error;
  150 
  151         if (uio->uio_resid != sizeof(he))
  152                 return (EINVAL);
  153 
  154 again:
  155         if (hotplug_get_event(&he) == 0)
  156                 return (uiomove(&he, sizeof(he), uio));
  157         if (flags & IO_NDELAY)
  158                 return (EAGAIN);
  159 
  160         error = tsleep_nsec(&evqueue, PRIBIO | PCATCH, "htplev", INFSLP);
  161         if (error)
  162                 return (error);
  163         goto again;
  164 }
  165 
  166 int
  167 hotplugioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  168 {
  169         switch (cmd) {
  170         case FIOASYNC:
  171                 /* ignore */
  172         case FIONBIO:
  173                 /* handled in the upper fs layer */
  174                 break;
  175         default:
  176                 return (ENOTTY);
  177         }
  178 
  179         return (0);
  180 }
  181 
  182 int
  183 hotplugkqfilter(dev_t dev, struct knote *kn)
  184 {
  185         struct klist *klist;
  186         int s;
  187 
  188         switch (kn->kn_filter) {
  189         case EVFILT_READ:
  190                 klist = &hotplug_sel.si_note;
  191                 kn->kn_fop = &hotplugread_filtops;
  192                 break;
  193         default:
  194                 return (EINVAL);
  195         }
  196 
  197         s = splbio();
  198         klist_insert_locked(klist, kn);
  199         splx(s);
  200         return (0);
  201 }
  202 
  203 void
  204 filt_hotplugrdetach(struct knote *kn)
  205 {
  206         int s;
  207 
  208         s = splbio();
  209         klist_remove_locked(&hotplug_sel.si_note, kn);
  210         splx(s);
  211 }
  212 
  213 int
  214 filt_hotplugread(struct knote *kn, long hint)
  215 {
  216         kn->kn_data = evqueue_count;
  217 
  218         return (evqueue_count > 0);
  219 }

Cache object: d661713dbbbc43180f8a6b07c1126455


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