static int snp_modevent(module_t mod, int type, void *data) { int i; lwkt_gettoken(&tty_token); switch (type) { case MOD_LOAD: snooplinedisc = ldisc_register(LDISC_LOAD, &snpdisc); make_autoclone_dev(&snp_ops, &DEVFS_CLONE_BITMAP(snp), snpclone, UID_ROOT, GID_WHEEL, 0600, "snp"); for (i = 0; i < SNP_PREALLOCATED_UNITS; i++) { make_dev(&snp_ops, i, UID_ROOT, GID_WHEEL, 0600, "snp%d", i); devfs_clone_bitmap_set(&DEVFS_CLONE_BITMAP(snp), i); } break; case MOD_UNLOAD: if (!LIST_EMPTY(&snp_sclist)) { lwkt_reltoken(&tty_token); return (EBUSY); } ldisc_deregister(snooplinedisc); devfs_clone_handler_del("snp"); dev_ops_remove_all(&snp_ops); devfs_clone_bitmap_uninit(&DEVFS_CLONE_BITMAP(snp)); break; default: break; } lwkt_reltoken(&tty_token); return (0); }
static int vnclone(struct dev_clone_args *ap) { int unit; unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(vn), 0); ap->a_dev = vn_create(unit, &DEVFS_CLONE_BITMAP(vn), 1); return 0; }
static int snpclone(struct dev_clone_args *ap) { int unit; lwkt_gettoken(&tty_token); unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(snp), 0); ap->a_dev = make_only_dev(&snp_ops, unit, UID_ROOT, GID_WHEEL, 0600, "snp%d", unit); lwkt_reltoken(&tty_token); return 0; }
static int uether_modevent(module_t mod, int type, void *data) { static int attached = 0; switch (type) { case MOD_LOAD: if (attached) return (EEXIST); devfs_clone_bitmap_init(&DEVFS_CLONE_BITMAP(ue)); attached = 1; break; case MOD_UNLOAD: devfs_clone_bitmap_uninit(&DEVFS_CLONE_BITMAP(ue)); break; default: return (EOPNOTSUPP); } return (0); }
/* * pti_done() releases the reference and checks to see if both sides have * been closed on a unix98 pty, allowing us to destroy the device and * release resources. * * We do not release resources on non-unix98 ptys. Those are left * statically allocated. */ static void pti_done(struct pt_ioctl *pti) { lwkt_gettoken(&tty_token); if (--pti->pt_refs == 0) { #ifdef UNIX98_PTYS cdev_t dev; int uminor_no; /* * Only unix09 ptys are freed up */ if ((pti->pt_flags & PF_UNIX98) == 0) { lwkt_reltoken(&tty_token); return; } /* * Interlock open attempts against termination by setting * PF_TERMINATED. This allows us to block while cleaning * out the device infrastructure. * * Do not terminate the tty if it still has a session * association (t_refs). */ if ((pti->pt_flags & (PF_SOPEN|PF_MOPEN)) == 0 && pti->pt_tty.t_refs == 0) { pti->pt_flags |= PF_TERMINATED; uminor_no = pti->pt_uminor; if ((dev = pti->devs) != NULL) { dev->si_drv1 = NULL; pti->devs = NULL; destroy_dev(dev); } if ((dev = pti->devc) != NULL) { dev->si_drv1 = NULL; pti->devc = NULL; destroy_dev(dev); } ttyunregister(&pti->pt_tty); devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(pty), uminor_no); kfree(pti, M_PTY); } #endif } lwkt_reltoken(&tty_token); }
static void ptc_drvinit(void *unused) { int i; #ifdef UNIX98_PTYS /* * Unix98 pty stuff. * Create the clonable base device. */ make_autoclone_dev(&ptc_ops, &DEVFS_CLONE_BITMAP(pty), ptyclone, 0, 0, 0666, "ptmx"); #endif for (i = 0; i < 256; i++) { ptyinit(i); } }
static int ptyclone(struct dev_clone_args *ap) { int unit; struct pt_ioctl *pt; /* * Limit the number of unix98 pty (slave) devices to 1000, as * the utmp(5) format only allows for 8 bytes for the tty, * "pts/XXX". * If this limit is reached, we don't clone and return error * to devfs. */ unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(pty), 1000); if (unit < 0) { ap->a_dev = NULL; return 1; } pt = kmalloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO); pt->devc = make_only_dev(&ptc98_ops, unit, ap->a_cred->cr_ruid, 0, 0600, "ptm/%d", unit); pt->devs = make_dev(&pts98_ops, unit, ap->a_cred->cr_ruid, GID_TTY, 0620, "pts/%d", unit); ap->a_dev = pt->devc; pt->devs->si_flags |= SI_OVERRIDE; /* uid, gid, perms from dev */ pt->devc->si_flags |= SI_OVERRIDE; /* uid, gid, perms from dev */ pt->pt_tty.t_dev = pt->devs; pt->pt_flags |= PF_UNIX98; pt->pt_uminor = unit; pt->devs->si_drv1 = pt->devc->si_drv1 = pt; pt->devs->si_tty = pt->devc->si_tty = &pt->pt_tty; ttyregister(&pt->pt_tty); return 0; }
static int vnclose(struct dev_close_args *ap) { cdev_t dev = ap->a_head.a_dev; struct vn_softc *vn; vn = dev->si_drv1; KKASSERT(vn != NULL); vn->sc_flags &= ~VNF_OPENED; /* The disk has been detached and can now be safely destroyed */ if (vn->sc_flags & VNF_DESTROY) { KKASSERT(disk_getopencount(&vn->sc_disk) == 0); disk_destroy(&vn->sc_disk); devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(vn), dkunit(dev)); SLIST_REMOVE(&vn_list, vn, vn_softc, sc_list); kfree(vn, M_VN); } return (0); }
static int snpclose(struct dev_close_args *ap) { cdev_t dev = ap->a_head.a_dev; struct snoop *snp; int ret; lwkt_gettoken(&tty_token); snp = dev->si_drv1; snp->snp_blen = 0; LIST_REMOVE(snp, snp_list); kfree(snp->snp_buf, M_SNP); snp->snp_flags &= ~SNOOP_OPEN; dev->si_drv1 = NULL; if (dev->si_uminor >= SNP_PREALLOCATED_UNITS) { devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(snp), dev->si_uminor); destroy_dev(dev); } ret = snp_detach(snp); lwkt_reltoken(&tty_token); return ret; }
void uether_ifdetach(struct usb_ether *ue) { struct ifnet *ifp; /* wait for any post attach or other command to complete */ usb_proc_drain(&ue->ue_tq); /* read "ifnet" pointer after taskqueue drain */ ifp = uether_getifp(ue); if (ifp != NULL) { /* we are not running any more */ UE_LOCK(ue); ifp->if_flags &= ~IFF_RUNNING; UE_UNLOCK(ue); /* drain any callouts */ usb_callout_drain(&ue->ue_watchdog); /* detach miibus */ if (ue->ue_miibus != NULL) { device_delete_child(ue->ue_dev, ue->ue_miibus); } /* detach ethernet */ ether_ifdetach(ifp); /* free sysctl */ sysctl_ctx_free(&ue->ue_sysctl_ctx); /* free unit */ devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(ue), ue->ue_unit); } /* free taskqueue, if any */ usb_proc_free(&ue->ue_tq); }
static void ue_attach_post_task(struct usb_proc_msg *_task) { struct usb_ether_cfg_task *task = (struct usb_ether_cfg_task *)_task; struct usb_ether *ue = task->ue; struct ifnet *ifp = uether_getifp(ue); int error; char num[14]; /* sufficient for 32 bits */ /* first call driver's post attach routine */ ue->ue_methods->ue_attach_post(ue); UE_UNLOCK(ue); KKASSERT(!lockowned(ue->ue_lock)); ue->ue_unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(ue), 0); usb_callout_init_mtx(&ue->ue_watchdog, ue->ue_lock, 0); sysctl_ctx_init(&ue->ue_sysctl_ctx); KKASSERT(!lockowned(ue->ue_lock)); error = 0; ifp->if_softc = ue; if_initname(ifp, "ue", ue->ue_unit); if (ue->ue_methods->ue_attach_post_sub != NULL) { error = ue->ue_methods->ue_attach_post_sub(ue); KKASSERT(!lockowned(ue->ue_lock)); } else { ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; if (ue->ue_methods->ue_ioctl != NULL) ifp->if_ioctl = ue->ue_methods->ue_ioctl; else ifp->if_ioctl = uether_ioctl; ifp->if_start = ue_start; ifp->if_init = ue_init; ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); ifq_set_ready(&ifp->if_snd); if (ue->ue_methods->ue_mii_upd != NULL && ue->ue_methods->ue_mii_sts != NULL) { error = mii_phy_probe(ue->ue_dev, &ue->ue_miibus, ue_ifmedia_upd, ue->ue_methods->ue_mii_sts); } } if (error) { device_printf(ue->ue_dev, "attaching PHYs failed\n"); goto fail; } if_printf(ifp, "<USB Ethernet> on %s\n", device_get_nameunit(ue->ue_dev)); ether_ifattach(ifp, ue->ue_eaddr, NULL); /* Tell upper layer we support VLAN oversized frames. */ if (ifp->if_capabilities & IFCAP_VLAN_MTU) ifp->if_hdrlen = sizeof(struct ether_vlan_header); ksnprintf(num, sizeof(num), "%u", ue->ue_unit); ue->ue_sysctl_oid = SYSCTL_ADD_NODE(&ue->ue_sysctl_ctx, &SYSCTL_NODE_CHILDREN(_net, ue), OID_AUTO, num, CTLFLAG_RD, NULL, ""); SYSCTL_ADD_PROC(&ue->ue_sysctl_ctx, SYSCTL_CHILDREN(ue->ue_sysctl_oid), OID_AUTO, "%parent", CTLTYPE_STRING | CTLFLAG_RD, ue, 0, ue_sysctl_parent, "A", "parent device"); KKASSERT(!lockowned(ue->ue_lock)); UE_LOCK(ue); return; fail: devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(ue), ue->ue_unit); UE_LOCK(ue); return; }