summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/udbp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/udbp.c')
-rw-r--r--sys/dev/usb/udbp.c860
1 files changed, 0 insertions, 860 deletions
diff --git a/sys/dev/usb/udbp.c b/sys/dev/usb/udbp.c
deleted file mode 100644
index 523184f..0000000
--- a/sys/dev/usb/udbp.c
+++ /dev/null
@@ -1,860 +0,0 @@
-/*-
- * Copyright (c) 1996-2000 Whistle Communications, Inc.
- * 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.
- * 3. Neither the name of author nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY NICK HIBMA 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.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/* Driver for arbitrary double bulk pipe devices.
- * The driver assumes that there will be the same driver on the other side.
- *
- * XXX Some more information on what the framing of the IP packets looks like.
- *
- * To take full advantage of bulk transmission, packets should be chosen
- * between 1k and 5k in size (1k to make sure the sending side starts
- * straming, and <5k to avoid overflowing the system with small TDs).
- */
-
-
-/* probe/attach/detach:
- * Connect the driver to the hardware and netgraph
- *
- * udbp_setup_out_transfer(sc);
- * Setup an outbound transfer. Only one transmit can be active at the same
- * time.
- * XXX If it is required that the driver is able to queue multiple requests
- * let me know. That is slightly difficult, due to the fact that we
- * cannot call usbd_alloc_xfer in int context.
- *
- * udbp_setup_in_transfer(sc)
- * Prepare an in transfer that will be waiting for data to come in. It
- * is submitted and sits there until data is available.
- * The callback resubmits a new transfer on completion.
- *
- * The reason we submit a bulk in transfer is that USB does not know about
- * interrupts. The bulk transfer continuously polls the device for data.
- * While the device has no data available, the device NAKs the TDs. As soon
- * as there is data, the transfer happens and the data comes flowing in.
- *
- * In case you were wondering, interrupt transfers happen exactly that way.
- * It therefore doesn't make sense to use the interrupt pipe to signal
- * 'data ready' and then schedule a bulk transfer to fetch it. That would
- * incur a 2ms delay at least, without reducing bandwidth requirements.
- *
- */
-
-
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/file.h>
-#include <sys/selinfo.h>
-#include <sys/poll.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/ctype.h>
-#include <sys/errno.h>
-#include <sys/sysctl.h>
-#include <net/if.h>
-#include <machine/bus.h>
-
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usbdivar.h>
-#include <dev/usb/usbhid.h>
-
-#include "usbdevs.h"
-
-
-#include <netgraph/ng_message.h>
-#include <netgraph/ng_parse.h>
-#include <dev/usb/udbp.h>
-#include <netgraph/netgraph.h>
-
-#ifdef USB_DEBUG
-#define DPRINTF(x) if (udbpdebug) printf x
-#define DPRINTFN(n,x) if (udbpdebug>(n)) printf x
-int udbpdebug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, udbp, CTLFLAG_RW, 0, "USB udbp");
-SYSCTL_INT(_hw_usb_udbp, OID_AUTO, debug, CTLFLAG_RW,
- &udbpdebug, 0, "udbp debug level");
-#else
-#define DPRINTF(x)
-#define DPRINTFN(n,x)
-#endif
-
-#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
-
-#define UDBP_TIMEOUT 2000 /* timeout on outbound transfers, in msecs */
-#define UDBP_BUFFERSIZE 2048 /* maximum number of bytes in one transfer */
-
-
-struct udbp_softc {
- device_t sc_dev; /* base device */
- usbd_interface_handle sc_iface;
-
- usbd_pipe_handle sc_bulkin_pipe;
- int sc_bulkin;
- usbd_xfer_handle sc_bulkin_xfer;
- void *sc_bulkin_buffer;
- int sc_bulkin_bufferlen;
- int sc_bulkin_datalen;
-
- usbd_pipe_handle sc_bulkout_pipe;
- int sc_bulkout;
- usbd_xfer_handle sc_bulkout_xfer;
- void *sc_bulkout_buffer;
- int sc_bulkout_bufferlen;
- int sc_bulkout_datalen;
-
- int flags;
-# define DISCONNECTED 0x01
-# define OUT_BUSY 0x02
-# define NETGRAPH_INITIALISED 0x04
- node_p node; /* back pointer to node */
- hook_p hook; /* pointer to the hook */
- u_int packets_in; /* packets in from downstream */
- u_int packets_out; /* packets out towards downstream */
- struct ifqueue xmitq_hipri; /* hi-priority transmit queue */
- struct ifqueue xmitq; /* low-priority transmit queue */
-
-};
-typedef struct udbp_softc *udbp_p;
-
-
-
-static ng_constructor_t ng_udbp_constructor;
-static ng_rcvmsg_t ng_udbp_rcvmsg;
-static ng_shutdown_t ng_udbp_rmnode;
-static ng_newhook_t ng_udbp_newhook;
-static ng_connect_t ng_udbp_connect;
-static ng_rcvdata_t ng_udbp_rcvdata;
-static ng_disconnect_t ng_udbp_disconnect;
-
-/* Parse type for struct ngudbpstat */
-static const struct ng_parse_struct_field
- ng_udbp_stat_type_fields[] = NG_UDBP_STATS_TYPE_INFO;
-static const struct ng_parse_type ng_udbp_stat_type = {
- &ng_parse_struct_type,
- &ng_udbp_stat_type_fields
-};
-
-/* List of commands and how to convert arguments to/from ASCII */
-static const struct ng_cmdlist ng_udbp_cmdlist[] = {
- {
- NGM_UDBP_COOKIE,
- NGM_UDBP_GET_STATUS,
- "getstatus",
- NULL,
- &ng_udbp_stat_type,
- },
- {
- NGM_UDBP_COOKIE,
- NGM_UDBP_SET_FLAG,
- "setflag",
- &ng_parse_int32_type,
- NULL
- },
- { 0 }
-};
-
-/* Netgraph node type descriptor */
-static struct ng_type ng_udbp_typestruct = {
- .version = NG_ABI_VERSION,
- .name = NG_UDBP_NODE_TYPE,
- .constructor = ng_udbp_constructor,
- .rcvmsg = ng_udbp_rcvmsg,
- .shutdown = ng_udbp_rmnode,
- .newhook = ng_udbp_newhook,
- .connect = ng_udbp_connect,
- .rcvdata = ng_udbp_rcvdata,
- .disconnect = ng_udbp_disconnect,
- .cmdlist = ng_udbp_cmdlist,
-};
-
-static int udbp_setup_in_transfer (udbp_p sc);
-static void udbp_in_transfer_cb (usbd_xfer_handle xfer,
- usbd_private_handle priv,
- usbd_status err);
-
-static int udbp_setup_out_transfer (udbp_p sc);
-static void udbp_out_transfer_cb (usbd_xfer_handle xfer,
- usbd_private_handle priv,
- usbd_status err);
-
-static device_probe_t udbp_match;
-static device_attach_t udbp_attach;
-static device_detach_t udbp_detach;
-
-static device_method_t udbp_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, udbp_match),
- DEVMETHOD(device_attach, udbp_attach),
- DEVMETHOD(device_detach, udbp_detach),
-
- { 0, 0 }
-};
-
-static driver_t udbp_driver = {
- "udbp",
- udbp_methods,
- sizeof(struct udbp_softc)
-};
-
-static devclass_t udbp_devclass;
-
-static int
-udbp_match(device_t self)
-{
- struct usb_attach_arg *uaa = device_get_ivars(self);
- usb_interface_descriptor_t *id;
- if (!uaa->iface)
- return (UMATCH_NONE);
- id = usbd_get_interface_descriptor(uaa->iface);
-
- /* XXX Julian, add the id of the device if you have one to test
- * things with. run 'usbdevs -v' and note the 3 ID's that appear.
- * The Vendor Id and Product Id are in hex and the Revision Id is in
- * bcd. But as usual if the revision is 0x101 then you should compare
- * the revision id in the device descriptor with 0x101
- * Or go search the file usbdevs.h. Maybe the device is already in
- * there.
- */
- if ((uaa->vendor == USB_VENDOR_NETCHIP &&
- uaa->product == USB_PRODUCT_NETCHIP_TURBOCONNECT))
- return (UMATCH_VENDOR_PRODUCT);
-
- if ((uaa->vendor == USB_VENDOR_PROLIFIC &&
- (uaa->product == USB_PRODUCT_PROLIFIC_PL2301 ||
- uaa->product == USB_PRODUCT_PROLIFIC_PL2302)))
- return (UMATCH_VENDOR_PRODUCT);
-
- if ((uaa->vendor == USB_VENDOR_ANCHOR &&
- uaa->product == USB_PRODUCT_ANCHOR_EZLINK))
- return (UMATCH_VENDOR_PRODUCT);
-
- if ((uaa->vendor == USB_VENDOR_GENESYS &&
- uaa->product == USB_PRODUCT_GENESYS_GL620USB))
- return (UMATCH_VENDOR_PRODUCT);
-
- return (UMATCH_NONE);
-}
-
-static int
-udbp_attach(device_t self)
-{
- struct udbp_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
- usbd_interface_handle iface = uaa->iface;
- usb_interface_descriptor_t *id;
- usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL;
- usbd_status err;
- int i;
- static int ngudbp_done_init=0;
-
- sc->flags |= DISCONNECTED;
- /* fetch the interface handle for the first interface */
- (void) usbd_device2interface_handle(uaa->device, 0, &iface);
- id = usbd_get_interface_descriptor(iface);
- sc->sc_dev = self;
-
- /* Find the two first bulk endpoints */
- for (i = 0 ; i < id->bNumEndpoints; i++) {
- ed = usbd_interface2endpoint_descriptor(iface, i);
- if (!ed) {
- device_printf(self, "could not read endpoint descriptor\n");
- return ENXIO;
- }
-
- if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
- && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
- ed_bulkin = ed;
- } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
- && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
- ed_bulkout = ed;
- }
-
- if (ed_bulkin && ed_bulkout) /* found all we need */
- break;
- }
-
- /* Verify that we goething sensible */
- if (ed_bulkin == NULL || ed_bulkout == NULL) {
- device_printf(self, "bulk-in and/or bulk-out endpoint not found\n");
- return ENXIO;
- }
-
- if (ed_bulkin->wMaxPacketSize[0] != ed_bulkout->wMaxPacketSize[0] ||
- ed_bulkin->wMaxPacketSize[1] != ed_bulkout->wMaxPacketSize[1]) {
- device_printf(self,
- "bulk-in and bulk-out have different packet sizes %d %d %d %d\n",
- ed_bulkin->wMaxPacketSize[0],
- ed_bulkout->wMaxPacketSize[0],
- ed_bulkin->wMaxPacketSize[1],
- ed_bulkout->wMaxPacketSize[1]);
- return ENXIO;
- }
-
- sc->sc_bulkin = ed_bulkin->bEndpointAddress;
- sc->sc_bulkout = ed_bulkout->bEndpointAddress;
-
- DPRINTF(("%s: Bulk-in: 0x%02x, bulk-out 0x%02x, packet size = %d\n",
- device_get_nameunit(sc->sc_dev), sc->sc_bulkin, sc->sc_bulkout,
- ed_bulkin->wMaxPacketSize[0]));
-
- /* Allocate the in transfer struct */
- sc->sc_bulkin_xfer = usbd_alloc_xfer(uaa->device);
- if (!sc->sc_bulkin_xfer) {
- goto bad;
- }
- sc->sc_bulkout_xfer = usbd_alloc_xfer(uaa->device);
- if (!sc->sc_bulkout_xfer) {
- goto bad;
- }
- sc->sc_bulkin_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_WAITOK);
- if (!sc->sc_bulkin_buffer) {
- goto bad;
- }
- sc->sc_bulkout_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_WAITOK);
- if (!sc->sc_bulkout_xfer || !sc->sc_bulkout_buffer) {
- goto bad;
- }
- sc->sc_bulkin_bufferlen = UDBP_BUFFERSIZE;
- sc->sc_bulkout_bufferlen = UDBP_BUFFERSIZE;
-
- /* We have decided on which endpoints to use, now open the pipes */
- err = usbd_open_pipe(iface, sc->sc_bulkin,
- USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
- if (err) {
- device_printf(self, "cannot open bulk-in pipe (addr %d)\n",
- sc->sc_bulkin);
- goto bad;
- }
- err = usbd_open_pipe(iface, sc->sc_bulkout,
- USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
- if (err) {
- device_printf(self, "cannot open bulk-out pipe (addr %d)\n",
- sc->sc_bulkout);
- goto bad;
- }
-
- if (!ngudbp_done_init){
- ngudbp_done_init=1;
- if (ng_newtype(&ng_udbp_typestruct)) {
- printf("ngudbp install failed\n");
- goto bad;
- }
- }
-
- if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
- char nodename[128];
- sprintf(nodename, "%s", device_get_nameunit(sc->sc_dev));
- if ((err = ng_name_node(sc->node, nodename))) {
- NG_NODE_UNREF(sc->node);
- sc->node = NULL;
- goto bad;
- } else {
- NG_NODE_SET_PRIVATE(sc->node, sc);
- sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
- sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
- mtx_init(&sc->xmitq.ifq_mtx, "usb_xmitq", NULL,
- MTX_DEF);
- mtx_init(&sc->xmitq_hipri.ifq_mtx,
- "usb_xmitq_hipri", NULL, MTX_DEF);
- }
- }
- sc->flags = NETGRAPH_INITIALISED;
- /* sc->flags &= ~DISCONNECTED; */ /* XXX */
-
-
- /* the device is now operational */
-
-
- /* schedule the first incoming xfer */
- err = udbp_setup_in_transfer(sc);
- if (err) {
- goto bad;
- }
- return 0;
-bad:
-#if 0 /* probably done in udbp_detach() */
- if (sc->sc_bulkout_buffer) {
- free(sc->sc_bulkout_buffer, M_USBDEV);
- }
- if (sc->sc_bulkin_buffer) {
- free(sc->sc_bulkin_buffer, M_USBDEV);
- }
- if (sc->sc_bulkout_xfer) {
- usbd_free_xfer(sc->sc_bulkout_xfer);
- }
- if (sc->sc_bulkin_xfer) {
- usbd_free_xfer(sc->sc_bulkin_xfer);
- }
-#endif
- udbp_detach(self);
- return ENXIO;
-}
-
-
-static int
-udbp_detach(device_t self)
-{
- struct udbp_softc *sc = device_get_softc(self);
-
- sc->flags |= DISCONNECTED;
-
- DPRINTF(("%s: disconnected\n", device_get_nameunit(self)));
-
- if (sc->sc_bulkin_pipe) {
- usbd_abort_pipe(sc->sc_bulkin_pipe);
- usbd_close_pipe(sc->sc_bulkin_pipe);
- }
- if (sc->sc_bulkout_pipe) {
- usbd_abort_pipe(sc->sc_bulkout_pipe);
- usbd_close_pipe(sc->sc_bulkout_pipe);
- }
-
- if (sc->flags & NETGRAPH_INITIALISED) {
- ng_rmnode_self(sc->node);
- NG_NODE_SET_PRIVATE(sc->node, NULL);
- NG_NODE_UNREF(sc->node);
- sc->node = NULL; /* Paranoid */
- }
-
- if (sc->sc_bulkin_xfer)
- usbd_free_xfer(sc->sc_bulkin_xfer);
- if (sc->sc_bulkout_xfer)
- usbd_free_xfer(sc->sc_bulkout_xfer);
-
- if (sc->sc_bulkin_buffer)
- free(sc->sc_bulkin_buffer, M_USBDEV);
- if (sc->sc_bulkout_buffer)
- free(sc->sc_bulkout_buffer, M_USBDEV);
- return 0;
-}
-
-
-static int
-udbp_setup_in_transfer(udbp_p sc)
-{
- void *priv = sc; /* XXX this should probably be some pointer to
- * struct describing the transfer (mbuf?)
- * See also below.
- */
- usbd_status err;
-
- /* XXX
- * How should we arrange for 2 extra bytes at the start of the
- * packet?
- */
-
- /* Initialise a USB transfer and then schedule it */
-
- (void) usbd_setup_xfer( sc->sc_bulkin_xfer,
- sc->sc_bulkin_pipe,
- priv,
- sc->sc_bulkin_buffer,
- sc->sc_bulkin_bufferlen,
- USBD_SHORT_XFER_OK,
- USBD_NO_TIMEOUT,
- udbp_in_transfer_cb);
-
- err = usbd_transfer(sc->sc_bulkin_xfer);
- if (err && err != USBD_IN_PROGRESS) {
- DPRINTF(("%s: failed to setup in-transfer, %s\n",
- device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
- return(err);
- }
-
- return (USBD_NORMAL_COMPLETION);
-}
-
-static void
-udbp_in_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
- usbd_status err)
-{
- udbp_p sc = priv; /* XXX see priv above */
- int s;
- int len;
- struct mbuf *m;
-
- if (err) {
- if (err != USBD_CANCELLED) {
- DPRINTF(("%s: bulk-out transfer failed: %s\n",
- device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
- } else {
- /* USBD_CANCELLED happens at unload of the driver */
- return;
- }
-
- /* Transfer has failed, packet is not received */
- } else {
-
- len = xfer->actlen;
-
- s = splimp(); /* block network stuff too */
- if (sc->hook) {
- /* get packet from device and send on */
- m = m_devget(sc->sc_bulkin_buffer, len, 0, NULL, NULL);
- NG_SEND_DATA_ONLY(err, sc->hook, m);
- }
- splx(s);
-
- }
- /* schedule the next in transfer */
- udbp_setup_in_transfer(sc);
-}
-
-
-static int
-udbp_setup_out_transfer(udbp_p sc)
-{
- void *priv = sc; /* XXX this should probably be some pointer to
- * struct describing the transfer (mbuf?)
- * See also below.
- */
- int pktlen;
- usbd_status err;
- int s, s1;
- struct mbuf *m;
-
-
- s = splusb();
- if (sc->flags & OUT_BUSY)
- panic("out transfer already in use, we should add queuing");
- sc->flags |= OUT_BUSY;
- splx(s);
- s1 = splimp(); /* Queueing happens at splnet */
- IF_DEQUEUE(&sc->xmitq_hipri, m);
- if (m == NULL) {
- IF_DEQUEUE(&sc->xmitq, m);
- }
- splx(s1);
-
- if (!m) {
- sc->flags &= ~OUT_BUSY;
- return (USBD_NORMAL_COMPLETION);
- }
-
- pktlen = m->m_pkthdr.len;
- if (pktlen > sc->sc_bulkout_bufferlen) {
- device_printf(sc->sc_dev, "Packet too large, %d > %d\n",
- pktlen, sc->sc_bulkout_bufferlen);
- return (USBD_IOERROR);
- }
-
- m_copydata(m, 0, pktlen, sc->sc_bulkout_buffer);
- m_freem(m);
-
- /* Initialise a USB transfer and then schedule it */
-
- (void) usbd_setup_xfer( sc->sc_bulkout_xfer,
- sc->sc_bulkout_pipe,
- priv,
- sc->sc_bulkout_buffer,
- pktlen,
- USBD_SHORT_XFER_OK,
- UDBP_TIMEOUT,
- udbp_out_transfer_cb);
-
- err = usbd_transfer(sc->sc_bulkout_xfer);
- if (err && err != USBD_IN_PROGRESS) {
- DPRINTF(("%s: failed to setup out-transfer, %s\n",
- device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
- return(err);
- }
-
- return (USBD_NORMAL_COMPLETION);
-}
-
-static void
-udbp_out_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
- usbd_status err)
-{
- udbp_p sc = priv; /* XXX see priv above */
- int s;
-
- if (err) {
- DPRINTF(("%s: bulk-out transfer failed: %s\n",
- device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
- /* Transfer has failed, packet is not transmitted */
- /* XXX Invalidate packet */
- return;
- }
-
- /* packet has been transmitted */
-
- s = splusb(); /* mark the buffer available */
- sc->flags &= ~OUT_BUSY;
- udbp_setup_out_transfer(sc);
- splx(s);
-}
-
-DRIVER_MODULE(udbp, uhub, udbp_driver, udbp_devclass, usbd_driver_load, 0);
-MODULE_DEPEND(udbp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
-MODULE_DEPEND(udbp, usb, 1, 1, 1);
-
-
-/***********************************************************************
- * Start of Netgraph methods
- **********************************************************************/
-
-/*
- * If this is a device node so this work is done in the attach()
- * routine and the constructor will return EINVAL as you should not be able
- * to create nodes that depend on hardware (unless you can add the hardware :)
- */
-static int
-ng_udbp_constructor(node_p node)
-{
- return (EINVAL);
-}
-
-/*
- * Give our ok for a hook to be added...
- * If we are not running this might kick a device into life.
- * Possibly decode information out of the hook name.
- * Add the hook's private info to the hook structure.
- * (if we had some). In this example, we assume that there is a
- * an array of structs, called 'channel' in the private info,
- * one for each active channel. The private
- * pointer of each hook points to the appropriate UDBP_hookinfo struct
- * so that the source of an input packet is easily identified.
- */
-static int
-ng_udbp_newhook(node_p node, hook_p hook, const char *name)
-{
- const udbp_p sc = NG_NODE_PRIVATE(node);
-
-#if 0
- /* Possibly start up the device if it's not already going */
- if ((sc->flags & SCF_RUNNING) == 0) {
- ng_udbp_start_hardware(sc);
- }
-#endif
-
- if (strcmp(name, NG_UDBP_HOOK_NAME) == 0) {
- sc->hook = hook;
- NG_HOOK_SET_PRIVATE(hook, NULL);
- } else {
- return (EINVAL); /* not a hook we know about */
- }
- return(0);
-}
-
-/*
- * Get a netgraph control message.
- * Check it is one we understand. If needed, send a response.
- * We could save the address for an async action later, but don't here.
- * Always free the message.
- * The response should be in a malloc'd region that the caller can 'free'.
- * A response is not required.
- * Theoretically you could respond defferently to old message types if
- * the cookie in the header didn't match what we consider to be current
- * (so that old userland programs could continue to work).
- */
-static int
-ng_udbp_rcvmsg(node_p node, item_p item, hook_p lasthook)
-{
- const udbp_p sc = NG_NODE_PRIVATE(node);
- struct ng_mesg *resp = NULL;
- int error = 0;
- struct ng_mesg *msg;
-
- NGI_GET_MSG(item, msg);
- /* Deal with message according to cookie and command */
- switch (msg->header.typecookie) {
- case NGM_UDBP_COOKIE:
- switch (msg->header.cmd) {
- case NGM_UDBP_GET_STATUS:
- {
- struct ngudbpstat *stats;
-
- NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT);
- if (!resp) {
- error = ENOMEM;
- break;
- }
- stats = (struct ngudbpstat *) resp->data;
- stats->packets_in = sc->packets_in;
- stats->packets_out = sc->packets_out;
- break;
- }
- case NGM_UDBP_SET_FLAG:
- if (msg->header.arglen != sizeof(u_int32_t)) {
- error = EINVAL;
- break;
- }
- sc->flags = *((u_int32_t *) msg->data);
- break;
- default:
- error = EINVAL; /* unknown command */
- break;
- }
- break;
- default:
- error = EINVAL; /* unknown cookie type */
- break;
- }
-
- /* Take care of synchronous response, if any */
- NG_RESPOND_MSG(error, node, item, resp);
- NG_FREE_MSG(msg);
- return(error);
-}
-
-/*
- * Accept data from the hook and queue it for output.
- */
-static int
-ng_udbp_rcvdata(hook_p hook, item_p item)
-{
- const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
- int error;
- struct ifqueue *xmitq_p;
- int s;
- struct mbuf *m;
- struct ng_tag_prio *ptag;
-
- NGI_GET_M(item, m);
- NG_FREE_ITEM(item);
-
- /*
- * Now queue the data for when it can be sent
- */
- if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE,
- NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) )
- xmitq_p = (&sc->xmitq_hipri);
- else
- xmitq_p = (&sc->xmitq);
-
- s = splusb();
- IF_LOCK(xmitq_p);
- if (_IF_QFULL(xmitq_p)) {
- _IF_DROP(xmitq_p);
- IF_UNLOCK(xmitq_p);
- splx(s);
- error = ENOBUFS;
- goto bad;
- }
- _IF_ENQUEUE(xmitq_p, m);
- IF_UNLOCK(xmitq_p);
- if (!(sc->flags & OUT_BUSY))
- udbp_setup_out_transfer(sc);
- splx(s);
- return (0);
-
-bad: /*
- * It was an error case.
- * check if we need to free the mbuf, and then return the error
- */
- NG_FREE_M(m);
- return (error);
-}
-
-/*
- * 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", device_get_nameunit(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);
-}
-
-/*
- * This is called once we've already connected a new hook to the other node.
- * It gives us a chance to balk at the last minute.
- */
-static int
-ng_udbp_connect(hook_p hook)
-{
- /* probably not at splnet, force outward queueing */
- NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
- /* be really amiable and just say "YUP that's OK by me! " */
- return (0);
-}
-
-/*
- * Dook disconnection
- *
- * For this type, removal of the last link destroys the node
- */
-static int
-ng_udbp_disconnect(hook_p hook)
-{
- const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
- sc->hook = NULL;
-
- if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
- && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))))
- ng_rmnode_self(NG_HOOK_NODE(hook));
- return (0);
-}
-
OpenPOWER on IntegriCloud