/* * Do local shutdown processing.. * All our links and the name have already been removed. * If we are a persistant device, we might refuse to go away. * In the case of a persistant node we signal the framework that we * are still in business by clearing the NGF_INVALID bit. However * If we find the NGF_REALLY_DIE bit set, this means that * we REALLY need to die (e.g. hardware removed). * This would have been set using the NG_NODE_REALLY_DIE(node) * macro in some device dependent function (not shown here) before * calling ng_rmnode_self(). */ static int ng_xxx_shutdown(node_p node) { const xxx_p privdata = NG_NODE_PRIVATE(node); #ifndef PERSISTANT_NODE NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(node); free(privdata, M_NETGRAPH); #else if (node->nd_flags & NGF_REALLY_DIE) { /* * WE came here because the widget card is being unloaded, * so stop being persistant. * Actually undo all the things we did on creation. */ NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(privdata->node); free(privdata, M_NETGRAPH); return (0); } NG_NODE_REVIVE(node); /* tell ng_rmnode() we will persist */ #endif /* PERSISTANT_NODE */ return (0); }
static int ng_btsocket_hci_raw_node_shutdown(node_p node) { int error = 0; NG_NODE_UNREF(node); error = ng_make_node_common(&typestruct, &ng_btsocket_hci_raw_node); if (error != 0) { NG_BTSOCKET_HCI_RAW_ALERT( "%s: Could not create Netgraph node, error=%d\n", __func__, error); ng_btsocket_hci_raw_node = NULL; return (ENOMEM); } error = ng_name_node(ng_btsocket_hci_raw_node, NG_BTSOCKET_HCI_RAW_NODE_TYPE); if (error != 0) { NG_BTSOCKET_HCI_RAW_ALERT( "%s: Could not name Netgraph node, error=%d\n", __func__, error); NG_NODE_UNREF(ng_btsocket_hci_raw_node); ng_btsocket_hci_raw_node = NULL; return (EINVAL); } return (0); } /* ng_btsocket_hci_raw_node_shutdown */
static int ng_bt3c_shutdown(node_p node) { bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); /* Let old node go */ NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(node); /* Create new fresh one if we are not going down */ if (sc == NULL) goto out; /* Create new Netgraph node */ if (ng_make_node_common(&typestruct, &sc->node) != 0) { device_printf(sc->dev, "Could not create Netgraph node\n"); sc->node = NULL; goto out; } /* Name new Netgraph node */ if (ng_name_node(sc->node, device_get_nameunit(sc->dev)) != 0) { device_printf(sc->dev, "Could not name Netgraph node\n"); NG_NODE_UNREF(sc->node); sc->node = NULL; goto out; } NG_NODE_SET_PRIVATE(sc->node, sc); out: return (0); } /* ng_bt3c_shutdown */
/* * Destroy node */ static int ng_ksocket_shutdown(node_p node) { const priv_p priv = NG_NODE_PRIVATE(node); priv_p embryo; /* Close our socket (if any) */ if (priv->so != NULL) { atomic_clear_int(&priv->so->so_rcv.ssb_flags, SSB_UPCALL); atomic_clear_int(&priv->so->so_snd.ssb_flags, SSB_UPCALL); priv->so->so_upcall = NULL; soclose(priv->so, FNONBLOCK); priv->so = NULL; } /* If we are an embryo, take ourselves out of the parent's list */ if (priv->flags & KSF_EMBRYONIC) { LIST_REMOVE(priv, siblings); priv->flags &= ~KSF_EMBRYONIC; } /* Remove any embryonic children we have */ while (!LIST_EMPTY(&priv->embryos)) { embryo = LIST_FIRST(&priv->embryos); ng_rmnode_self(embryo->node); } /* Take down netgraph node */ bzero(priv, sizeof(*priv)); kfree(priv, M_NETGRAPH); NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(node); /* let the node escape */ return (0); }
/* * Shutdown node */ static int ngfrm_shutdown(node_p node) { const sc_p sc = NG_NODE_PRIVATE(node); NG_NODE_SET_PRIVATE(node, NULL); FREE(sc, M_NETGRAPH); NG_NODE_UNREF(node); return (0); }
/* * Do local shutdown processing.. * Cut any remaining links and free our local resources. */ static int nglmi_shutdown(node_p node) { const sc_p sc = NG_NODE_PRIVATE(node); NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(sc->node); free(sc, M_NETGRAPH); return (0); }
static int ng_vboxnetflt_shutdown(node_p node) { PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node); bool fActive; /* Prevent node shutdown if we're active */ if (pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE) return (EBUSY); NG_NODE_UNREF(node); return (0); }
static int ng_split_shutdown(node_p node) { const priv_p priv = NG_NODE_PRIVATE(node); NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(node); free(priv, M_NETGRAPH); return (0); }
/* * Do local shutdown processing.. * We are a persistant device, we refuse to go away, and * only remove our links and reset ourself. */ Static int ng_udbp_rmnode(node_p node) { const udbp_p sc = NG_NODE_PRIVATE(node); int err; if (sc->flags & DISCONNECTED) { /* * WE are really going away.. hardware must have gone. * Assume that the hardware drive part will clear up the * sc, in fact it may already have done so.. * In which case we may have just segfaulted..XXX */ return (0); } /* stolen from attach routine */ /* Drain the queues */ IF_DRAIN(&sc->xmitq_hipri); IF_DRAIN(&sc->xmitq); sc->packets_in = 0; /* reset stats */ sc->packets_out = 0; NG_NODE_UNREF(node); /* forget it ever existed */ if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) { char nodename[128]; sprintf(nodename, "%s", USBDEVNAME(sc->sc_dev)); if ((err = ng_name_node(sc->node, nodename))) { NG_NODE_UNREF(sc->node); /* out damned spot! */ sc->flags &= ~NETGRAPH_INITIALISED; sc->node = NULL; } else { NG_NODE_SET_PRIVATE(sc->node, sc); } } return (err); }
static int ng_sscop_shutdown(node_p node) { struct priv *priv = NG_NODE_PRIVATE(node); sscop_destroy(priv->sscop); free(priv, M_NG_SSCOP); NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(node); return (0); }
/* * Shutdown processing * * This is tricky. If we have both a left and right hook, then we * probably want to extricate ourselves and leave the two peers * still linked to each other. Otherwise we should just shut down as * a normal node would. * * To keep the scope of info correct the routine to "extract" a node * from two links is in ng_base.c. */ static int ngt_shutdown(node_p node) { const sc_p privdata = NG_NODE_PRIVATE(node); #if 0 /* can never happen as cutlinks is already called */ if (privdata->left.hook && privdata->right.hook) ng_bypass(privdata->left.hook, privdata->right.hook); #endif NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(privdata->node); FREE(privdata, M_NETGRAPH); return (0); }
static int ng_ubt_shutdown(node_p node) { if (node->nd_flags & NGF_REALLY_DIE) { /* * We came here because the USB device is being * detached, so stop being persistent. */ NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(node); } else NG_NODE_REVIVE(node); /* tell ng_rmnode we are persisant */ return (0); } /* ng_ubt_shutdown */
/* * Do local shutdown processing. * In this case, that involves making sure the socket * knows we should be shutting down. */ static int ngs_shutdown(node_p node) { struct ngsock *const priv = NG_NODE_PRIVATE(node); struct ngpcb *const dpcbp = priv->datasock; struct ngpcb *const pcbp = priv->ctlsock; if (dpcbp != NULL) soisdisconnected(dpcbp->ng_socket); if (pcbp != NULL) soisdisconnected(pcbp->ng_socket); mtx_lock(&priv->mtx); priv->node = NULL; NG_NODE_SET_PRIVATE(node, NULL); ng_socket_free_priv(priv); NG_NODE_UNREF(node); return (0); }
/* * Remove a reference from node private data. */ static void ng_socket_free_priv(struct ngsock *priv) { mtx_assert(&priv->mtx, MA_OWNED); priv->refs--; if (priv->refs == 0) { mtx_destroy(&priv->mtx); kfree(priv, M_NETGRAPH_SOCK); return; } if ((priv->refs == 1) && (priv->node != NULL)) { node_p node = priv->node; priv->node = NULL; mtx_unlock(&priv->mtx); NG_NODE_UNREF(node); ng_rmnode_self(node); } else mtx_unlock(&priv->mtx); }
/* * Remove a reference from node private data. */ static void ng_socket_free_priv(struct ngsock *priv) { KKASSERT(mtx_owned(&priv->mtx)); priv->refs--; if (priv->refs == 0) { mtx_uninit(&priv->mtx); kfree(priv, M_NETGRAPH_SOCK); return; } if ((priv->refs == 1) && (priv->node != NULL)) { node_p node = priv->node; priv->node = NULL; mtx_unlock(&priv->mtx); NG_NODE_UNREF(node); ng_rmnode_self(node); } else mtx_unlock(&priv->mtx); }
/* * Destroy node */ static int ng_ksocket_shutdown(node_p node) { const priv_p priv = NG_NODE_PRIVATE(node); priv_p embryo; /* Close our socket (if any) */ if (priv->so != NULL) { SOCKBUF_LOCK(&priv->so->so_rcv); soupcall_clear(priv->so, SO_RCV); SOCKBUF_UNLOCK(&priv->so->so_rcv); SOCKBUF_LOCK(&priv->so->so_snd); soupcall_clear(priv->so, SO_SND); SOCKBUF_UNLOCK(&priv->so->so_snd); soclose(priv->so); priv->so = NULL; } /* If we are an embryo, take ourselves out of the parent's list */ if (priv->flags & KSF_EMBRYONIC) { LIST_REMOVE(priv, siblings); priv->flags &= ~KSF_EMBRYONIC; } /* Remove any embryonic children we have */ while (!LIST_EMPTY(&priv->embryos)) { embryo = LIST_FIRST(&priv->embryos); ng_rmnode_self(embryo->node); } /* Take down netgraph node */ bzero(priv, sizeof(*priv)); free(priv, M_NETGRAPH_KSOCKET); NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(node); /* let the node escape */ return (0); }
/* * Handle the first completed incoming connection, assumed to be already * on the socket's so_comp queue. */ static void ng_ksocket_finish_accept(priv_p priv) { struct socket *const head = priv->so; struct socket *so; struct sockaddr *sa = NULL; struct ng_mesg *resp; struct ng_ksocket_accept *resp_data; node_p node; priv_p priv2; int len; int error; ACCEPT_LOCK(); so = TAILQ_FIRST(&head->so_comp); if (so == NULL) { /* Should never happen */ ACCEPT_UNLOCK(); return; } TAILQ_REMOVE(&head->so_comp, so, so_list); head->so_qlen--; so->so_qstate &= ~SQ_COMP; so->so_head = NULL; SOCK_LOCK(so); soref(so); sosetstate(so, SS_NBIO); SOCK_UNLOCK(so); ACCEPT_UNLOCK(); /* XXX KNOTE(&head->so_rcv.sb_sel.si_note, 0); */ soaccept(so, &sa); len = OFFSETOF(struct ng_ksocket_accept, addr); if (sa != NULL) len += sa->sa_len; NG_MKMESSAGE(resp, NGM_KSOCKET_COOKIE, NGM_KSOCKET_ACCEPT, len, M_WAITOK | M_NULLOK); if (resp == NULL) { soclose(so); goto out; } resp->header.flags |= NGF_RESP; resp->header.token = priv->response_token; /* Clone a ksocket node to wrap the new socket */ error = ng_make_node_common(&ng_ksocket_typestruct, &node); if (error) { kfree(resp, M_NETGRAPH); soclose(so); goto out; } if (ng_ksocket_constructor(node) != 0) { NG_NODE_UNREF(node); kfree(resp, M_NETGRAPH); soclose(so); goto out; } priv2 = NG_NODE_PRIVATE(node); priv2->so = so; priv2->flags |= KSF_CLONED | KSF_EMBRYONIC; /* * Insert the cloned node into a list of embryonic children * on the parent node. When a hook is created on the cloned * node it will be removed from this list. When the parent * is destroyed it will destroy any embryonic children it has. */ LIST_INSERT_HEAD(&priv->embryos, priv2, siblings); so->so_upcallarg = (caddr_t)node; so->so_upcall = ng_ksocket_incoming; SOCKBUF_LOCK(&so->so_rcv); so->so_rcv.sb_flags |= SB_UPCALL; SOCKBUF_UNLOCK(&so->so_rcv); SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_flags |= SB_UPCALL; SOCKBUF_UNLOCK(&so->so_snd); /* Fill in the response data and send it or return it to the caller */ resp_data = (struct ng_ksocket_accept *)resp->data; resp_data->nodeid = NG_NODE_ID(node); if (sa != NULL) bcopy(sa, &resp_data->addr, sa->sa_len); NG_SEND_MSG_ID(error, node, resp, priv->response_addr, 0); out: if (sa != NULL) kfree(sa, M_SONAME); }
static int bt3c_pccard_attach(device_t dev) { bt3c_softc_p sc = (bt3c_softc_p) device_get_softc(dev); /* Allocate I/O ports */ sc->iobase_rid = 0; sc->iobase = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &sc->iobase_rid, 8, RF_ACTIVE); if (sc->iobase == NULL) { device_printf(dev, "Could not allocate I/O ports\n"); goto bad; } sc->iot = rman_get_bustag(sc->iobase); sc->ioh = rman_get_bushandle(sc->iobase); /* Allocate IRQ */ sc->irq_rid = 0; sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, RF_ACTIVE); if (sc->irq == NULL) { device_printf(dev, "Could not allocate IRQ\n"); goto bad; } sc->irq_cookie = NULL; if (bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, NULL, bt3c_intr, sc, &sc->irq_cookie) != 0) { device_printf(dev, "Could not setup ISR\n"); goto bad; } /* Attach handler to TTY SWI thread */ sc->ith = NULL; if (swi_add(&tty_intr_event, device_get_nameunit(dev), bt3c_swi_intr, sc, SWI_TTY, 0, &sc->ith) < 0) { device_printf(dev, "Could not setup SWI ISR\n"); goto bad; } /* Create Netgraph node */ if (ng_make_node_common(&typestruct, &sc->node) != 0) { device_printf(dev, "Could not create Netgraph node\n"); sc->node = NULL; goto bad; } /* Name Netgraph node */ if (ng_name_node(sc->node, device_get_nameunit(dev)) != 0) { device_printf(dev, "Could not name Netgraph node\n"); NG_NODE_UNREF(sc->node); sc->node = NULL; goto bad; } sc->dev = dev; sc->debug = NG_BT3C_WARN_LEVEL; sc->inq.ifq_maxlen = sc->outq.ifq_maxlen = BT3C_DEFAULTQLEN; mtx_init(&sc->inq.ifq_mtx, "BT3C inq", NULL, MTX_DEF); mtx_init(&sc->outq.ifq_mtx, "BT3C outq", NULL, MTX_DEF); sc->state = NG_BT3C_W4_PKT_IND; sc->want = 1; NG_NODE_SET_PRIVATE(sc->node, sc); return (0); bad: if (sc->ith != NULL) { swi_remove(sc->ith); sc->ith = NULL; } if (sc->irq != NULL) { if (sc->irq_cookie != NULL) bus_teardown_intr(dev, sc->irq, sc->irq_cookie); bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq); sc->irq = NULL; sc->irq_rid = 0; } if (sc->iobase != NULL) { bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase); sc->iobase = NULL; sc->iobase_rid = 0; } return (ENXIO); } /* bt3c_pccacd_attach */
static int ubt_attach(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); struct ubt_softc *sc = device_get_softc(dev); struct usb_endpoint_descriptor *ed; struct usb_interface_descriptor *id; struct usb_interface *iface; uint16_t wMaxPacketSize; uint8_t alt_index, i, j; uint8_t iface_index[2] = { 0, 1 }; device_set_usb_desc(dev); sc->sc_dev = dev; sc->sc_debug = NG_UBT_WARN_LEVEL; /* * Create Netgraph node */ if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) { UBT_ALERT(sc, "could not create Netgraph node\n"); return (ENXIO); } /* Name Netgraph node */ if (ng_name_node(sc->sc_node, device_get_nameunit(dev)) != 0) { UBT_ALERT(sc, "could not name Netgraph node\n"); NG_NODE_UNREF(sc->sc_node); return (ENXIO); } NG_NODE_SET_PRIVATE(sc->sc_node, sc); NG_NODE_FORCE_WRITER(sc->sc_node); /* * Initialize device softc structure */ /* initialize locks */ mtx_init(&sc->sc_ng_mtx, "ubt ng", NULL, MTX_DEF); mtx_init(&sc->sc_if_mtx, "ubt if", NULL, MTX_DEF | MTX_RECURSE); /* initialize packet queues */ NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN); NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN); NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN); /* initialize glue task */ TASK_INIT(&sc->sc_task, 0, ubt_task, sc); /* * Configure Bluetooth USB device. Discover all required USB * interfaces and endpoints. * * USB device must present two interfaces: * 1) Interface 0 that has 3 endpoints * 1) Interrupt endpoint to receive HCI events * 2) Bulk IN endpoint to receive ACL data * 3) Bulk OUT endpoint to send ACL data * * 2) Interface 1 then has 2 endpoints * 1) Isochronous IN endpoint to receive SCO data * 2) Isochronous OUT endpoint to send SCO data * * Interface 1 (with isochronous endpoints) has several alternate * configurations with different packet size. */ /* * For interface #1 search alternate settings, and find * the descriptor with the largest wMaxPacketSize */ wMaxPacketSize = 0; alt_index = 0; i = 0; j = 0; ed = NULL; /* * Search through all the descriptors looking for the largest * packet size: */ while ((ed = (struct usb_endpoint_descriptor *)usb_desc_foreach( usbd_get_config_descriptor(uaa->device), (struct usb_descriptor *)ed))) { if ((ed->bDescriptorType == UDESC_INTERFACE) && (ed->bLength >= sizeof(*id))) { id = (struct usb_interface_descriptor *)ed; i = id->bInterfaceNumber; j = id->bAlternateSetting; } if ((ed->bDescriptorType == UDESC_ENDPOINT) && (ed->bLength >= sizeof(*ed)) && (i == 1)) { uint16_t temp; temp = UGETW(ed->wMaxPacketSize); if (temp > wMaxPacketSize) { wMaxPacketSize = temp; alt_index = j; } } } /* Set alt configuration on interface #1 only if we found it */ if (wMaxPacketSize > 0 && usbd_set_alt_interface_index(uaa->device, 1, alt_index)) { UBT_ALERT(sc, "could not set alternate setting %d " \ "for interface 1!\n", alt_index); goto detach; } /* Setup transfers for both interfaces */ if (usbd_transfer_setup(uaa->device, iface_index, sc->sc_xfer, ubt_config, UBT_N_TRANSFER, sc, &sc->sc_if_mtx)) { UBT_ALERT(sc, "could not allocate transfers\n"); goto detach; } /* Claim all interfaces belonging to the Bluetooth part */ for (i = 1;; i++) { iface = usbd_get_iface(uaa->device, i); if (iface == NULL) break; id = usbd_get_interface_descriptor(iface); if ((id != NULL) && (id->bInterfaceClass == UICLASS_WIRELESS) && (id->bInterfaceSubClass == UISUBCLASS_RF) && (id->bInterfaceProtocol == UIPROTO_BLUETOOTH)) { usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); } } return (0); /* success */ detach: ubt_detach(dev); return (ENXIO); } /* ubt_attach */