summaryrefslogtreecommitdiffstats
path: root/sys/dev/nmdm/nmdm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/nmdm/nmdm.c')
-rw-r--r--sys/dev/nmdm/nmdm.c169
1 files changed, 85 insertions, 84 deletions
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);
OpenPOWER on IntegriCloud