summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/majors3
-rw-r--r--sys/dev/nmdm/nmdm.c169
-rw-r--r--sys/dev/snp/snp.c30
-rw-r--r--sys/kern/kern_conf.c137
-rw-r--r--sys/net/if_tap.c164
-rw-r--r--sys/net/if_tapvar.h1
-rw-r--r--sys/net/if_tun.c163
-rw-r--r--sys/net/if_tunvar.h55
-rw-r--r--sys/sys/conf.h9
-rw-r--r--sys/sys/linedisc.h9
10 files changed, 342 insertions, 398 deletions
diff --git a/sys/conf/majors b/sys/conf/majors
index 62f5264..5671b38 100644
--- a/sys/conf/majors
+++ b/sys/conf/majors
@@ -23,7 +23,6 @@
5 *pts pseudo tty "tty" half
6 *ptc pseudo tty "master" half
7 *log system log
-18 *nmdm nullmodem back-to-back tty ports
19 *tw X-10 power interface
22 *fd (/dev/stdin etc)
30 *snd sound driver system
@@ -37,7 +36,6 @@
42 *cx Cronyx/Sigma serial adapter
43 vn vnode "disk" device (retired)
46 - -
-52 *tun IP tunnel device
54 OLDnic ISDN system
58 - Was dgb: Digiboard PC/Xe
62 worm SCSI "worm type"
@@ -77,7 +75,6 @@
139 wanrouter Sangoma Technologies Inc. (al.feldman@sangoma.com)
141 pcdmx PCDMX theatre lighting controller
142 skip SKIP port (security/skip) control device
-149 *tap Ethernet tunneling device <myevmenkin@att.com>
154 *asr Adaptec SCSI RAID <msmith@freebsd.org>
155 phone Quicknet PhoneJACK and LineJACK cards for VoIP <roger>
159 *ata ATA control device
diff --git a/sys/dev/nmdm/nmdm.c b/sys/dev/nmdm/nmdm.c
index 3227b11..f3440dd 100644
--- a/sys/dev/nmdm/nmdm.c
+++ b/sys/dev/nmdm/nmdm.c
@@ -63,8 +63,7 @@ MALLOC_DEFINE(M_NLMDM, "nullmodem", "nullmodem data structures");
static void nmdmstart(struct tty *tp);
static void nmdmstop(struct tty *tp, int rw);
static void wakeup_other(struct tty *tp, int flag);
-static void nmdminit(int);
-static int nmdmshutdown(void);
+static void nmdminit(dev_t dev);
static d_open_t nmdmopen;
static d_close_t nmdmclose;
@@ -72,7 +71,6 @@ static d_read_t nmdmread;
static d_write_t nmdmwrite;
static d_ioctl_t nmdmioctl;
-#define CDEV_MAJOR 18
static struct cdevsw nmdm_cdevsw = {
.d_open = nmdmopen,
.d_close = nmdmclose,
@@ -80,14 +78,14 @@ static struct cdevsw nmdm_cdevsw = {
.d_write = nmdmwrite,
.d_ioctl = nmdmioctl,
.d_poll = ttypoll,
- .d_name = "pts",
- .d_maj = CDEV_MAJOR,
- .d_flags = D_TTY,
+ .d_name = "nmdm",
+ .d_flags = D_TTY | D_PSEUDO,
};
#define BUFSIZ 100 /* Chunk size iomoved to/from user */
#define NMDM_MAX_NUM 128 /* Artificially limit # devices. */
#define PF_STOPPED 0x10 /* user told stopped */
+#define BFLAG CLONE_FLAG0
struct softpart {
struct tty nm_tty;
@@ -97,11 +95,61 @@ struct softpart {
};
struct nm_softc {
- int pt_flags;
- struct softpart part1, part2;
- struct prison *pt_prison;
+ TAILQ_ENTRY(nm_softc) pt_list;
+ int pt_flags;
+ struct softpart part1, part2;
+ struct prison *pt_prison;
};
+static struct clonedevs *nmdmclones;
+static TAILQ_HEAD(,nm_softc) nmdmhead = TAILQ_HEAD_INITIALIZER(nmdmhead);
+
+static void
+nmdm_clone(void *arg, char *name, int nameen, dev_t *dev)
+{
+ int i, unit;
+ char *p;
+ dev_t d1, d2;
+
+ if (*dev != NODEV)
+ return;
+ if (strcmp(name, "nmdm") == 0) {
+ p = NULL;
+ unit = -1;
+ } else {
+ i = dev_stdclone(name, &p, "nmdm", &unit);
+ if (i == 0)
+ return;
+ if (p[0] != '\0' && p[0] != 'A' && p[0] != 'B')
+ return;
+ else if (p[0] != '\0' && p[1] != '\0')
+ return;
+ }
+ i = clone_create(&nmdmclones, &nmdm_cdevsw, &unit, &d1, 0);
+ if (i) {
+ d1 = make_dev(&nmdm_cdevsw, unit2minor(unit),
+ 0, 0, 0666, "nmdm%dA", unit);
+ if (d1 == NULL)
+ return;
+ d2 = make_dev(&nmdm_cdevsw, unit2minor(unit) | BFLAG,
+ 0, 0, 0666, "nmdm%dB", unit);
+ if (d2 == NULL) {
+ destroy_dev(d1);
+ return;
+ }
+ d2->si_drv2 = d1;
+ d1->si_drv2 = d2;
+ dev_depends(d1, d2);
+ dev_depends(d2, d1);
+ d1->si_flags |= SI_CHEAPCLONE;
+ d2->si_flags |= SI_CHEAPCLONE;
+ }
+ if (p != NULL && p[0] == 'B')
+ *dev = d1->si_drv2;
+ else
+ *dev = d1;
+}
+
static void
nmdm_crossover(struct nm_softc *pti,
struct softpart *ourpart,
@@ -123,24 +171,22 @@ do { \
* This function creates and initializes a pair of ttys.
*/
static void
-nmdminit(n)
- int n;
+nmdminit(dev_t dev1)
{
- dev_t dev1, dev2;
+ dev_t dev2;
struct nm_softc *pt;
- /* For now we only map the lower 8 bits of the minor */
- if (n & ~0xff)
- return;
+ dev2 = dev1->si_drv2;
- pt = malloc(sizeof(*pt), M_NLMDM, M_WAITOK);
- bzero(pt, sizeof(*pt));
- pt->part1.dev = dev1 = make_dev(&nmdm_cdevsw, n+n,
- 0, 0, 0666, "nmdm%dA", n);
- pt->part2.dev = dev2 = make_dev(&nmdm_cdevsw, n+n+1,
- 0, 0, 0666, "nmdm%dB", n);
+ dev1->si_flags &= ~SI_CHEAPCLONE;
+ dev2->si_flags &= ~SI_CHEAPCLONE;
+ pt = malloc(sizeof(*pt), M_NLMDM, M_WAITOK | M_ZERO);
+ TAILQ_INSERT_TAIL(&nmdmhead, pt, pt_list);
dev1->si_drv1 = dev2->si_drv1 = pt;
+
+ pt->part1.dev = dev1;
+ pt->part2.dev = dev2;
dev1->si_tty = &pt->part1.nm_tty;
dev2->si_tty = &pt->part2.nm_tty;
ttyregister(&pt->part1.nm_tty);
@@ -148,9 +194,9 @@ nmdminit(n)
pt->part1.nm_tty.t_oproc = nmdmstart;
pt->part2.nm_tty.t_oproc = nmdmstart;
pt->part1.nm_tty.t_stop = nmdmstop;
+ pt->part2.nm_tty.t_stop = nmdmstop;
pt->part2.nm_tty.t_dev = dev1;
pt->part1.nm_tty.t_dev = dev2;
- pt->part2.nm_tty.t_stop = nmdmstop;
}
/*
@@ -161,39 +207,14 @@ nmdmopen(dev_t dev, int flag, int devtype, struct thread *td)
{
register struct tty *tp, *tp2;
int error;
- int minr;
- dev_t nextdev;
struct nm_softc *pti;
- int is_b;
- int pair;
struct softpart *ourpart, *otherpart;
- /*
- * XXX: Gross hack for DEVFS:
- * If we openned this device, ensure we have the
- * next one too, so people can open it.
- */
- minr = dev2unit(dev);
- pair = minr >> 1;
- is_b = minr & 1;
-
- if (pair < (NMDM_MAX_NUM - 1)) {
- nextdev = makedev(major(dev), minr + 2);
- if (!nextdev->si_drv1) {
- nmdminit(pair + 1);
- }
- } else { /* Limit ourselves to 128 of them for now */
- if (pair > (NMDM_MAX_NUM - 1))
- return (ENXIO);
- }
- if (!dev->si_drv1)
- nmdminit(pair);
-
- if (!dev->si_drv1)
- return(ENXIO);
-
+ if (dev->si_drv1 == NULL)
+ nmdminit(dev);
pti = dev->si_drv1;
- if (is_b)
+
+ if (minor(dev) & BFLAG)
tp = &pti->part2.nm_tty;
else
tp = &pti->part1.nm_tty;
@@ -567,20 +588,27 @@ nmdm_crossover(struct nm_softc *pti, struct softpart *ourpart,
static int
nmdm_modevent(module_t mod, int type, void *data)
{
+ static eventhandler_tag tag;
+ struct nm_softc *pt, *tpt;
int error = 0;
switch(type) {
- case MOD_LOAD: /* start with 4 of them */
- nmdminit(0);
- nmdminit(1);
- nmdminit(2);
- nmdminit(3);
+ case MOD_LOAD:
+ tag = EVENTHANDLER_REGISTER(dev_clone, nmdm_clone, 0, 1000);
+ if (tag == NULL)
+ return (ENOMEM);
break;
case MOD_SHUTDOWN:
/* FALLTHROUGH */
case MOD_UNLOAD:
- nmdmshutdown();
+ EVENTHANDLER_DEREGISTER(dev_clone, tag);
+ TAILQ_FOREACH_SAFE(pt, &nmdmhead, pt_list, tpt) {
+ destroy_dev(pt->part1.dev);
+ TAILQ_REMOVE(&nmdmhead, pt, pt_list);
+ free(pt, M_NLMDM);
+ }
+ clone_cleanup(&nmdmclones);
break;
default:
error = EOPNOTSUPP;
@@ -588,31 +616,4 @@ nmdm_modevent(module_t mod, int type, void *data)
return (error);
}
-/*
- * Handle teardown of device
- */
-static int
-nmdmshutdown(void)
-{
- int i;
- dev_t nextdev1;
- dev_t nextdev2;
- void * ptr1;
-
- for(i = 0;( i < NMDM_MAX_NUM) ;i++) {
- nextdev1 = makedev(CDEV_MAJOR, (i+i) );
- nextdev2 = makedev(CDEV_MAJOR, (i+i) + 1);
- ptr1 = nextdev1->si_drv1;
- if (ptr1) {
- destroy_dev(nextdev1);
- destroy_dev(nextdev2);
- free(ptr1, M_NLMDM);
- } else {
- freedev(nextdev1);
- freedev(nextdev2);
- }
- }
- return(0);
-}
-
DEV_MODULE(nmdm, nmdm_modevent, NULL);
diff --git a/sys/dev/snp/snp.c b/sys/dev/snp/snp.c
index 4c4115d..2c1c3c6 100644
--- a/sys/dev/snp/snp.c
+++ b/sys/dev/snp/snp.c
@@ -38,7 +38,6 @@ static d_write_t snpwrite;
static d_ioctl_t snpioctl;
static d_poll_t snppoll;
-#define CDEV_MAJOR 53
static struct cdevsw snp_cdevsw = {
.d_open = snpopen,
.d_close = snpclose,
@@ -47,7 +46,7 @@ static struct cdevsw snp_cdevsw = {
.d_ioctl = snpioctl,
.d_poll = snppoll,
.d_name = "snp",
- .d_maj = CDEV_MAJOR,
+ .d_flags = D_PSEUDO,
};
static struct linesw snpdisc = {
@@ -101,10 +100,9 @@ static MALLOC_DEFINE(M_SNP, "snp", "Snoop device data");
* module load time.
*/
static int snooplinedisc;
-static udev_t snpbasedev = NOUDEV;
-
static LIST_HEAD(, snoop) snp_sclist = LIST_HEAD_INITIALIZER(&snp_sclist);
+static struct clonedevs *snpclones;
static struct tty *snpdevtotty(dev_t dev);
static void snp_clone(void *arg, char *name,
@@ -384,9 +382,7 @@ snpopen(dev, flag, mode, td)
struct snoop *snp;
if (dev->si_drv1 == NULL) {
- if (!(dev->si_flags & SI_NAMED))
- make_dev(&snp_cdevsw, minor(dev), UID_ROOT, GID_WHEEL,
- 0600, "snp%d", dev2unit(dev));
+ dev->si_flags &= ~SI_CHEAPCLONE;
dev->si_drv1 = snp = malloc(sizeof(*snp), M_SNP,
M_WAITOK | M_ZERO);
snp->snp_unit = dev2unit(dev);
@@ -466,6 +462,7 @@ snpclose(dev, flags, fmt, td)
free(snp->snp_buf, M_SNP);
snp->snp_flags &= ~SNOOP_OPEN;
dev->si_drv1 = NULL;
+ destroy_dev(dev);
return (snp_detach(snp));
}
@@ -608,20 +605,18 @@ snp_clone(arg, name, namelen, dev)
int namelen;
dev_t *dev;
{
- int u;
+ int u, i;
if (*dev != NODEV)
return;
if (dev_stdclone(name, NULL, "snp", &u) != 1)
return;
- *dev = make_dev(&snp_cdevsw, unit2minor(u), UID_ROOT, GID_WHEEL, 0600,
- "snp%d", u);
- if (snpbasedev == NOUDEV)
- snpbasedev = (*dev)->si_udev;
- else {
+ i = clone_create(&snpclones, &snp_cdevsw, &u, dev, 0);
+ if (i)
+ *dev = make_dev(&snp_cdevsw, unit2minor(u),
+ UID_ROOT, GID_WHEEL, 0600, "snp%d", u);
+ if (*dev != NULL)
(*dev)->si_flags |= SI_CHEAPCLONE;
- dev_depends(udev2dev(snpbasedev, 0), *dev);
- }
}
static int
@@ -642,8 +637,7 @@ snp_modevent(mod, type, data)
if (!LIST_EMPTY(&snp_sclist))
return (EBUSY);
EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
- if (snpbasedev != NOUDEV)
- destroy_dev(udev2dev(snpbasedev, 0));
+ clone_cleanup(&snpclones);
ldisc_deregister(snooplinedisc);
break;
default:
@@ -657,4 +651,4 @@ static moduledata_t snp_mod = {
snp_modevent,
NULL
};
-DECLARE_MODULE(snp, snp_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR);
+DECLARE_MODULE(snp, snp_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c
index c99173d..62033c7 100644
--- a/sys/kern/kern_conf.c
+++ b/sys/kern/kern_conf.c
@@ -324,10 +324,22 @@ makeudev(int x, int y)
}
static void
-prep_cdevsw(struct cdevsw *devsw)
+find_major(struct cdevsw *devsw)
{
int i;
+ for (i = NUMCDEVSW - 1; i > 0; i--)
+ if (reserved_majors[i] != i)
+ break;
+ KASSERT(i > 0, ("Out of major numbers (%s)", devsw->d_name));
+ devsw->d_maj = i;
+ reserved_majors[i] = i;
+}
+
+static void
+prep_cdevsw(struct cdevsw *devsw)
+{
+
if (devsw->d_open == NULL) devsw->d_open = null_open;
if (devsw->d_close == NULL) devsw->d_close = null_close;
if (devsw->d_read == NULL) devsw->d_read = no_read;
@@ -339,12 +351,7 @@ prep_cdevsw(struct cdevsw *devsw)
if (devsw->d_dump == NULL) devsw->d_dump = no_dump;
if (devsw->d_kqfilter == NULL) devsw->d_kqfilter = no_kqfilter;
if (devsw->d_maj == MAJOR_AUTO) {
- for (i = NUMCDEVSW - 1; i > 0; i--)
- if (reserved_majors[i] != i)
- break;
- KASSERT(i > 0, ("Out of major numbers (%s)", devsw->d_name));
- devsw->d_maj = i;
- reserved_majors[i] = i;
+ find_major(devsw);
} else {
if (devsw->d_maj == 256) /* XXX: tty_cons.c is magic */
devsw->d_maj = 0;
@@ -458,17 +465,22 @@ destroy_dev(dev_t dev)
}
devfs_destroy(dev);
+ dev->si_flags &= ~SI_NAMED;
+
if (dev->si_flags & SI_CHILD) {
LIST_REMOVE(dev, si_siblings);
dev->si_flags &= ~SI_CHILD;
}
while (!LIST_EMPTY(&dev->si_children))
destroy_dev(LIST_FIRST(&dev->si_children));
+ if (dev->si_flags & SI_CLONELIST) {
+ LIST_REMOVE(dev, si_clone);
+ dev->si_flags &= ~SI_CLONELIST;
+ }
dev->si_drv1 = 0;
dev->si_drv2 = 0;
dev->si_devsw = 0;
bzero(&dev->__si_u, sizeof(dev->__si_u));
- dev->si_flags &= ~SI_NAMED;
dev->si_flags &= ~SI_ALIAS;
freedev(dev);
}
@@ -523,6 +535,115 @@ dev_stdclone(char *name, char **namep, const char *stem, int *unit)
}
/*
+ * Helper functions for cloning device drivers.
+ *
+ * The objective here is to make it unnecessary for the device drivers to
+ * use rman or similar to manage their unit number space. Due to the way
+ * we do "on-demand" devices, using rman or other "private" methods
+ * will be very tricky to lock down properly once we lock down this file.
+ *
+ * Instead we give the drivers these routines which puts the dev_t's that
+ * are to be managed on their own list, and gives the driver the ability
+ * to ask for the first free unit number or a given specified unit number.
+ *
+ * In addition these routines support paired devices (pty, nmdm and similar)
+ * by respecting a number of "flag" bits in the minor number.
+ *
+ */
+
+struct clonedevs {
+ LIST_HEAD(,cdev) head;
+};
+
+int
+clone_create(struct clonedevs **cdp, struct cdevsw *csw, int *up, dev_t *dp, u_int extra)
+{
+ struct clonedevs *cd;
+ dev_t dev, dl, de;
+ int unit, low, u;
+
+ KASSERT(!(extra & CLONE_UNITMASK),
+ ("Illegal extra bits (0x%x) in clone_create", extra));
+ KASSERT(*up <= CLONE_UNITMASK,
+ ("Too high unit (0x%x) in clone_create", *up));
+
+ if (csw->d_maj == MAJOR_AUTO)
+ find_major(csw);
+ /* if clonedevs have not been initialized, we do it here */
+ cd = *cdp;
+ if (cd == NULL) {
+ cd = malloc(sizeof *cd, M_DEVBUF, M_WAITOK | M_ZERO);
+ LIST_INIT(&cd->head);
+ *cdp = cd;
+ }
+
+ /*
+ * Search the list for a lot of things in one go:
+ * A preexisting match is returned immediately.
+ * The lowest free unit number if we are passed -1, and the place
+ * in the list where we should insert that new element.
+ * The place to insert a specified unit number, if applicable
+ * the end of the list.
+ */
+ unit = *up;
+ low = 0;
+ de = dl = NULL;
+ LIST_FOREACH(dev, &cd->head, si_clone) {
+ u = dev2unit(dev);
+ if (u == (unit | extra)) {
+ *dp = dev;
+ return (0);
+ }
+ if (unit == -1 && u == low) {
+ low++;
+ de = dev;
+ continue;
+ }
+ if (u > unit) {
+ dl = dev;
+ break;
+ }
+ de = dev;
+ }
+ if (unit == -1)
+ unit = low;
+ dev = makedev(csw->d_maj, unit2minor(unit | extra));
+ KASSERT(!(dev->si_flags & SI_CLONELIST),
+ ("Dev %p should not be on clonelist", dev));
+ if (dl != NULL)
+ LIST_INSERT_BEFORE(dl, dev, si_clone);
+ else if (de != NULL)
+ LIST_INSERT_AFTER(de, dev, si_clone);
+ else
+ LIST_INSERT_HEAD(&cd->head, dev, si_clone);
+ dev->si_flags |= SI_CLONELIST;
+ *up = unit;
+ return (1);
+}
+
+/*
+ * Kill everything still on the list. The driver should already have
+ * disposed of any softc hung of the dev_t's at this time.
+ */
+void
+clone_cleanup(struct clonedevs **cdp)
+{
+ dev_t dev, tdev;
+ struct clonedevs *cd;
+
+ cd = *cdp;
+ if (cd == NULL)
+ return;
+ LIST_FOREACH_SAFE(dev, &cd->head, si_clone, tdev) {
+ KASSERT(dev->si_flags & SI_NAMED,
+ ("Driver has goofed in cloning underways udev %x", dev->si_udev));
+ destroy_dev(dev);
+ }
+ free(cd, M_DEVBUF);
+ *cdp = NULL;
+}
+
+/*
* Helper sysctl for devname(3). We're given a {u}dev_t and return
* the name, if any, registered by the device driver.
*/
diff --git a/sys/net/if_tap.c b/sys/net/if_tap.c
index 82ae3b9..f83243b 100644
--- a/sys/net/if_tap.c
+++ b/sys/net/if_tap.c
@@ -54,8 +54,6 @@
#include <sys/ttycom.h>
#include <sys/uio.h>
#include <sys/vnode.h>
-#include <machine/bus.h> /* XXX: Shouldn't really be required! */
-#include <sys/rman.h>
#include <sys/queue.h>
#include <net/bpf.h>
@@ -71,14 +69,12 @@
#define CDEV_NAME "tap"
-#define CDEV_MAJOR 149
#define TAPDEBUG if (tapdebug) printf
#define TAP "tap"
#define VMNET "vmnet"
#define TAPMAXUNIT 0x7fff
-#define VMNET_DEV_MASK 0x00800000
- /* 0x007f00ff */
+#define VMNET_DEV_MASK CLONE_FLAG0
/* module */
static int tapmodevent(module_t, int, void *);
@@ -108,15 +104,12 @@ static struct cdevsw tap_cdevsw = {
.d_ioctl = tapioctl,
.d_poll = tappoll,
.d_name = CDEV_NAME,
- .d_maj = CDEV_MAJOR,
+ .d_flags = D_PSEUDO,
};
static int tapdebug = 0; /* debug flag */
static SLIST_HEAD(, tap_softc) taphead; /* first device */
-static udev_t tapbasedev = NOUDEV; /* base device */
-static struct rman tapdevunits[2]; /* device units */
-#define tapunits tapdevunits
-#define vmnetunits (tapdevunits + 1)
+static struct clonedevs *tapclones;
MALLOC_DECLARE(M_TAP);
MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
@@ -137,63 +130,27 @@ tapmodevent(mod, type, data)
static eventhandler_tag eh_tag = NULL;
struct tap_softc *tp = NULL;
struct ifnet *ifp = NULL;
- int error, s;
+ int s;
switch (type) {
case MOD_LOAD:
- /* initialize resources */
- tapunits->rm_type = RMAN_ARRAY;
- tapunits->rm_descr = "open tap units";
- vmnetunits->rm_type = RMAN_ARRAY;
- vmnetunits->rm_descr = "open vmnet units";
-
- error = rman_init(tapunits);
- if (error != 0)
- goto bail;
-
- error = rman_init(vmnetunits);
- if (error != 0)
- goto bail1;
-
- error = rman_manage_region(tapunits, 0, TAPMAXUNIT);
- if (error != 0)
- goto bail2;
-
- error = rman_manage_region(vmnetunits, 0, TAPMAXUNIT);
- if (error != 0)
- goto bail2;
/* intitialize device */
SLIST_INIT(&taphead);
eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000);
- if (eh_tag == NULL) {
- error = ENOMEM;
- goto bail2;
- }
-
-
+ if (eh_tag == NULL)
+ return (ENOMEM);
return (0);
-bail2:
- rman_fini(vmnetunits);
-bail1:
- rman_fini(tapunits);
-bail:
- return (error);
case MOD_UNLOAD:
SLIST_FOREACH(tp, &taphead, tap_next)
- if (tp->tap_unit != NULL)
+ if (tp->tap_flags & TAP_OPEN)
return (EBUSY);
EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
- error = rman_fini(tapunits);
- KASSERT((error == 0), ("Could not fini tap units"));
- error = rman_fini(vmnetunits);
- KASSERT((error == 0), ("Could not fini vmnet units"));
-
while ((tp = SLIST_FIRST(&taphead)) != NULL) {
SLIST_REMOVE_HEAD(&taphead, tap_next);
@@ -204,18 +161,14 @@ bail:
KASSERT(!(tp->tap_flags & TAP_OPEN),
("%s flags is out of sync", ifp->if_xname));
- /* XXX makedev check? nah.. not right now :) */
-
+ destroy_dev(tp->tap_dev);
s = splimp();
ether_ifdetach(ifp);
splx(s);
free(tp, M_TAP);
}
-
- if (tapbasedev != NOUDEV)
- destroy_dev(udev2dev(tapbasedev, 0));
-
+ clone_cleanup(&tapclones);
break;
@@ -239,65 +192,35 @@ tapclone(arg, name, namelen, dev)
int namelen;
dev_t *dev;
{
- int unit, minor = 0 /* XXX avoid warning */ , error;
+ u_int extra;
+ int i, unit;
char *device_name = name;
- struct resource *r = NULL;
if (*dev != NODEV)
return;
- if (strcmp(device_name, TAP) == 0) {
- /* get first free tap unit */
- r = rman_reserve_resource(tapunits, 0, TAPMAXUNIT, 1,
- RF_ALLOCATED | RF_ACTIVE, NULL);
- unit = rman_get_start(r);
- minor = unit2minor(unit);
- }
- else if (strcmp(device_name, VMNET) == 0) {
- /* get first free vmnet unit */
- r = rman_reserve_resource(vmnetunits, 0, TAPMAXUNIT, 1,
- RF_ALLOCATED | RF_ACTIVE, NULL);
- unit = rman_get_start(r);
- minor = unit2minor(unit) | VMNET_DEV_MASK;
+ device_name = TAP;
+ extra = 0;
+ if (strcmp(name, TAP) == 0) {
+ unit = -1;
+ } else if (strcmp(name, VMNET) == 0) {
+ device_name = VMNET;
+ extra = VMNET_DEV_MASK;
+ unit = -1;
+ } else if (dev_stdclone(name, NULL, device_name, &unit) != 1) {
+ device_name = VMNET;
+ extra = VMNET_DEV_MASK;
+ if (dev_stdclone(name, NULL, device_name, &unit) != 1)
+ return;
}
- if (r != NULL) { /* need cloning */
- TAPDEBUG("%s%d is available. minor = %#x\n",
- device_name, unit, minor);
-
- error = rman_release_resource(r);
- KASSERT((error == 0), ("Could not release tap/vmnet unit"));
-
- /* check if device for the unit has been created */
- *dev = makedev(CDEV_MAJOR, minor);
- if ((*dev)->si_flags & SI_NAMED) {
- TAPDEBUG("%s%d device exists. minor = %#x\n",
- device_name, unit, minor);
- return; /* device has been created */
- }
- } else { /* try to match name/unit, first try tap then vmnet */
- device_name = TAP;
- if (dev_stdclone(name, NULL, device_name, &unit) != 1) {
- device_name = VMNET;
-
- if (dev_stdclone(name, NULL, device_name, &unit) != 1)
- return;
-
- minor = unit2minor(unit) | VMNET_DEV_MASK;
- } else
- minor = unit2minor(unit);
- }
-
- TAPDEBUG("make_dev(%s%d). minor = %#x\n", device_name, unit, minor);
-
- *dev = make_dev(&tap_cdevsw, minor, UID_ROOT, GID_WHEEL, 0600, "%s%d",
- device_name, unit);
-
- if (tapbasedev == NOUDEV)
- tapbasedev = (*dev)->si_udev;
- else {
- (*dev)->si_flags |= SI_CHEAPCLONE;
- dev_depends(udev2dev(tapbasedev, 0), *dev);
+ /* find any existing device, or allocate new unit number */
+ i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra);
+ if (i) {
+ *dev = make_dev(&tap_cdevsw, unit2minor(unit) | extra,
+ UID_ROOT, GID_WHEEL, 0600, "%s%d", device_name, unit);
+ if (*dev != NULL)
+ (*dev)->si_flags |= SI_CHEAPCLONE;
}
} /* tapclone */
@@ -317,6 +240,8 @@ tapcreate(dev)
int unit, s;
char *name = NULL;
+ dev->si_flags &= ~SI_CHEAPCLONE;
+
/* allocate driver storage and create device */
MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK | M_ZERO);
SLIST_INSERT_HEAD(&taphead, tp, tap_next);
@@ -354,6 +279,7 @@ tapcreate(dev)
ifp->if_snd.ifq_maxlen = ifqmaxlen;
dev->si_drv1 = tp;
+ tp->tap_dev = dev;
s = splimp();
ether_ifattach(ifp, tp->arpcom.ac_enaddr);
@@ -380,24 +306,12 @@ tapopen(dev, flag, mode, td)
{
struct tap_softc *tp = NULL;
int unit, error;
- struct resource *r = NULL;
if ((error = suser(td)) != 0)
return (error);
unit = dev2unit(dev) & TAPMAXUNIT;
- if (minor(dev) & VMNET_DEV_MASK)
- r = rman_reserve_resource(vmnetunits, unit, unit, 1,
- RF_ALLOCATED | RF_ACTIVE, NULL);
- else
- r = rman_reserve_resource(tapunits, unit, unit, 1,
- RF_ALLOCATED | RF_ACTIVE, NULL);
-
- if (r == NULL)
- return (EBUSY);
-
- dev->si_flags &= ~SI_CHEAPCLONE;
tp = dev->si_drv1;
if (tp == NULL) {
@@ -410,7 +324,6 @@ tapopen(dev, flag, mode, td)
bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr));
- tp->tap_unit = r;
tp->tap_pid = td->td_proc->p_pid;
tp->tap_flags |= TAP_OPEN;
@@ -433,12 +346,9 @@ tapclose(dev, foo, bar, td)
int bar;
struct thread *td;
{
- int s, error;
struct tap_softc *tp = dev->si_drv1;
struct ifnet *ifp = &tp->tap_if;
-
- KASSERT((tp->tap_unit != NULL),
- ("%s is not open", ifp->if_xname));
+ int s;
/* junk all pending output */
IF_DRAIN(&ifp->if_snd);
@@ -479,10 +389,6 @@ tapclose(dev, foo, bar, td)
tp->tap_flags &= ~TAP_OPEN;
tp->tap_pid = 0;
- error = rman_release_resource(tp->tap_unit);
- KASSERT((error == 0),
- ("%s could not release unit", ifp->if_xname));
- tp->tap_unit = NULL;
TAPDEBUG("%s is closed. minor = %#x\n",
ifp->if_xname, minor(dev));
diff --git a/sys/net/if_tapvar.h b/sys/net/if_tapvar.h
index 06e3bbdf..ae6c3cd 100644
--- a/sys/net/if_tapvar.h
+++ b/sys/net/if_tapvar.h
@@ -61,6 +61,7 @@ struct tap_softc {
struct selinfo tap_rsel; /* read select */
SLIST_ENTRY(tap_softc) tap_next; /* next device in chain */
+ dev_t tap_dev;
};
#endif /* !_NET_IF_TAPVAR_H_ */
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c
index 516d299..4a64da4 100644
--- a/sys/net/if_tun.c
+++ b/sys/net/if_tun.c
@@ -41,9 +41,7 @@
#include <sys/uio.h>
#include <sys/vnode.h>
#include <sys/malloc.h>
-#include <machine/bus.h> /* XXX Shouldn't really be required ! */
#include <sys/random.h>
-#include <sys/rman.h>
#include <net/if.h>
#include <net/if_types.h>
@@ -53,17 +51,40 @@
#include <netinet/in.h>
#endif
#include <net/bpf.h>
-#include <net/if_tunvar.h>
#include <net/if_tun.h>
+#include <sys/queue.h>
+
+struct tun_softc {
+ TAILQ_ENTRY(tun_softc) tun_list;
+ int tun_unit;
+ dev_t tun_dev;
+ u_short tun_flags; /* misc flags */
+#define TUN_OPEN 0x0001
+#define TUN_INITED 0x0002
+#define TUN_RCOLL 0x0004
+#define TUN_IASET 0x0008
+#define TUN_DSTADDR 0x0010
+#define TUN_LMODE 0x0020
+#define TUN_RWAIT 0x0040
+#define TUN_ASYNC 0x0080
+#define TUN_IFHEAD 0x0100
+
+#define TUN_READY (TUN_OPEN | TUN_INITED)
+
+ struct proc *tun_proc; /* Owning process */
+ struct ifnet tun_if; /* the interface */
+ struct sigio *tun_sigio; /* information for async I/O */
+ struct selinfo tun_rsel; /* read select */
+};
+
#define TUNDEBUG if (tundebug) if_printf
#define TUNNAME "tun"
static MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface");
static int tundebug = 0;
-static struct tun_softc *tunhead = NULL;
-static struct rman tununits;
-static udev_t tunbasedev = NOUDEV;
+static struct clonedevs *tunclones;
+static TAILQ_HEAD(,tun_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead);
SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
static void tunclone(void *arg, char *name, int namelen, dev_t *dev);
@@ -82,7 +103,6 @@ static d_write_t tunwrite;
static d_ioctl_t tunioctl;
static d_poll_t tunpoll;
-#define CDEV_MAJOR 52
static struct cdevsw tun_cdevsw = {
.d_open = tunopen,
.d_close = tunclose,
@@ -91,44 +111,32 @@ static struct cdevsw tun_cdevsw = {
.d_ioctl = tunioctl,
.d_poll = tunpoll,
.d_name = TUNNAME,
- .d_maj = CDEV_MAJOR,
+ .d_flags = D_PSEUDO,
};
static void
tunclone(void *arg, char *name, int namelen, dev_t *dev)
{
- struct resource *r;
- int err;
- int u;
+ int u, i;
if (*dev != NODEV)
return;
if (strcmp(name, TUNNAME) == 0) {
- r = rman_reserve_resource(&tununits, 0, IF_MAXUNIT, 1,
- RF_ALLOCATED | RF_ACTIVE, NULL);
- u = rman_get_start(r);
- err = rman_release_resource(r);
- KASSERT(err == 0, ("Unexpected failure releasing resource"));
- *dev = makedev(CDEV_MAJOR, unit2minor(u));
- if ((*dev)->si_flags & SI_NAMED)
- return; /* Already make_dev()d */
+ u = -1;
} else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1)
return; /* Don't recognise the name */
-
- *dev = make_dev(&tun_cdevsw, unit2minor(u),
- UID_ROOT, GID_WHEEL, 0600, "tun%d", u);
-
- /*
- * All devices depend on tunbasedev so that we can simply
- * destroy_dev() this device at module unload time to get
- * rid of all our make_dev()d resources.
- */
- if (tunbasedev == NOUDEV)
- tunbasedev = (*dev)->si_udev;
- else {
- (*dev)->si_flags |= SI_CHEAPCLONE;
- dev_depends(udev2dev(tunbasedev, 0), *dev);
+ if (u != -1 && u > IF_MAXUNIT)
+ return; /* Unit number too high */
+
+ /* find any existing device, or allocate new unit number */
+ i = clone_create(&tunclones, &tun_cdevsw, &u, dev, 0);
+ if (i) {
+ /* No preexisting dev_t, create one */
+ *dev = make_dev(&tun_cdevsw, unit2minor(u),
+ UID_UUCP, GID_DIALER, 0600, "tun%d", u);
+ if (*dev != NULL)
+ (*dev)->si_flags |= SI_CHEAPCLONE;
}
}
@@ -138,57 +146,29 @@ tunmodevent(module_t mod, int type, void *data)
static eventhandler_tag tag;
struct tun_softc *tp;
dev_t dev;
- int err;
switch (type) {
case MOD_LOAD:
tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000);
if (tag == NULL)
return (ENOMEM);
- tununits.rm_type = RMAN_ARRAY;
- tununits.rm_descr = "open if_tun units";
- err = rman_init(&tununits);
- if (err != 0) {
- EVENTHANDLER_DEREGISTER(dev_clone, tag);
- return (err);
- }
- err = rman_manage_region(&tununits, 0, IF_MAXUNIT);
- if (err != 0) {
- printf("%s: tununits: rman_manage_region: Failed %d\n",
- TUNNAME, err);
- rman_fini(&tununits);
- EVENTHANDLER_DEREGISTER(dev_clone, tag);
- return (err);
- }
break;
case MOD_UNLOAD:
- err = rman_fini(&tununits);
- if (err != 0)
- return (err);
EVENTHANDLER_DEREGISTER(dev_clone, tag);
- while (tunhead != NULL) {
- KASSERT((tunhead->tun_flags & TUN_OPEN) == 0,
+ while (!TAILQ_EMPTY(&tunhead)) {
+ tp = TAILQ_FIRST(&tunhead);
+ KASSERT((tp->tun_flags & TUN_OPEN) == 0,
("tununits is out of sync - unit %d",
- tunhead->tun_if.if_dunit));
- tp = tunhead;
- dev = makedev(tun_cdevsw.d_maj,
- unit2minor(tp->tun_if.if_dunit));
- KASSERT(dev->si_drv1 == tp, ("Bad makedev result"));
- tunhead = tp->next;
+ tp->tun_if.if_dunit));
+ TAILQ_REMOVE(&tunhead, tp, tun_list);
+ dev = tp->tun_dev;
bpfdetach(&tp->tun_if);
if_detach(&tp->tun_if);
- KASSERT(dev->si_flags & SI_NAMED, ("Missing make_dev"));
+ destroy_dev(dev);
free(tp, M_TUN);
}
-
- /*
- * Destroying tunbasedev results in all of our make_dev()s
- * conveniently going away.
- */
- if (tunbasedev != NOUDEV)
- destroy_dev(udev2dev(tunbasedev, 0));
-
+ clone_cleanup(&tunclones);
break;
}
return 0;
@@ -222,14 +202,12 @@ tuncreate(dev_t dev)
struct tun_softc *sc;
struct ifnet *ifp;
- if (!(dev->si_flags & SI_NAMED))
- dev = make_dev(&tun_cdevsw, minor(dev),
- UID_UUCP, GID_DIALER, 0600, "tun%d", dev2unit(dev));
+ dev->si_flags &= ~SI_CHEAPCLONE;
MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO);
sc->tun_flags = TUN_INITED;
- sc->next = tunhead;
- tunhead = sc;
+ sc->tun_dev = dev;
+ TAILQ_INSERT_TAIL(&tunhead, sc, tun_list);
ifp = &sc->tun_if;
if_initname(ifp, TUNNAME, dev2unit(dev));
@@ -249,32 +227,21 @@ tuncreate(dev_t dev)
static int
tunopen(dev_t dev, int flag, int mode, struct thread *td)
{
- struct resource *r;
struct ifnet *ifp;
struct tun_softc *tp;
- int unit;
-
- unit = dev2unit(dev);
- if (unit > IF_MAXUNIT)
- return (ENXIO);
-
- r = rman_reserve_resource(&tununits, unit, unit, 1,
- RF_ALLOCATED | RF_ACTIVE, NULL);
- if (r == NULL)
- return (EBUSY);
-
- dev->si_flags &= ~SI_CHEAPCLONE;
tp = dev->si_drv1;
if (!tp) {
tuncreate(dev);
tp = dev->si_drv1;
}
- KASSERT(!(tp->tun_flags & TUN_OPEN), ("Resource & flags out-of-sync"));
- tp->tun_unit = r;
- tp->tun_pid = td->td_proc->p_pid;
- ifp = &tp->tun_if;
+
+ if (tp->tun_proc != NULL && tp->tun_proc != td->td_proc)
+ return (EBUSY);
+ tp->tun_proc = td->td_proc;
+
tp->tun_flags |= TUN_OPEN;
+ ifp = &tp->tun_if;
TUNDEBUG(ifp, "open\n");
return (0);
@@ -290,14 +257,12 @@ tunclose(dev_t dev, int foo, int bar, struct thread *td)
struct tun_softc *tp;
struct ifnet *ifp;
int s;
- int err;
tp = dev->si_drv1;
ifp = &tp->tun_if;
- KASSERT(tp->tun_unit, ("Unit %d not marked open", tp->tun_if.if_dunit));
tp->tun_flags &= ~TUN_OPEN;
- tp->tun_pid = 0;
+ tp->tun_proc = NULL;
/*
* junk all pending output
@@ -325,11 +290,7 @@ tunclose(dev_t dev, int foo, int bar, struct thread *td)
funsetown(&tp->tun_sigio);
selwakeuppri(&tp->tun_rsel, PZERO + 1);
-
TUNDEBUG (ifp, "closed\n");
- err = rman_release_resource(tp->tun_unit);
- KASSERT(err == 0, ("Unit %d failed to release", tp->tun_if.if_dunit));
-
return (0);
}
@@ -384,9 +345,9 @@ tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
switch(cmd) {
case SIOCGIFSTATUS:
ifs = (struct ifstat *)data;
- if (tp->tun_pid)
+ if (tp->tun_proc)
sprintf(ifs->ascii + strlen(ifs->ascii),
- "\tOpened by PID %d\n", tp->tun_pid);
+ "\tOpened by PID %d\n", tp->tun_proc->p_pid);
break;
case SIOCSIFADDR:
error = tuninit(ifp);
@@ -573,7 +534,7 @@ tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
}
break;
case TUNSIFPID:
- tp->tun_pid = curthread->td_proc->p_pid;
+ tp->tun_proc = curthread->td_proc;
break;
case FIONBIO:
break;
diff --git a/sys/net/if_tunvar.h b/sys/net/if_tunvar.h
deleted file mode 100644
index cda53f0..0000000
--- a/sys/net/if_tunvar.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*-
- * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NET_IF_TUNVAR_H_
-#define _NET_IF_TUNVAR_H_
-
-struct tun_softc {
- u_short tun_flags; /* misc flags */
-#define TUN_OPEN 0x0001
-#define TUN_INITED 0x0002
-#define TUN_RCOLL 0x0004
-#define TUN_IASET 0x0008
-#define TUN_DSTADDR 0x0010
-#define TUN_LMODE 0x0020
-#define TUN_RWAIT 0x0040
-#define TUN_ASYNC 0x0080
-#define TUN_IFHEAD 0x0100
-
-#define TUN_READY (TUN_OPEN | TUN_INITED)
-
- pid_t tun_pid; /* PID of process to open */
- struct ifnet tun_if; /* the interface */
- struct sigio *tun_sigio; /* information for async I/O */
- struct selinfo tun_rsel; /* read select */
-
- struct tun_softc *next; /* Next softc in list */
- struct resource *tun_unit; /* resource allocated for this unit */
-};
-
-#endif /* !_NET_IF_TUNVAR_H_ */
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index fb39f08..a203c11 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -64,10 +64,12 @@ struct cdev {
#define SI_CONSOPEN 0x0040 /* opened by console */
#define SI_DUMPDEV 0x0080 /* is kernel dumpdev */
#define SI_CANDELETE 0x0100 /* can do BIO_DELETE */
+#define SI_CLONELIST 0x0200 /* on a clone list */
struct timespec si_atime;
struct timespec si_ctime;
struct timespec si_mtime;
udev_t si_udev;
+ LIST_ENTRY(cdev) si_clone;
LIST_ENTRY(cdev) si_hash;
SLIST_HEAD(, vnode) si_hlist;
LIST_HEAD(, cdev) si_children;
@@ -125,6 +127,7 @@ struct buf;
struct thread;
struct uio;
struct knote;
+struct clonedevs;
/*
* Note: d_thread_t is provided as a transition aid for those drivers
@@ -198,6 +201,7 @@ typedef int dumper_t(
#define D_NAGGED 0x00020000 /* nagged about missing make_dev() */
#define D_TRACKCLOSE 0x00080000 /* track all closes */
#define D_MMAP_ANON 0x00100000 /* special treatment in vm_mmap.c */
+#define D_PSEUDO 0x00200000 /* make_dev() can return NULL */
#define D_NOGIANT 0x00400000 /* Doesn't want Giant */
/*
@@ -274,6 +278,11 @@ static moduledata_t name##_mod = { \
DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE)
+void clone_cleanup(struct clonedevs **);
+#define CLONE_UNITMASK 0xfffff
+#define CLONE_FLAG0 (CLONE_UNITMASK + 1)
+int clone_create(struct clonedevs **, struct cdevsw *, int *unit, dev_t *dev, u_int extra);
+
int count_dev(dev_t _dev);
void destroy_dev(dev_t _dev);
struct cdevsw *devsw(dev_t _dev);
diff --git a/sys/sys/linedisc.h b/sys/sys/linedisc.h
index fb39f08..a203c11 100644
--- a/sys/sys/linedisc.h
+++ b/sys/sys/linedisc.h
@@ -64,10 +64,12 @@ struct cdev {
#define SI_CONSOPEN 0x0040 /* opened by console */
#define SI_DUMPDEV 0x0080 /* is kernel dumpdev */
#define SI_CANDELETE 0x0100 /* can do BIO_DELETE */
+#define SI_CLONELIST 0x0200 /* on a clone list */
struct timespec si_atime;
struct timespec si_ctime;
struct timespec si_mtime;
udev_t si_udev;
+ LIST_ENTRY(cdev) si_clone;
LIST_ENTRY(cdev) si_hash;
SLIST_HEAD(, vnode) si_hlist;
LIST_HEAD(, cdev) si_children;
@@ -125,6 +127,7 @@ struct buf;
struct thread;
struct uio;
struct knote;
+struct clonedevs;
/*
* Note: d_thread_t is provided as a transition aid for those drivers
@@ -198,6 +201,7 @@ typedef int dumper_t(
#define D_NAGGED 0x00020000 /* nagged about missing make_dev() */
#define D_TRACKCLOSE 0x00080000 /* track all closes */
#define D_MMAP_ANON 0x00100000 /* special treatment in vm_mmap.c */
+#define D_PSEUDO 0x00200000 /* make_dev() can return NULL */
#define D_NOGIANT 0x00400000 /* Doesn't want Giant */
/*
@@ -274,6 +278,11 @@ static moduledata_t name##_mod = { \
DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE)
+void clone_cleanup(struct clonedevs **);
+#define CLONE_UNITMASK 0xfffff
+#define CLONE_FLAG0 (CLONE_UNITMASK + 1)
+int clone_create(struct clonedevs **, struct cdevsw *, int *unit, dev_t *dev, u_int extra);
+
int count_dev(dev_t _dev);
void destroy_dev(dev_t _dev);
struct cdevsw *devsw(dev_t _dev);
OpenPOWER on IntegriCloud