summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrik <rik@FreeBSD.org>2005-09-27 16:12:49 +0000
committerrik <rik@FreeBSD.org>2005-09-27 16:12:49 +0000
commitfe4bf0ce4614cf5425181079a4c55239cf59d2a9 (patch)
treede33282379b1d3e356725c8104dae5989b6f278f
parentdfb93b65df016fabc02e13f5947c237d1216e828 (diff)
downloadFreeBSD-src-fe4bf0ce4614cf5425181079a4c55239cf59d2a9.zip
FreeBSD-src-fe4bf0ce4614cf5425181079a4c55239cf59d2a9.tar.gz
Backout if_cp 1.26, if_ct 1.27, if_cx 1.47 by obrien:
---------------------------- revision 1.26 date: 2005/09/07 09:53:35; author: obrien; state: Exp; lines: +1452 -1453 Reorder code to not depend on an ISO-C illegal forward extern declaration. ---------------------------- Reason: do not move large functions location without serious reason. The same could be done by forward function declaration. Please do not enlarge diff without a reason any more. Backout if_cp 1.27 ---------------------------- revision 1.27 date: 2005/09/19 03:10:16; author: imp; state: Exp; lines: +3 -2 Make sure that we call if_free(ifp) after bus_teardown_intr. Since we could get an interrupt after we free the ifp, and the interrupt handler depended on the ifp being still alive, this could, in theory, cause a crash. Eliminate this possibility by moving the if_free to after the bus_teardown_intr() call. Reason: bad previous commit. Would be restored by next commit.
-rw-r--r--sys/dev/cp/if_cp.c1619
-rw-r--r--sys/dev/ctau/if_ct.c1066
-rw-r--r--sys/dev/cx/if_cx.c895
3 files changed, 1793 insertions, 1787 deletions
diff --git a/sys/dev/cp/if_cp.c b/sys/dev/cp/if_cp.c
index f6ecd74..2adcfd6 100644
--- a/sys/dev/cp/if_cp.c
+++ b/sys/dev/cp/if_cp.c
@@ -184,6 +184,816 @@ static struct callout timeout_handle;
static int cp_destroy = 0;
+static int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td);
+static int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td);
+static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td);
+static struct cdevsw cp_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = cp_open,
+ .d_close = cp_close,
+ .d_ioctl = cp_ioctl,
+ .d_name = "cp",
+ .d_flags = D_NEEDGIANT,
+};
+
+/*
+ * Print the mbuf chain, for debug purposes only.
+ */
+static void printmbuf (struct mbuf *m)
+{
+ printf ("mbuf:");
+ for (; m; m=m->m_next) {
+ if (m->m_flags & M_PKTHDR)
+ printf (" HDR %d:", m->m_pkthdr.len);
+ if (m->m_flags & M_EXT)
+ printf (" EXT:");
+ printf (" %d", m->m_len);
+ }
+ printf ("\n");
+}
+
+/*
+ * Make an mbuf from data.
+ */
+static struct mbuf *makembuf (void *buf, unsigned len)
+{
+ struct mbuf *m;
+
+ MGETHDR (m, M_DONTWAIT, MT_DATA);
+ if (! m)
+ return 0;
+ MCLGET (m, M_DONTWAIT);
+ if (! (m->m_flags & M_EXT)) {
+ m_freem (m);
+ return 0;
+ }
+ m->m_pkthdr.len = m->m_len = len;
+ bcopy (buf, mtod (m, caddr_t), len);
+ return m;
+}
+
+static int cp_probe (device_t dev)
+{
+ if ((pci_get_vendor (dev) == cp_vendor_id) &&
+ (pci_get_device (dev) == cp_device_id)) {
+ device_set_desc (dev, "Cronyx-Tau-PCI serial adapter");
+ return BUS_PROBE_DEFAULT;
+ }
+ return ENXIO;
+}
+
+static void cp_timeout (void *arg)
+{
+ drv_t *d;
+ int s, i, k;
+
+ for (i = 0; i < NBRD; ++i) {
+ if (adapter[i] == NULL)
+ continue;
+ for (k = 0; k < NCHAN; ++k) {
+ s = splimp ();
+ if (cp_destroy) {
+ splx (s);
+ return;
+ }
+ d = channel[i * NCHAN + k];
+ if (!d) {
+ splx (s);
+ continue;
+ }
+ CP_LOCK ((bdrv_t *)d->board->sys);
+ switch (d->chan->type) {
+ case T_G703:
+ cp_g703_timer (d->chan);
+ break;
+ case T_E1:
+ cp_e1_timer (d->chan);
+ break;
+ case T_E3:
+ case T_T3:
+ case T_STS1:
+ cp_e3_timer (d->chan);
+ break;
+ default:
+ break;
+ }
+ CP_UNLOCK ((bdrv_t *)d->board->sys);
+ splx (s);
+ }
+ }
+ s = splimp ();
+ if (!cp_destroy)
+ callout_reset (&timeout_handle, hz, cp_timeout, 0);
+ splx (s);
+}
+
+static void cp_led_off (void *arg)
+{
+ cp_board_t *b = arg;
+ bdrv_t *bd = (bdrv_t *) b->sys;
+ int s;
+ s = splimp ();
+ if (cp_destroy) {
+ splx (s);
+ return;
+ }
+ CP_LOCK (bd);
+ cp_led (b, 0);
+ CP_UNLOCK (bd);
+ splx (s);
+}
+
+static void cp_intr (void *arg)
+{
+ bdrv_t *bd = arg;
+ cp_board_t *b = bd->board;
+#ifndef NETGRAPH
+ int i;
+#endif
+ int s = splimp ();
+ if (cp_destroy) {
+ splx (s);
+ return;
+ }
+ CP_LOCK (bd);
+ /* Check if we are ready */
+ if (b->sys == NULL) {
+ /* Not we are not, just cleanup. */
+ cp_interrupt_poll (b, 1);
+ CP_UNLOCK (bd);
+ return;
+ }
+ /* Turn LED on. */
+ cp_led (b, 1);
+
+ cp_interrupt (b);
+
+ /* Turn LED off 50 msec later. */
+ callout_reset (&led_timo[b->num], hz/20, cp_led_off, b);
+ CP_UNLOCK (bd);
+ splx (s);
+
+#ifndef NETGRAPH
+ /* Pass packets in a lock-free state */
+ for (i = 0; i < NCHAN && b->chan[i].type; i++) {
+ drv_t *d = b->chan[i].sys;
+ struct mbuf *m;
+ if (!d || !d->running)
+ continue;
+ while (_IF_QLEN(&d->queue)) {
+ IF_DEQUEUE (&d->queue,m);
+ if (!m)
+ continue;
+ sppp_input (d->ifp, m);
+ }
+ }
+#endif
+}
+
+static void
+cp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ unsigned long *addr;
+
+ if (error)
+ return;
+
+ KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg));
+ addr = arg;
+ *addr = segs->ds_addr;
+}
+
+static int
+cp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem)
+{
+ int error;
+
+ error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1,
+ dmem->size, 0, NULL, NULL, &dmem->dmat);
+ if (error) {
+ if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum);
+ else printf ("cp%d: ", bnum);
+ printf ("couldn't allocate tag for dma memory\n");
+ return 0;
+ }
+ error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt,
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp);
+ if (error) {
+ if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum);
+ else printf ("cp%d: ", bnum);
+ printf ("couldn't allocate mem for dma memory\n");
+ bus_dma_tag_destroy (dmem->dmat);
+ return 0;
+ }
+ error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt,
+ dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0);
+ if (error) {
+ if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum);
+ else printf ("cp%d: ", bnum);
+ printf ("couldn't load mem map for dma memory\n");
+ bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp);
+ bus_dma_tag_destroy (dmem->dmat);
+ return 0;
+ }
+ return 1;
+}
+
+static void
+cp_bus_dma_mem_free (cp_dma_mem_t *dmem)
+{
+ bus_dmamap_unload (dmem->dmat, dmem->mapp);
+ bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp);
+ bus_dma_tag_destroy (dmem->dmat);
+}
+
+/*
+ * Called if the probe succeeded.
+ */
+static int cp_attach (device_t dev)
+{
+ bdrv_t *bd = device_get_softc (dev);
+ int unit = device_get_unit (dev);
+ char *cp_ln = CP_LOCK_NAME;
+ unsigned short res;
+ vm_offset_t vbase;
+ int rid, error;
+ cp_board_t *b;
+ cp_chan_t *c;
+ drv_t *d;
+ int s = splimp ();
+
+ b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK);
+ if (!b) {
+ printf ("cp%d: couldn't allocate memory\n", unit);
+ splx (s);
+ return (ENXIO);
+ }
+ bzero (b, sizeof(cp_board_t));
+
+ bd->board = b;
+ rid = PCIR_BAR(0);
+ bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (! bd->cp_res) {
+ printf ("cp%d: cannot map memory\n", unit);
+ free (b, M_DEVBUF);
+ splx (s);
+ return (ENXIO);
+ }
+ vbase = (vm_offset_t) rman_get_virtual (bd->cp_res);
+
+ cp_ln[2] = '0' + unit;
+ mtx_init (&bd->cp_mtx, cp_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE);
+ res = cp_init (b, unit, (u_char*) vbase);
+ if (res) {
+ printf ("cp%d: can't init, error code:%x\n", unit, res);
+ bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res);
+ free (b, M_DEVBUF);
+ splx (s);
+ return (ENXIO);
+ }
+
+ bd->dmamem.size = sizeof(cp_qbuf_t);
+ if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) {
+ free (b, M_DEVBUF);
+ splx (s);
+ return (ENXIO);
+ }
+ CP_LOCK (bd);
+ cp_reset (b, bd->dmamem.virt, bd->dmamem.phys);
+ CP_UNLOCK (bd);
+
+ rid = 0;
+ bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (! bd->cp_irq) {
+ cp_destroy = 1;
+ printf ("cp%d: cannot map interrupt\n", unit);
+ bus_release_resource (dev, SYS_RES_MEMORY,
+ PCIR_BAR(0), bd->cp_res);
+ mtx_destroy (&bd->cp_mtx);
+ free (b, M_DEVBUF);
+ splx (s);
+ return (ENXIO);
+ }
+ callout_init (&led_timo[unit], cp_mpsafenet ? CALLOUT_MPSAFE : 0);
+ error = bus_setup_intr (dev, bd->cp_irq,
+ INTR_TYPE_NET|(cp_mpsafenet?INTR_MPSAFE:0),
+ cp_intr, bd, &bd->cp_intrhand);
+ if (error) {
+ cp_destroy = 1;
+ printf ("cp%d: cannot set up irq\n", unit);
+ bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
+ bus_release_resource (dev, SYS_RES_MEMORY,
+ PCIR_BAR(0), bd->cp_res);
+ mtx_destroy (&bd->cp_mtx);
+ free (b, M_DEVBUF);
+ splx (s);
+ return (ENXIO);
+ }
+ printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000);
+
+ for (c = b->chan; c < b->chan + NCHAN; ++c) {
+ if (! c->type)
+ continue;
+ d = &bd->channel[c->num];
+ d->dmamem.size = sizeof(cp_buf_t);
+ if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem))
+ continue;
+ channel [b->num*NCHAN + c->num] = d;
+ sprintf (d->name, "cp%d.%d", b->num, c->num);
+ d->board = b;
+ d->chan = c;
+ c->sys = d;
+#ifdef NETGRAPH
+ if (ng_make_node_common (&typestruct, &d->node) != 0) {
+ printf ("%s: cannot make common node\n", d->name);
+ d->node = NULL;
+ continue;
+ }
+ NG_NODE_SET_PRIVATE (d->node, d);
+ sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE,
+ c->board->num*NCHAN + c->num);
+ if (ng_name_node (d->node, d->nodename)) {
+ printf ("%s: cannot name node\n", d->nodename);
+ NG_NODE_UNREF (d->node);
+ continue;
+ }
+ d->queue.ifq_maxlen = IFQ_MAXLEN;
+ d->hi_queue.ifq_maxlen = IFQ_MAXLEN;
+ mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF);
+ mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF);
+ callout_init (&d->timeout_handle,
+ cp_mpsafenet ? CALLOUT_MPSAFE : 0);
+#else /*NETGRAPH*/
+ d->ifp = if_alloc(IFT_PPP);
+ if (d->ifp == NULL) {
+ printf ("%s: cannot if_alloc() interface\n", d->name);
+ continue;
+ }
+ d->ifp->if_softc = d;
+ if_initname (d->ifp, "cp", b->num * NCHAN + c->num);
+ d->ifp->if_mtu = PP_MTU;
+ d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
+ if (!cp_mpsafenet)
+ d->ifp->if_flags |= IFF_NEEDSGIANT;
+ d->ifp->if_ioctl = cp_sioctl;
+ d->ifp->if_start = cp_ifstart;
+ d->ifp->if_watchdog = cp_ifwatchdog;
+ d->ifp->if_init = cp_initialize;
+ d->queue.ifq_maxlen = NRBUF;
+ mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF);
+ sppp_attach (d->ifp);
+ if_attach (d->ifp);
+ IFP2SP(d->ifp)->pp_tlf = cp_tlf;
+ IFP2SP(d->ifp)->pp_tls = cp_tls;
+ /* If BPF is in the kernel, call the attach for it.
+ * The header size of PPP or Cisco/HDLC is 4 bytes. */
+ bpfattach (d->ifp, DLT_PPP, 4);
+#endif /*NETGRAPH*/
+ cp_start_e1 (c);
+ cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys);
+
+ /* Register callback functions. */
+ cp_register_transmit (c, &cp_transmit);
+ cp_register_receive (c, &cp_receive);
+ cp_register_error (c, &cp_error);
+ d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT,
+ GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num);
+ }
+ CP_LOCK (bd);
+ b->sys = bd;
+ adapter[unit] = b;
+ CP_UNLOCK (bd);
+ splx (s);
+ return 0;
+}
+
+static int cp_detach (device_t dev)
+{
+ bdrv_t *bd = device_get_softc (dev);
+ cp_board_t *b = bd->board;
+ cp_chan_t *c;
+ int s;
+
+ KASSERT (mtx_initialized (&bd->cp_mtx), ("cp mutex not initialized"));
+ s = splimp ();
+ CP_LOCK (bd);
+ /* Check if the device is busy (open). */
+ for (c = b->chan; c < b->chan + NCHAN; ++c) {
+ drv_t *d = (drv_t*) c->sys;
+
+ if (! d || ! d->chan->type)
+ continue;
+ if (d->running) {
+ CP_UNLOCK (bd);
+ splx (s);
+ return EBUSY;
+ }
+ }
+
+ /* Ok, we can unload driver */
+ /* At first we should stop all channels */
+ for (c = b->chan; c < b->chan + NCHAN; ++c) {
+ drv_t *d = (drv_t*) c->sys;
+
+ if (! d || ! d->chan->type)
+ continue;
+
+ cp_stop_chan (c);
+ cp_stop_e1 (c);
+ cp_set_dtr (d->chan, 0);
+ cp_set_rts (d->chan, 0);
+ }
+
+ /* Reset the adapter. */
+ cp_destroy = 1;
+ cp_interrupt_poll (b, 1);
+ cp_led_off (b);
+ cp_reset (b, 0 ,0);
+ callout_stop (&led_timo[b->num]);
+
+ for (c=b->chan; c<b->chan+NCHAN; ++c) {
+ drv_t *d = (drv_t*) c->sys;
+
+ if (! d || ! d->chan->type)
+ continue;
+#ifndef NETGRAPH
+ /* Detach from the packet filter list of interfaces. */
+ bpfdetach (d->ifp);
+
+ /* Detach from the sync PPP list. */
+ sppp_detach (d->ifp);
+
+ /* Detach from the system list of interfaces. */
+ if_detach (d->ifp);
+ if_free (d->ifp);
+ IF_DRAIN (&d->queue);
+ mtx_destroy (&d->queue.ifq_mtx);
+#else
+ if (d->node) {
+ ng_rmnode_self (d->node);
+ NG_NODE_UNREF (d->node);
+ d->node = NULL;
+ }
+ mtx_destroy (&d->queue.ifq_mtx);
+ mtx_destroy (&d->hi_queue.ifq_mtx);
+#endif
+ destroy_dev (d->devt);
+ }
+
+ b->sys = NULL;
+ CP_UNLOCK (bd);
+
+ /* Disable the interrupt request. */
+ bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand);
+ bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
+ bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
+ bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res);
+
+ CP_LOCK (bd);
+ cp_led_off (b);
+ CP_UNLOCK (bd);
+ callout_drain (&led_timo[b->num]);
+ splx (s);
+
+ s = splimp ();
+ for (c = b->chan; c < b->chan + NCHAN; ++c) {
+ drv_t *d = (drv_t*) c->sys;
+
+ if (! d || ! d->chan->type)
+ continue;
+ channel [b->num*NCHAN + c->num] = 0;
+ /* Deallocate buffers. */
+ cp_bus_dma_mem_free (&d->dmamem);
+ }
+ adapter [b->num] = 0;
+ cp_bus_dma_mem_free (&bd->dmamem);
+ free (b, M_DEVBUF);
+ splx (s);
+ mtx_destroy (&bd->cp_mtx);
+ return 0;
+}
+
+#ifndef NETGRAPH
+static void cp_ifstart (struct ifnet *ifp)
+{
+ drv_t *d = ifp->if_softc;
+ bdrv_t *bd = d->board->sys;
+
+ CP_LOCK (bd);
+ cp_start (d);
+ CP_UNLOCK (bd);
+}
+
+static void cp_ifwatchdog (struct ifnet *ifp)
+{
+ drv_t *d = ifp->if_softc;
+
+ cp_watchdog (d);
+}
+
+static void cp_tlf (struct sppp *sp)
+{
+ drv_t *d = SP2IFP(sp)->if_softc;
+
+ CP_DEBUG2 (d, ("cp_tlf\n"));
+ /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */
+/* cp_set_dtr (d->chan, 0);*/
+/* cp_set_rts (d->chan, 0);*/
+ if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO))
+ sp->pp_down (sp);
+}
+
+static void cp_tls (struct sppp *sp)
+{
+ drv_t *d = SP2IFP(sp)->if_softc;
+
+ CP_DEBUG2 (d, ("cp_tls\n"));
+ if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO))
+ sp->pp_up (sp);
+}
+
+/*
+ * Process an ioctl request.
+ */
+static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ drv_t *d = ifp->if_softc;
+ bdrv_t *bd = d->board->sys;
+ int error, s, was_up, should_be_up;
+
+ was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0;
+ error = sppp_ioctl (ifp, cmd, data);
+
+ if (error)
+ return error;
+
+ if (! (ifp->if_flags & IFF_DEBUG))
+ d->chan->debug = 0;
+ else if (! d->chan->debug)
+ d->chan->debug = 1;
+
+ switch (cmd) {
+ default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0;
+ case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0;
+ case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0;
+ case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break;
+ case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break;
+ }
+
+ /* We get here only in case of SIFFLAGS or SIFADDR. */
+ s = splimp ();
+ CP_LOCK (bd);
+ should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0;
+ if (! was_up && should_be_up) {
+ /* Interface goes up -- start it. */
+ cp_up (d);
+ cp_start (d);
+ } else if (was_up && ! should_be_up) {
+ /* Interface is going down -- stop it. */
+/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/
+ cp_down (d);
+ }
+ CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd));
+ CP_UNLOCK (bd);
+ splx (s);
+ return 0;
+}
+
+/*
+ * Initialization of interface.
+ * It seems to be never called by upper level?
+ */
+static void cp_initialize (void *softc)
+{
+ drv_t *d = softc;
+
+ CP_DEBUG (d, ("cp_initialize\n"));
+}
+#endif /*NETGRAPH*/
+
+/*
+ * Stop the interface. Called on splimp().
+ */
+static void cp_down (drv_t *d)
+{
+ CP_DEBUG (d, ("cp_down\n"));
+ /* Interface is going down -- stop it. */
+ cp_set_dtr (d->chan, 0);
+ cp_set_rts (d->chan, 0);
+
+ d->running = 0;
+}
+
+/*
+ * Start the interface. Called on splimp().
+ */
+static void cp_up (drv_t *d)
+{
+ CP_DEBUG (d, ("cp_up\n"));
+ cp_set_dtr (d->chan, 1);
+ cp_set_rts (d->chan, 1);
+ d->running = 1;
+}
+
+/*
+ * Start output on the interface. Get another datagram to send
+ * off of the interface queue, and copy it to the interface
+ * before starting the output.
+ */
+static void cp_send (drv_t *d)
+{
+ struct mbuf *m;
+ u_short len;
+
+ CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te));
+
+ /* No output if the interface is down. */
+ if (! d->running)
+ return;
+
+ /* No output if the modem is off. */
+ if (! (d->chan->lloop || d->chan->type != T_SERIAL ||
+ cp_get_dsr (d->chan)))
+ return;
+
+ while (cp_transmit_space (d->chan)) {
+ /* Get the packet to send. */
+#ifdef NETGRAPH
+ IF_DEQUEUE (&d->hi_queue, m);
+ if (! m)
+ IF_DEQUEUE (&d->queue, m);
+#else
+ m = sppp_dequeue (d->ifp);
+#endif
+ if (! m)
+ return;
+#ifndef NETGRAPH
+ if (d->ifp->if_bpf)
+ BPF_MTAP (d->ifp, m);
+#endif
+ len = m_length (m, NULL);
+ if (len >= BUFSZ)
+ printf ("%s: too long packet: %d bytes: ",
+ d->name, len);
+ else if (! m->m_next)
+ cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0);
+ else {
+ u_char *buf = d->chan->tbuf[d->chan->te];
+ m_copydata (m, 0, len, buf);
+ cp_send_packet (d->chan, buf, len, 0);
+ }
+ m_freem (m);
+ /* Set up transmit timeout, if the transmit ring is not empty.*/
+#ifdef NETGRAPH
+ d->timeout = 10;
+#else
+ d->ifp->if_timer = 10;
+#endif
+ }
+#ifndef NETGRAPH
+ d->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+#endif
+}
+
+/*
+ * Start output on the interface.
+ * Always called on splimp().
+ */
+static void cp_start (drv_t *d)
+{
+ if (d->running) {
+ if (! d->chan->dtr)
+ cp_set_dtr (d->chan, 1);
+ if (! d->chan->rts)
+ cp_set_rts (d->chan, 1);
+ cp_send (d);
+ }
+}
+
+/*
+ * Handle transmit timeouts.
+ * Recover after lost transmit interrupts.
+ * Always called on splimp().
+ */
+static void cp_watchdog (drv_t *d)
+{
+ bdrv_t *bd = d->board->sys;
+ CP_DEBUG (d, ("device timeout\n"));
+ if (d->running) {
+ int s = splimp ();
+
+ CP_LOCK (bd);
+ cp_stop_chan (d->chan);
+ cp_stop_e1 (d->chan);
+ cp_start_e1 (d->chan);
+ cp_start_chan (d->chan, 1, 1, 0, 0);
+ cp_set_dtr (d->chan, 1);
+ cp_set_rts (d->chan, 1);
+ cp_start (d);
+ CP_UNLOCK (bd);
+ splx (s);
+ }
+}
+
+static void cp_transmit (cp_chan_t *c, void *attachment, int len)
+{
+ drv_t *d = c->sys;
+
+#ifdef NETGRAPH
+ d->timeout = 0;
+#else
+ ++d->ifp->if_opackets;
+ d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ d->ifp->if_timer = 0;
+#endif
+ cp_start (d);
+}
+
+static void cp_receive (cp_chan_t *c, unsigned char *data, int len)
+{
+ drv_t *d = c->sys;
+ struct mbuf *m;
+#ifdef NETGRAPH
+ int error;
+#endif
+
+ if (! d->running)
+ return;
+
+ m = makembuf (data, len);
+ if (! m) {
+ CP_DEBUG (d, ("no memory for packet\n"));
+#ifndef NETGRAPH
+ ++d->ifp->if_iqdrops;
+#endif
+ return;
+ }
+ if (c->debug > 1)
+ printmbuf (m);
+#ifdef NETGRAPH
+ m->m_pkthdr.rcvif = 0;
+ NG_SEND_DATA_ONLY (error, d->hook, m);
+#else
+ ++d->ifp->if_ipackets;
+ m->m_pkthdr.rcvif = d->ifp;
+ /* Check if there's a BPF listener on this interface.
+ * If so, hand off the raw packet to bpf. */
+ if (d->ifp->if_bpf)
+ BPF_TAP (d->ifp, data, len);
+ IF_ENQUEUE (&d->queue, m);
+#endif
+}
+
+static void cp_error (cp_chan_t *c, int data)
+{
+ drv_t *d = c->sys;
+
+ switch (data) {
+ case CP_FRAME:
+ CP_DEBUG (d, ("frame error\n"));
+#ifndef NETGRAPH
+ ++d->ifp->if_ierrors;
+#endif
+ break;
+ case CP_CRC:
+ CP_DEBUG (d, ("crc error\n"));
+#ifndef NETGRAPH
+ ++d->ifp->if_ierrors;
+#endif
+ break;
+ case CP_OVERRUN:
+ CP_DEBUG (d, ("overrun error\n"));
+#ifndef NETGRAPH
+ ++d->ifp->if_collisions;
+ ++d->ifp->if_ierrors;
+#endif
+ break;
+ case CP_OVERFLOW:
+ CP_DEBUG (d, ("overflow error\n"));
+#ifndef NETGRAPH
+ ++d->ifp->if_ierrors;
+#endif
+ break;
+ case CP_UNDERRUN:
+ CP_DEBUG (d, ("underrun error\n"));
+#ifdef NETGRAPH
+ d->timeout = 0;
+#else
+ ++d->ifp->if_oerrors;
+ d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ d->ifp->if_timer = 0;
+#endif
+ cp_start (d);
+ break;
+ default:
+ CP_DEBUG (d, ("error #%d\n", data));
+ break;
+ }
+}
+
/*
* You also need read, write, open, close routines.
* This should get you started
@@ -229,7 +1039,6 @@ static int cp_modem_status (cp_chan_t *c)
return status;
}
-
static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
{
drv_t *d = channel [minor (dev)];
@@ -1011,814 +1820,6 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc
return ENOTTY;
}
-static struct cdevsw cp_cdevsw = {
- .d_version = D_VERSION,
- .d_open = cp_open,
- .d_close = cp_close,
- .d_ioctl = cp_ioctl,
- .d_name = "cp",
- .d_flags = D_NEEDGIANT,
-};
-
-/*
- * Print the mbuf chain, for debug purposes only.
- */
-static void printmbuf (struct mbuf *m)
-{
- printf ("mbuf:");
- for (; m; m=m->m_next) {
- if (m->m_flags & M_PKTHDR)
- printf (" HDR %d:", m->m_pkthdr.len);
- if (m->m_flags & M_EXT)
- printf (" EXT:");
- printf (" %d", m->m_len);
- }
- printf ("\n");
-}
-
-/*
- * Make an mbuf from data.
- */
-static struct mbuf *makembuf (void *buf, unsigned len)
-{
- struct mbuf *m;
-
- MGETHDR (m, M_DONTWAIT, MT_DATA);
- if (! m)
- return 0;
- MCLGET (m, M_DONTWAIT);
- if (! (m->m_flags & M_EXT)) {
- m_freem (m);
- return 0;
- }
- m->m_pkthdr.len = m->m_len = len;
- bcopy (buf, mtod (m, caddr_t), len);
- return m;
-}
-
-static int cp_probe (device_t dev)
-{
- if ((pci_get_vendor (dev) == cp_vendor_id) &&
- (pci_get_device (dev) == cp_device_id)) {
- device_set_desc (dev, "Cronyx-Tau-PCI serial adapter");
- return BUS_PROBE_DEFAULT;
- }
- return ENXIO;
-}
-
-static void cp_timeout (void *arg)
-{
- drv_t *d;
- int s, i, k;
-
- for (i = 0; i < NBRD; ++i) {
- if (adapter[i] == NULL)
- continue;
- for (k = 0; k < NCHAN; ++k) {
- s = splimp ();
- if (cp_destroy) {
- splx (s);
- return;
- }
- d = channel[i * NCHAN + k];
- if (!d) {
- splx (s);
- continue;
- }
- CP_LOCK ((bdrv_t *)d->board->sys);
- switch (d->chan->type) {
- case T_G703:
- cp_g703_timer (d->chan);
- break;
- case T_E1:
- cp_e1_timer (d->chan);
- break;
- case T_E3:
- case T_T3:
- case T_STS1:
- cp_e3_timer (d->chan);
- break;
- default:
- break;
- }
- CP_UNLOCK ((bdrv_t *)d->board->sys);
- splx (s);
- }
- }
- s = splimp ();
- if (!cp_destroy)
- callout_reset (&timeout_handle, hz, cp_timeout, 0);
- splx (s);
-}
-
-static void cp_led_off (void *arg)
-{
- cp_board_t *b = arg;
- bdrv_t *bd = (bdrv_t *) b->sys;
- int s;
- s = splimp ();
- if (cp_destroy) {
- splx (s);
- return;
- }
- CP_LOCK (bd);
- cp_led (b, 0);
- CP_UNLOCK (bd);
- splx (s);
-}
-
-static void cp_intr (void *arg)
-{
- bdrv_t *bd = arg;
- cp_board_t *b = bd->board;
-#ifndef NETGRAPH
- int i;
-#endif
- int s = splimp ();
- if (cp_destroy) {
- splx (s);
- return;
- }
- CP_LOCK (bd);
- /* Check if we are ready */
- if (b->sys == NULL) {
- /* Not we are not, just cleanup. */
- cp_interrupt_poll (b, 1);
- CP_UNLOCK (bd);
- return;
- }
- /* Turn LED on. */
- cp_led (b, 1);
-
- cp_interrupt (b);
-
- /* Turn LED off 50 msec later. */
- callout_reset (&led_timo[b->num], hz/20, cp_led_off, b);
- CP_UNLOCK (bd);
- splx (s);
-
-#ifndef NETGRAPH
- /* Pass packets in a lock-free state */
- for (i = 0; i < NCHAN && b->chan[i].type; i++) {
- drv_t *d = b->chan[i].sys;
- struct mbuf *m;
- if (!d || !d->running)
- continue;
- while (_IF_QLEN(&d->queue)) {
- IF_DEQUEUE (&d->queue,m);
- if (!m)
- continue;
- sppp_input (d->ifp, m);
- }
- }
-#endif
-}
-
-static void
-cp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- unsigned long *addr;
-
- if (error)
- return;
-
- KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg));
- addr = arg;
- *addr = segs->ds_addr;
-}
-
-static int
-cp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem)
-{
- int error;
-
- error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT,
- BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1,
- dmem->size, 0, NULL, NULL, &dmem->dmat);
- if (error) {
- if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum);
- else printf ("cp%d: ", bnum);
- printf ("couldn't allocate tag for dma memory\n");
- return 0;
- }
- error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt,
- BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp);
- if (error) {
- if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum);
- else printf ("cp%d: ", bnum);
- printf ("couldn't allocate mem for dma memory\n");
- bus_dma_tag_destroy (dmem->dmat);
- return 0;
- }
- error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt,
- dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0);
- if (error) {
- if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum);
- else printf ("cp%d: ", bnum);
- printf ("couldn't load mem map for dma memory\n");
- bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp);
- bus_dma_tag_destroy (dmem->dmat);
- return 0;
- }
- return 1;
-}
-
-static void
-cp_bus_dma_mem_free (cp_dma_mem_t *dmem)
-{
- bus_dmamap_unload (dmem->dmat, dmem->mapp);
- bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp);
- bus_dma_tag_destroy (dmem->dmat);
-}
-
-/*
- * Called if the probe succeeded.
- */
-static int cp_attach (device_t dev)
-{
- bdrv_t *bd = device_get_softc (dev);
- int unit = device_get_unit (dev);
- char *cp_ln = CP_LOCK_NAME;
- unsigned short res;
- vm_offset_t vbase;
- int rid, error;
- cp_board_t *b;
- cp_chan_t *c;
- drv_t *d;
- int s = splimp ();
-
- b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK);
- if (!b) {
- printf ("cp%d: couldn't allocate memory\n", unit);
- splx (s);
- return (ENXIO);
- }
- bzero (b, sizeof(cp_board_t));
-
- bd->board = b;
- rid = PCIR_BAR(0);
- bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid,
- 0, ~0, 1, RF_ACTIVE);
- if (! bd->cp_res) {
- printf ("cp%d: cannot map memory\n", unit);
- free (b, M_DEVBUF);
- splx (s);
- return (ENXIO);
- }
- vbase = (vm_offset_t) rman_get_virtual (bd->cp_res);
-
- cp_ln[2] = '0' + unit;
- mtx_init (&bd->cp_mtx, cp_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE);
- res = cp_init (b, unit, (u_char*) vbase);
- if (res) {
- printf ("cp%d: can't init, error code:%x\n", unit, res);
- bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res);
- free (b, M_DEVBUF);
- splx (s);
- return (ENXIO);
- }
-
- bd->dmamem.size = sizeof(cp_qbuf_t);
- if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) {
- free (b, M_DEVBUF);
- splx (s);
- return (ENXIO);
- }
- CP_LOCK (bd);
- cp_reset (b, bd->dmamem.virt, bd->dmamem.phys);
- CP_UNLOCK (bd);
-
- rid = 0;
- bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
- RF_SHAREABLE | RF_ACTIVE);
- if (! bd->cp_irq) {
- cp_destroy = 1;
- printf ("cp%d: cannot map interrupt\n", unit);
- bus_release_resource (dev, SYS_RES_MEMORY,
- PCIR_BAR(0), bd->cp_res);
- mtx_destroy (&bd->cp_mtx);
- free (b, M_DEVBUF);
- splx (s);
- return (ENXIO);
- }
- callout_init (&led_timo[unit], cp_mpsafenet ? CALLOUT_MPSAFE : 0);
- error = bus_setup_intr (dev, bd->cp_irq,
- INTR_TYPE_NET|(cp_mpsafenet?INTR_MPSAFE:0),
- cp_intr, bd, &bd->cp_intrhand);
- if (error) {
- cp_destroy = 1;
- printf ("cp%d: cannot set up irq\n", unit);
- bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
- bus_release_resource (dev, SYS_RES_MEMORY,
- PCIR_BAR(0), bd->cp_res);
- mtx_destroy (&bd->cp_mtx);
- free (b, M_DEVBUF);
- splx (s);
- return (ENXIO);
- }
- printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000);
-
- for (c = b->chan; c < b->chan + NCHAN; ++c) {
- if (! c->type)
- continue;
- d = &bd->channel[c->num];
- d->dmamem.size = sizeof(cp_buf_t);
- if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem))
- continue;
- channel [b->num*NCHAN + c->num] = d;
- sprintf (d->name, "cp%d.%d", b->num, c->num);
- d->board = b;
- d->chan = c;
- c->sys = d;
-#ifdef NETGRAPH
- if (ng_make_node_common (&typestruct, &d->node) != 0) {
- printf ("%s: cannot make common node\n", d->name);
- d->node = NULL;
- continue;
- }
- NG_NODE_SET_PRIVATE (d->node, d);
- sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE,
- c->board->num*NCHAN + c->num);
- if (ng_name_node (d->node, d->nodename)) {
- printf ("%s: cannot name node\n", d->nodename);
- NG_NODE_UNREF (d->node);
- continue;
- }
- d->queue.ifq_maxlen = IFQ_MAXLEN;
- d->hi_queue.ifq_maxlen = IFQ_MAXLEN;
- mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF);
- mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF);
- callout_init (&d->timeout_handle,
- cp_mpsafenet ? CALLOUT_MPSAFE : 0);
-#else /*NETGRAPH*/
- d->ifp = if_alloc(IFT_PPP);
- if (d->ifp == NULL) {
- printf ("%s: cannot if_alloc() interface\n", d->name);
- continue;
- }
- d->ifp->if_softc = d;
- if_initname (d->ifp, "cp", b->num * NCHAN + c->num);
- d->ifp->if_mtu = PP_MTU;
- d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
- if (!cp_mpsafenet)
- d->ifp->if_flags |= IFF_NEEDSGIANT;
- d->ifp->if_ioctl = cp_sioctl;
- d->ifp->if_start = cp_ifstart;
- d->ifp->if_watchdog = cp_ifwatchdog;
- d->ifp->if_init = cp_initialize;
- d->queue.ifq_maxlen = NRBUF;
- mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF);
- sppp_attach (d->ifp);
- if_attach (d->ifp);
- IFP2SP(d->ifp)->pp_tlf = cp_tlf;
- IFP2SP(d->ifp)->pp_tls = cp_tls;
- /* If BPF is in the kernel, call the attach for it.
- * The header size of PPP or Cisco/HDLC is 4 bytes. */
- bpfattach (d->ifp, DLT_PPP, 4);
-#endif /*NETGRAPH*/
- cp_start_e1 (c);
- cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys);
-
- /* Register callback functions. */
- cp_register_transmit (c, &cp_transmit);
- cp_register_receive (c, &cp_receive);
- cp_register_error (c, &cp_error);
- d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT,
- GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num);
- }
- CP_LOCK (bd);
- b->sys = bd;
- adapter[unit] = b;
- CP_UNLOCK (bd);
- splx (s);
- return 0;
-}
-
-static int cp_detach (device_t dev)
-{
- bdrv_t *bd = device_get_softc (dev);
- cp_board_t *b = bd->board;
- cp_chan_t *c;
- int s;
-
- KASSERT (mtx_initialized (&bd->cp_mtx), ("cp mutex not initialized"));
- s = splimp ();
- CP_LOCK (bd);
- /* Check if the device is busy (open). */
- for (c = b->chan; c < b->chan + NCHAN; ++c) {
- drv_t *d = (drv_t*) c->sys;
-
- if (! d || ! d->chan->type)
- continue;
- if (d->running) {
- CP_UNLOCK (bd);
- splx (s);
- return EBUSY;
- }
- }
-
- /* Ok, we can unload driver */
- /* At first we should stop all channels */
- for (c = b->chan; c < b->chan + NCHAN; ++c) {
- drv_t *d = (drv_t*) c->sys;
-
- if (! d || ! d->chan->type)
- continue;
-
- cp_stop_chan (c);
- cp_stop_e1 (c);
- cp_set_dtr (d->chan, 0);
- cp_set_rts (d->chan, 0);
- }
-
- /* Reset the adapter. */
- cp_destroy = 1;
- cp_interrupt_poll (b, 1);
- cp_led_off (b);
- cp_reset (b, 0 ,0);
- callout_stop (&led_timo[b->num]);
-
- /* Disable the interrupt request. */
- bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand);
-
- for (c=b->chan; c<b->chan+NCHAN; ++c) {
- drv_t *d = (drv_t*) c->sys;
-
- if (! d || ! d->chan->type)
- continue;
-#ifndef NETGRAPH
- /* Detach from the packet filter list of interfaces. */
- bpfdetach (d->ifp);
-
- /* Detach from the sync PPP list. */
- sppp_detach (d->ifp);
-
- /* Detach from the system list of interfaces. */
- if_detach (d->ifp);
- if_free (d->ifp);
- IF_DRAIN (&d->queue);
- mtx_destroy (&d->queue.ifq_mtx);
-#else
- if (d->node) {
- ng_rmnode_self (d->node);
- NG_NODE_UNREF (d->node);
- d->node = NULL;
- }
- mtx_destroy (&d->queue.ifq_mtx);
- mtx_destroy (&d->hi_queue.ifq_mtx);
-#endif
- destroy_dev (d->devt);
- }
-
- b->sys = NULL;
- CP_UNLOCK (bd);
-
- bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
- bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq);
- bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res);
-
- CP_LOCK (bd);
- cp_led_off (b);
- CP_UNLOCK (bd);
- callout_drain (&led_timo[b->num]);
- splx (s);
-
- s = splimp ();
- for (c = b->chan; c < b->chan + NCHAN; ++c) {
- drv_t *d = (drv_t*) c->sys;
-
- if (! d || ! d->chan->type)
- continue;
- channel [b->num*NCHAN + c->num] = 0;
- /* Deallocate buffers. */
- cp_bus_dma_mem_free (&d->dmamem);
- }
- adapter [b->num] = 0;
- cp_bus_dma_mem_free (&bd->dmamem);
- free (b, M_DEVBUF);
- splx (s);
- mtx_destroy (&bd->cp_mtx);
- return 0;
-}
-
-#ifndef NETGRAPH
-static void cp_ifstart (struct ifnet *ifp)
-{
- drv_t *d = ifp->if_softc;
- bdrv_t *bd = d->board->sys;
-
- CP_LOCK (bd);
- cp_start (d);
- CP_UNLOCK (bd);
-}
-
-static void cp_ifwatchdog (struct ifnet *ifp)
-{
- drv_t *d = ifp->if_softc;
-
- cp_watchdog (d);
-}
-
-static void cp_tlf (struct sppp *sp)
-{
- drv_t *d = SP2IFP(sp)->if_softc;
-
- CP_DEBUG2 (d, ("cp_tlf\n"));
- /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */
-/* cp_set_dtr (d->chan, 0);*/
-/* cp_set_rts (d->chan, 0);*/
- if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO))
- sp->pp_down (sp);
-}
-
-static void cp_tls (struct sppp *sp)
-{
- drv_t *d = SP2IFP(sp)->if_softc;
-
- CP_DEBUG2 (d, ("cp_tls\n"));
- if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO))
- sp->pp_up (sp);
-}
-
-/*
- * Process an ioctl request.
- */
-static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
-{
- drv_t *d = ifp->if_softc;
- bdrv_t *bd = d->board->sys;
- int error, s, was_up, should_be_up;
-
- was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0;
- error = sppp_ioctl (ifp, cmd, data);
-
- if (error)
- return error;
-
- if (! (ifp->if_flags & IFF_DEBUG))
- d->chan->debug = 0;
- else if (! d->chan->debug)
- d->chan->debug = 1;
-
- switch (cmd) {
- default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0;
- case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0;
- case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0;
- case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break;
- case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break;
- }
-
- /* We get here only in case of SIFFLAGS or SIFADDR. */
- s = splimp ();
- CP_LOCK (bd);
- should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0;
- if (! was_up && should_be_up) {
- /* Interface goes up -- start it. */
- cp_up (d);
- cp_start (d);
- } else if (was_up && ! should_be_up) {
- /* Interface is going down -- stop it. */
-/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/
- cp_down (d);
- }
- CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd));
- CP_UNLOCK (bd);
- splx (s);
- return 0;
-}
-
-/*
- * Initialization of interface.
- * It seems to be never called by upper level?
- */
-static void cp_initialize (void *softc)
-{
- drv_t *d = softc;
-
- CP_DEBUG (d, ("cp_initialize\n"));
-}
-#endif /*NETGRAPH*/
-
-/*
- * Stop the interface. Called on splimp().
- */
-static void cp_down (drv_t *d)
-{
- CP_DEBUG (d, ("cp_down\n"));
- /* Interface is going down -- stop it. */
- cp_set_dtr (d->chan, 0);
- cp_set_rts (d->chan, 0);
-
- d->running = 0;
-}
-
-/*
- * Start the interface. Called on splimp().
- */
-static void cp_up (drv_t *d)
-{
- CP_DEBUG (d, ("cp_up\n"));
- cp_set_dtr (d->chan, 1);
- cp_set_rts (d->chan, 1);
- d->running = 1;
-}
-
-/*
- * Start output on the interface. Get another datagram to send
- * off of the interface queue, and copy it to the interface
- * before starting the output.
- */
-static void cp_send (drv_t *d)
-{
- struct mbuf *m;
- u_short len;
-
- CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te));
-
- /* No output if the interface is down. */
- if (! d->running)
- return;
-
- /* No output if the modem is off. */
- if (! (d->chan->lloop || d->chan->type != T_SERIAL ||
- cp_get_dsr (d->chan)))
- return;
-
- while (cp_transmit_space (d->chan)) {
- /* Get the packet to send. */
-#ifdef NETGRAPH
- IF_DEQUEUE (&d->hi_queue, m);
- if (! m)
- IF_DEQUEUE (&d->queue, m);
-#else
- m = sppp_dequeue (d->ifp);
-#endif
- if (! m)
- return;
-#ifndef NETGRAPH
- if (d->ifp->if_bpf)
- BPF_MTAP (d->ifp, m);
-#endif
- len = m_length (m, NULL);
- if (len >= BUFSZ)
- printf ("%s: too long packet: %d bytes: ",
- d->name, len);
- else if (! m->m_next)
- cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0);
- else {
- u_char *buf = d->chan->tbuf[d->chan->te];
- m_copydata (m, 0, len, buf);
- cp_send_packet (d->chan, buf, len, 0);
- }
- m_freem (m);
- /* Set up transmit timeout, if the transmit ring is not empty.*/
-#ifdef NETGRAPH
- d->timeout = 10;
-#else
- d->ifp->if_timer = 10;
-#endif
- }
-#ifndef NETGRAPH
- d->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-#endif
-}
-
-/*
- * Start output on the interface.
- * Always called on splimp().
- */
-static void cp_start (drv_t *d)
-{
- if (d->running) {
- if (! d->chan->dtr)
- cp_set_dtr (d->chan, 1);
- if (! d->chan->rts)
- cp_set_rts (d->chan, 1);
- cp_send (d);
- }
-}
-
-/*
- * Handle transmit timeouts.
- * Recover after lost transmit interrupts.
- * Always called on splimp().
- */
-static void cp_watchdog (drv_t *d)
-{
- bdrv_t *bd = d->board->sys;
- CP_DEBUG (d, ("device timeout\n"));
- if (d->running) {
- int s = splimp ();
-
- CP_LOCK (bd);
- cp_stop_chan (d->chan);
- cp_stop_e1 (d->chan);
- cp_start_e1 (d->chan);
- cp_start_chan (d->chan, 1, 1, 0, 0);
- cp_set_dtr (d->chan, 1);
- cp_set_rts (d->chan, 1);
- cp_start (d);
- CP_UNLOCK (bd);
- splx (s);
- }
-}
-
-static void cp_transmit (cp_chan_t *c, void *attachment, int len)
-{
- drv_t *d = c->sys;
-
-#ifdef NETGRAPH
- d->timeout = 0;
-#else
- ++d->ifp->if_opackets;
- d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- d->ifp->if_timer = 0;
-#endif
- cp_start (d);
-}
-
-static void cp_receive (cp_chan_t *c, unsigned char *data, int len)
-{
- drv_t *d = c->sys;
- struct mbuf *m;
-#ifdef NETGRAPH
- int error;
-#endif
-
- if (! d->running)
- return;
-
- m = makembuf (data, len);
- if (! m) {
- CP_DEBUG (d, ("no memory for packet\n"));
-#ifndef NETGRAPH
- ++d->ifp->if_iqdrops;
-#endif
- return;
- }
- if (c->debug > 1)
- printmbuf (m);
-#ifdef NETGRAPH
- m->m_pkthdr.rcvif = 0;
- NG_SEND_DATA_ONLY (error, d->hook, m);
-#else
- ++d->ifp->if_ipackets;
- m->m_pkthdr.rcvif = d->ifp;
- /* Check if there's a BPF listener on this interface.
- * If so, hand off the raw packet to bpf. */
- if (d->ifp->if_bpf)
- BPF_TAP (d->ifp, data, len);
- IF_ENQUEUE (&d->queue, m);
-#endif
-}
-
-static void cp_error (cp_chan_t *c, int data)
-{
- drv_t *d = c->sys;
-
- switch (data) {
- case CP_FRAME:
- CP_DEBUG (d, ("frame error\n"));
-#ifndef NETGRAPH
- ++d->ifp->if_ierrors;
-#endif
- break;
- case CP_CRC:
- CP_DEBUG (d, ("crc error\n"));
-#ifndef NETGRAPH
- ++d->ifp->if_ierrors;
-#endif
- break;
- case CP_OVERRUN:
- CP_DEBUG (d, ("overrun error\n"));
-#ifndef NETGRAPH
- ++d->ifp->if_collisions;
- ++d->ifp->if_ierrors;
-#endif
- break;
- case CP_OVERFLOW:
- CP_DEBUG (d, ("overflow error\n"));
-#ifndef NETGRAPH
- ++d->ifp->if_ierrors;
-#endif
- break;
- case CP_UNDERRUN:
- CP_DEBUG (d, ("underrun error\n"));
-#ifdef NETGRAPH
- d->timeout = 0;
-#else
- ++d->ifp->if_oerrors;
- d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- d->ifp->if_timer = 0;
-#endif
- cp_start (d);
- break;
- default:
- CP_DEBUG (d, ("error #%d\n", data));
- break;
- }
-}
-
#ifdef NETGRAPH
static int ng_cp_constructor (node_p node)
{
diff --git a/sys/dev/ctau/if_ct.c b/sys/dev/ctau/if_ct.c
index 251b3fa..fcc0a96 100644
--- a/sys/dev/ctau/if_ct.c
+++ b/sys/dev/ctau/if_ct.c
@@ -186,538 +186,9 @@ static drv_t *channel [NCTAU*NCHAN];
static struct callout led_timo [NCTAU];
static struct callout timeout_handle;
-static int ct_open (struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
- drv_t *d;
-
- if (minor(dev) >= NCTAU*NCHAN || ! (d = channel[minor(dev)]))
- return ENXIO;
-
- CT_DEBUG2 (d, ("ct_open\n"));
- return 0;
-}
-
-static int ct_close (struct cdev *dev, int fflag, int devtype, struct thread *td)
-{
- drv_t *d = channel [minor(dev)];
-
- if (!d)
- return 0;
-
- CT_DEBUG2 (d, ("ct_close\n"));
- return 0;
-}
-
-static int ct_modem_status (ct_chan_t *c)
-{
- drv_t *d = c->sys;
- bdrv_t *bd;
- int status, s;
-
- if (!d)
- return 0;
-
- bd = d->bd;
-
- status = d->running ? TIOCM_LE : 0;
- s = splimp ();
- CT_LOCK (bd);
- if (ct_get_cd (c)) status |= TIOCM_CD;
- if (ct_get_cts (c)) status |= TIOCM_CTS;
- if (ct_get_dsr (c)) status |= TIOCM_DSR;
- if (c->dtr) status |= TIOCM_DTR;
- if (c->rts) status |= TIOCM_RTS;
- CT_UNLOCK (bd);
- splx (s);
- return status;
-}
-
-/*
- * Process an ioctl request on /dev/cronyx/ctauN.
- */
-static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
-{
- drv_t *d = channel [minor (dev)];
- bdrv_t *bd;
- ct_chan_t *c;
- struct serial_statistics *st;
- struct e1_statistics *opte1;
- int error, s;
- char mask[16];
-
- if (!d || !d->chan)
- return 0;
-
- bd = d->bd;
- c = d->chan;
-
- switch (cmd) {
- case SERIAL_GETREGISTERED:
- bzero (mask, sizeof(mask));
- for (s=0; s<NCTAU*NCHAN; ++s)
- if (channel [s])
- mask [s/8] |= 1 << (s & 7);
- bcopy (mask, data, sizeof (mask));
- return 0;
-
-#ifndef NETGRAPH
- case SERIAL_GETPROTO:
- strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" :
- (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp");
- return 0;
-
- case SERIAL_SETPROTO:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if (d->ifp->if_drv_flags & IFF_DRV_RUNNING)
- return EBUSY;
- if (! strcmp ("cisco", (char*)data)) {
- IFP2SP(d->ifp)->pp_flags &= ~(PP_FR);
- IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE;
- d->ifp->if_flags |= PP_CISCO;
- } else if (! strcmp ("fr", (char*)data)) {
- d->ifp->if_flags &= ~(PP_CISCO);
- IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE;
- } else if (! strcmp ("ppp", (char*)data)) {
- IFP2SP(d->ifp)->pp_flags &= ~(PP_FR | PP_KEEPALIVE);
- d->ifp->if_flags &= ~(PP_CISCO);
- } else
- return EINVAL;
- return 0;
-
- case SERIAL_GETKEEPALIVE:
- if ((IFP2SP(d->ifp)->pp_flags & PP_FR) ||
- (d->ifp->if_flags & PP_CISCO))
- return EINVAL;
- *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0;
- return 0;
-
- case SERIAL_SETKEEPALIVE:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if ((IFP2SP(d->ifp)->pp_flags & PP_FR) ||
- (d->ifp->if_flags & PP_CISCO))
- return EINVAL;
- if (*(int*)data)
- IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE;
- else
- IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE;
- return 0;
-#endif /*NETGRAPH*/
-
- case SERIAL_GETMODE:
- *(int*)data = SERIAL_HDLC;
- return 0;
-
- case SERIAL_GETCFG:
- if (c->mode == M_HDLC)
- return EINVAL;
- switch (ct_get_config (c->board)) {
- default: *(char*)data = 'a'; break;
- case CFG_B: *(char*)data = 'b'; break;
- case CFG_C: *(char*)data = 'c'; break;
- }
- return 0;
-
- case SERIAL_SETCFG:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if (c->mode == M_HDLC)
- return EINVAL;
- s = splimp ();
- CT_LOCK (bd);
- switch (*(char*)data) {
- case 'a': ct_set_config (c->board, CFG_A); break;
- case 'b': ct_set_config (c->board, CFG_B); break;
- case 'c': ct_set_config (c->board, CFG_C); break;
- }
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETSTAT:
- st = (struct serial_statistics*) data;
- st->rintr = c->rintr;
- st->tintr = c->tintr;
- st->mintr = c->mintr;
- st->ibytes = c->ibytes;
- st->ipkts = c->ipkts;
- st->ierrs = c->ierrs;
- st->obytes = c->obytes;
- st->opkts = c->opkts;
- st->oerrs = c->oerrs;
- return 0;
-
- case SERIAL_GETESTAT:
- opte1 = (struct e1_statistics*)data;
- opte1->status = c->status;
- opte1->cursec = c->cursec;
- opte1->totsec = c->totsec + c->cursec;
-
- opte1->currnt.bpv = c->currnt.bpv;
- opte1->currnt.fse = c->currnt.fse;
- opte1->currnt.crce = c->currnt.crce;
- opte1->currnt.rcrce = c->currnt.rcrce;
- opte1->currnt.uas = c->currnt.uas;
- opte1->currnt.les = c->currnt.les;
- opte1->currnt.es = c->currnt.es;
- opte1->currnt.bes = c->currnt.bes;
- opte1->currnt.ses = c->currnt.ses;
- opte1->currnt.oofs = c->currnt.oofs;
- opte1->currnt.css = c->currnt.css;
- opte1->currnt.dm = c->currnt.dm;
-
- opte1->total.bpv = c->total.bpv + c->currnt.bpv;
- opte1->total.fse = c->total.fse + c->currnt.fse;
- opte1->total.crce = c->total.crce + c->currnt.crce;
- opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce;
- opte1->total.uas = c->total.uas + c->currnt.uas;
- opte1->total.les = c->total.les + c->currnt.les;
- opte1->total.es = c->total.es + c->currnt.es;
- opte1->total.bes = c->total.bes + c->currnt.bes;
- opte1->total.ses = c->total.ses + c->currnt.ses;
- opte1->total.oofs = c->total.oofs + c->currnt.oofs;
- opte1->total.css = c->total.css + c->currnt.css;
- opte1->total.dm = c->total.dm + c->currnt.dm;
- for (s=0; s<48; ++s) {
- opte1->interval[s].bpv = c->interval[s].bpv;
- opte1->interval[s].fse = c->interval[s].fse;
- opte1->interval[s].crce = c->interval[s].crce;
- opte1->interval[s].rcrce = c->interval[s].rcrce;
- opte1->interval[s].uas = c->interval[s].uas;
- opte1->interval[s].les = c->interval[s].les;
- opte1->interval[s].es = c->interval[s].es;
- opte1->interval[s].bes = c->interval[s].bes;
- opte1->interval[s].ses = c->interval[s].ses;
- opte1->interval[s].oofs = c->interval[s].oofs;
- opte1->interval[s].css = c->interval[s].css;
- opte1->interval[s].dm = c->interval[s].dm;
- }
- return 0;
-
- case SERIAL_CLRSTAT:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- c->rintr = 0;
- c->tintr = 0;
- c->mintr = 0;
- c->ibytes = 0;
- c->ipkts = 0;
- c->ierrs = 0;
- c->obytes = 0;
- c->opkts = 0;
- c->oerrs = 0;
- bzero (&c->currnt, sizeof (c->currnt));
- bzero (&c->total, sizeof (c->total));
- bzero (c->interval, sizeof (c->interval));
- return 0;
-
- case SERIAL_GETBAUD:
- *(long*)data = ct_get_baud(c);
- return 0;
-
- case SERIAL_SETBAUD:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- s = splimp ();
- CT_LOCK (bd);
- ct_set_baud (c, *(long*)data);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETLOOP:
- *(int*)data = ct_get_loop (c);
- return 0;
-
- case SERIAL_SETLOOP:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- s = splimp ();
- CT_LOCK (bd);
- ct_set_loop (c, *(int*)data);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETDPLL:
- if (c->mode == M_E1 || c->mode == M_G703)
- return EINVAL;
- *(int*)data = ct_get_dpll (c);
- return 0;
-
- case SERIAL_SETDPLL:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if (c->mode == M_E1 || c->mode == M_G703)
- return EINVAL;
- s = splimp ();
- CT_LOCK (bd);
- ct_set_dpll (c, *(int*)data);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETNRZI:
- if (c->mode == M_E1 || c->mode == M_G703)
- return EINVAL;
- *(int*)data = ct_get_nrzi (c);
- return 0;
-
- case SERIAL_SETNRZI:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if (c->mode == M_E1 || c->mode == M_G703)
- return EINVAL;
- s = splimp ();
- CT_LOCK (bd);
- ct_set_nrzi (c, *(int*)data);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETDEBUG:
- *(int*)data = c->debug;
- return 0;
-
- case SERIAL_SETDEBUG:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- c->debug = *(int*)data;
-#ifndef NETGRAPH
- if (d->chan->debug)
- d->ifp->if_flags |= IFF_DEBUG;
- else
- d->ifp->if_flags &= (~IFF_DEBUG);
-#endif
- return 0;
-
- case SERIAL_GETHIGAIN:
- if (c->mode != M_E1)
- return EINVAL;
- *(int*)data = ct_get_higain (c);
- return 0;
-
- case SERIAL_SETHIGAIN:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- s = splimp ();
- CT_LOCK (bd);
- ct_set_higain (c, *(int*)data);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETPHONY:
- CT_DEBUG2 (d, ("ioctl: getphony\n"));
- if (c->mode != M_E1)
- return EINVAL;
- *(int*)data = c->gopt.phony;
- return 0;
-
- case SERIAL_SETPHONY:
- CT_DEBUG2 (d, ("ioctl: setphony\n"));
- if (c->mode != M_E1)
- return EINVAL;
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- s = splimp ();
- CT_LOCK (bd);
- ct_set_phony (c, *(int*)data);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETCLK:
- if (c->mode != M_E1 && c->mode != M_G703)
- return EINVAL;
- switch (ct_get_clk(c)) {
- default: *(int*)data = E1CLK_INTERNAL; break;
- case GCLK_RCV: *(int*)data = E1CLK_RECEIVE; break;
- case GCLK_RCLKO: *(int*)data = c->num ?
- E1CLK_RECEIVE_CHAN0 : E1CLK_RECEIVE_CHAN1; break;
- }
- return 0;
-
- case SERIAL_SETCLK:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- s = splimp ();
- CT_LOCK (bd);
- switch (*(int*)data) {
- default: ct_set_clk (c, GCLK_INT); break;
- case E1CLK_RECEIVE: ct_set_clk (c, GCLK_RCV); break;
- case E1CLK_RECEIVE_CHAN0:
- case E1CLK_RECEIVE_CHAN1:
- ct_set_clk (c, GCLK_RCLKO); break;
- }
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETTIMESLOTS:
- if (c->mode != M_E1)
- return EINVAL;
- *(long*)data = ct_get_ts (c);
- return 0;
-
- case SERIAL_SETTIMESLOTS:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- s = splimp ();
- CT_LOCK (bd);
- ct_set_ts (c, *(long*)data);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETSUBCHAN:
- if (c->mode != M_E1)
- return EINVAL;
- *(long*)data = ct_get_subchan (c->board);
- return 0;
-
- case SERIAL_SETSUBCHAN:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- s = splimp ();
- CT_LOCK (bd);
- ct_set_subchan (c->board, *(long*)data);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETINVCLK:
- case SERIAL_GETINVTCLK:
- if (c->mode == M_E1 || c->mode == M_G703)
- return EINVAL;
- *(int*)data = ct_get_invtxc (c);
- return 0;
-
- case SERIAL_GETINVRCLK:
- if (c->mode == M_E1 || c->mode == M_G703)
- return EINVAL;
- *(int*)data = ct_get_invrxc (c);
- return 0;
-
- case SERIAL_SETINVCLK:
- case SERIAL_SETINVTCLK:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if (c->mode == M_E1 || c->mode == M_G703)
- return EINVAL;
- s = splimp ();
- CT_LOCK (bd);
- ct_set_invtxc (c, *(int*)data);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_SETINVRCLK:
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if (c->mode == M_E1 || c->mode == M_G703)
- return EINVAL;
- s = splimp ();
- CT_LOCK (bd);
- ct_set_invrxc (c, *(int*)data);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETLEVEL:
- if (c->mode != M_G703)
- return EINVAL;
- s = splimp ();
- CT_LOCK (bd);
- *(int*)data = ct_get_lq (c);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case TIOCSDTR: /* Set DTR */
- s = splimp ();
- CT_LOCK (bd);
- ct_set_dtr (c, 1);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case TIOCCDTR: /* Clear DTR */
- s = splimp ();
- CT_LOCK (bd);
- ct_set_dtr (c, 0);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case TIOCMSET: /* Set DTR/RTS */
- s = splimp ();
- CT_LOCK (bd);
- ct_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0);
- ct_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case TIOCMBIS: /* Add DTR/RTS */
- s = splimp ();
- CT_LOCK (bd);
- if (*(int*)data & TIOCM_DTR) ct_set_dtr (c, 1);
- if (*(int*)data & TIOCM_RTS) ct_set_rts (c, 1);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case TIOCMBIC: /* Clear DTR/RTS */
- s = splimp ();
- CT_LOCK (bd);
- if (*(int*)data & TIOCM_DTR) ct_set_dtr (c, 0);
- if (*(int*)data & TIOCM_RTS) ct_set_rts (c, 0);
- CT_UNLOCK (bd);
- splx (s);
- return 0;
-
- case TIOCMGET: /* Get modem status */
- *(int*)data = ct_modem_status (c);
- return 0;
- }
- return ENOTTY;
-}
-
-
+static int ct_open (struct cdev *dev, int oflags, int devtype, struct thread *td);
+static int ct_close (struct cdev *dev, int fflag, int devtype, struct thread *td);
+static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td);
static struct cdevsw ct_cdevsw = {
.d_version = D_VERSION,
.d_open = ct_open,
@@ -1748,6 +1219,537 @@ static void ct_error (ct_chan_t *c, int data)
}
}
+static int ct_open (struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ drv_t *d;
+
+ if (minor(dev) >= NCTAU*NCHAN || ! (d = channel[minor(dev)]))
+ return ENXIO;
+
+ CT_DEBUG2 (d, ("ct_open\n"));
+ return 0;
+}
+
+static int ct_close (struct cdev *dev, int fflag, int devtype, struct thread *td)
+{
+ drv_t *d = channel [minor(dev)];
+
+ if (!d)
+ return 0;
+
+ CT_DEBUG2 (d, ("ct_close\n"));
+ return 0;
+}
+
+static int ct_modem_status (ct_chan_t *c)
+{
+ drv_t *d = c->sys;
+ bdrv_t *bd;
+ int status, s;
+
+ if (!d)
+ return 0;
+
+ bd = d->bd;
+
+ status = d->running ? TIOCM_LE : 0;
+ s = splimp ();
+ CT_LOCK (bd);
+ if (ct_get_cd (c)) status |= TIOCM_CD;
+ if (ct_get_cts (c)) status |= TIOCM_CTS;
+ if (ct_get_dsr (c)) status |= TIOCM_DSR;
+ if (c->dtr) status |= TIOCM_DTR;
+ if (c->rts) status |= TIOCM_RTS;
+ CT_UNLOCK (bd);
+ splx (s);
+ return status;
+}
+
+/*
+ * Process an ioctl request on /dev/cronyx/ctauN.
+ */
+static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
+{
+ drv_t *d = channel [minor (dev)];
+ bdrv_t *bd;
+ ct_chan_t *c;
+ struct serial_statistics *st;
+ struct e1_statistics *opte1;
+ int error, s;
+ char mask[16];
+
+ if (!d || !d->chan)
+ return 0;
+
+ bd = d->bd;
+ c = d->chan;
+
+ switch (cmd) {
+ case SERIAL_GETREGISTERED:
+ bzero (mask, sizeof(mask));
+ for (s=0; s<NCTAU*NCHAN; ++s)
+ if (channel [s])
+ mask [s/8] |= 1 << (s & 7);
+ bcopy (mask, data, sizeof (mask));
+ return 0;
+
+#ifndef NETGRAPH
+ case SERIAL_GETPROTO:
+ strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" :
+ (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp");
+ return 0;
+
+ case SERIAL_SETPROTO:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if (d->ifp->if_drv_flags & IFF_DRV_RUNNING)
+ return EBUSY;
+ if (! strcmp ("cisco", (char*)data)) {
+ IFP2SP(d->ifp)->pp_flags &= ~(PP_FR);
+ IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE;
+ d->ifp->if_flags |= PP_CISCO;
+ } else if (! strcmp ("fr", (char*)data)) {
+ d->ifp->if_flags &= ~(PP_CISCO);
+ IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE;
+ } else if (! strcmp ("ppp", (char*)data)) {
+ IFP2SP(d->ifp)->pp_flags &= ~(PP_FR | PP_KEEPALIVE);
+ d->ifp->if_flags &= ~(PP_CISCO);
+ } else
+ return EINVAL;
+ return 0;
+
+ case SERIAL_GETKEEPALIVE:
+ if ((IFP2SP(d->ifp)->pp_flags & PP_FR) ||
+ (d->ifp->if_flags & PP_CISCO))
+ return EINVAL;
+ *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0;
+ return 0;
+
+ case SERIAL_SETKEEPALIVE:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if ((IFP2SP(d->ifp)->pp_flags & PP_FR) ||
+ (d->ifp->if_flags & PP_CISCO))
+ return EINVAL;
+ if (*(int*)data)
+ IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE;
+ else
+ IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE;
+ return 0;
+#endif /*NETGRAPH*/
+
+ case SERIAL_GETMODE:
+ *(int*)data = SERIAL_HDLC;
+ return 0;
+
+ case SERIAL_GETCFG:
+ if (c->mode == M_HDLC)
+ return EINVAL;
+ switch (ct_get_config (c->board)) {
+ default: *(char*)data = 'a'; break;
+ case CFG_B: *(char*)data = 'b'; break;
+ case CFG_C: *(char*)data = 'c'; break;
+ }
+ return 0;
+
+ case SERIAL_SETCFG:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if (c->mode == M_HDLC)
+ return EINVAL;
+ s = splimp ();
+ CT_LOCK (bd);
+ switch (*(char*)data) {
+ case 'a': ct_set_config (c->board, CFG_A); break;
+ case 'b': ct_set_config (c->board, CFG_B); break;
+ case 'c': ct_set_config (c->board, CFG_C); break;
+ }
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETSTAT:
+ st = (struct serial_statistics*) data;
+ st->rintr = c->rintr;
+ st->tintr = c->tintr;
+ st->mintr = c->mintr;
+ st->ibytes = c->ibytes;
+ st->ipkts = c->ipkts;
+ st->ierrs = c->ierrs;
+ st->obytes = c->obytes;
+ st->opkts = c->opkts;
+ st->oerrs = c->oerrs;
+ return 0;
+
+ case SERIAL_GETESTAT:
+ opte1 = (struct e1_statistics*)data;
+ opte1->status = c->status;
+ opte1->cursec = c->cursec;
+ opte1->totsec = c->totsec + c->cursec;
+
+ opte1->currnt.bpv = c->currnt.bpv;
+ opte1->currnt.fse = c->currnt.fse;
+ opte1->currnt.crce = c->currnt.crce;
+ opte1->currnt.rcrce = c->currnt.rcrce;
+ opte1->currnt.uas = c->currnt.uas;
+ opte1->currnt.les = c->currnt.les;
+ opte1->currnt.es = c->currnt.es;
+ opte1->currnt.bes = c->currnt.bes;
+ opte1->currnt.ses = c->currnt.ses;
+ opte1->currnt.oofs = c->currnt.oofs;
+ opte1->currnt.css = c->currnt.css;
+ opte1->currnt.dm = c->currnt.dm;
+
+ opte1->total.bpv = c->total.bpv + c->currnt.bpv;
+ opte1->total.fse = c->total.fse + c->currnt.fse;
+ opte1->total.crce = c->total.crce + c->currnt.crce;
+ opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce;
+ opte1->total.uas = c->total.uas + c->currnt.uas;
+ opte1->total.les = c->total.les + c->currnt.les;
+ opte1->total.es = c->total.es + c->currnt.es;
+ opte1->total.bes = c->total.bes + c->currnt.bes;
+ opte1->total.ses = c->total.ses + c->currnt.ses;
+ opte1->total.oofs = c->total.oofs + c->currnt.oofs;
+ opte1->total.css = c->total.css + c->currnt.css;
+ opte1->total.dm = c->total.dm + c->currnt.dm;
+ for (s=0; s<48; ++s) {
+ opte1->interval[s].bpv = c->interval[s].bpv;
+ opte1->interval[s].fse = c->interval[s].fse;
+ opte1->interval[s].crce = c->interval[s].crce;
+ opte1->interval[s].rcrce = c->interval[s].rcrce;
+ opte1->interval[s].uas = c->interval[s].uas;
+ opte1->interval[s].les = c->interval[s].les;
+ opte1->interval[s].es = c->interval[s].es;
+ opte1->interval[s].bes = c->interval[s].bes;
+ opte1->interval[s].ses = c->interval[s].ses;
+ opte1->interval[s].oofs = c->interval[s].oofs;
+ opte1->interval[s].css = c->interval[s].css;
+ opte1->interval[s].dm = c->interval[s].dm;
+ }
+ return 0;
+
+ case SERIAL_CLRSTAT:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ c->rintr = 0;
+ c->tintr = 0;
+ c->mintr = 0;
+ c->ibytes = 0;
+ c->ipkts = 0;
+ c->ierrs = 0;
+ c->obytes = 0;
+ c->opkts = 0;
+ c->oerrs = 0;
+ bzero (&c->currnt, sizeof (c->currnt));
+ bzero (&c->total, sizeof (c->total));
+ bzero (c->interval, sizeof (c->interval));
+ return 0;
+
+ case SERIAL_GETBAUD:
+ *(long*)data = ct_get_baud(c);
+ return 0;
+
+ case SERIAL_SETBAUD:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_baud (c, *(long*)data);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETLOOP:
+ *(int*)data = ct_get_loop (c);
+ return 0;
+
+ case SERIAL_SETLOOP:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_loop (c, *(int*)data);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETDPLL:
+ if (c->mode == M_E1 || c->mode == M_G703)
+ return EINVAL;
+ *(int*)data = ct_get_dpll (c);
+ return 0;
+
+ case SERIAL_SETDPLL:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if (c->mode == M_E1 || c->mode == M_G703)
+ return EINVAL;
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_dpll (c, *(int*)data);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETNRZI:
+ if (c->mode == M_E1 || c->mode == M_G703)
+ return EINVAL;
+ *(int*)data = ct_get_nrzi (c);
+ return 0;
+
+ case SERIAL_SETNRZI:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if (c->mode == M_E1 || c->mode == M_G703)
+ return EINVAL;
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_nrzi (c, *(int*)data);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETDEBUG:
+ *(int*)data = c->debug;
+ return 0;
+
+ case SERIAL_SETDEBUG:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ c->debug = *(int*)data;
+#ifndef NETGRAPH
+ if (d->chan->debug)
+ d->ifp->if_flags |= IFF_DEBUG;
+ else
+ d->ifp->if_flags &= (~IFF_DEBUG);
+#endif
+ return 0;
+
+ case SERIAL_GETHIGAIN:
+ if (c->mode != M_E1)
+ return EINVAL;
+ *(int*)data = ct_get_higain (c);
+ return 0;
+
+ case SERIAL_SETHIGAIN:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_higain (c, *(int*)data);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETPHONY:
+ CT_DEBUG2 (d, ("ioctl: getphony\n"));
+ if (c->mode != M_E1)
+ return EINVAL;
+ *(int*)data = c->gopt.phony;
+ return 0;
+
+ case SERIAL_SETPHONY:
+ CT_DEBUG2 (d, ("ioctl: setphony\n"));
+ if (c->mode != M_E1)
+ return EINVAL;
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_phony (c, *(int*)data);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETCLK:
+ if (c->mode != M_E1 && c->mode != M_G703)
+ return EINVAL;
+ switch (ct_get_clk(c)) {
+ default: *(int*)data = E1CLK_INTERNAL; break;
+ case GCLK_RCV: *(int*)data = E1CLK_RECEIVE; break;
+ case GCLK_RCLKO: *(int*)data = c->num ?
+ E1CLK_RECEIVE_CHAN0 : E1CLK_RECEIVE_CHAN1; break;
+ }
+ return 0;
+
+ case SERIAL_SETCLK:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ s = splimp ();
+ CT_LOCK (bd);
+ switch (*(int*)data) {
+ default: ct_set_clk (c, GCLK_INT); break;
+ case E1CLK_RECEIVE: ct_set_clk (c, GCLK_RCV); break;
+ case E1CLK_RECEIVE_CHAN0:
+ case E1CLK_RECEIVE_CHAN1:
+ ct_set_clk (c, GCLK_RCLKO); break;
+ }
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETTIMESLOTS:
+ if (c->mode != M_E1)
+ return EINVAL;
+ *(long*)data = ct_get_ts (c);
+ return 0;
+
+ case SERIAL_SETTIMESLOTS:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_ts (c, *(long*)data);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETSUBCHAN:
+ if (c->mode != M_E1)
+ return EINVAL;
+ *(long*)data = ct_get_subchan (c->board);
+ return 0;
+
+ case SERIAL_SETSUBCHAN:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_subchan (c->board, *(long*)data);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETINVCLK:
+ case SERIAL_GETINVTCLK:
+ if (c->mode == M_E1 || c->mode == M_G703)
+ return EINVAL;
+ *(int*)data = ct_get_invtxc (c);
+ return 0;
+
+ case SERIAL_GETINVRCLK:
+ if (c->mode == M_E1 || c->mode == M_G703)
+ return EINVAL;
+ *(int*)data = ct_get_invrxc (c);
+ return 0;
+
+ case SERIAL_SETINVCLK:
+ case SERIAL_SETINVTCLK:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if (c->mode == M_E1 || c->mode == M_G703)
+ return EINVAL;
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_invtxc (c, *(int*)data);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_SETINVRCLK:
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if (c->mode == M_E1 || c->mode == M_G703)
+ return EINVAL;
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_invrxc (c, *(int*)data);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETLEVEL:
+ if (c->mode != M_G703)
+ return EINVAL;
+ s = splimp ();
+ CT_LOCK (bd);
+ *(int*)data = ct_get_lq (c);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case TIOCSDTR: /* Set DTR */
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_dtr (c, 1);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case TIOCCDTR: /* Clear DTR */
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_dtr (c, 0);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case TIOCMSET: /* Set DTR/RTS */
+ s = splimp ();
+ CT_LOCK (bd);
+ ct_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0);
+ ct_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case TIOCMBIS: /* Add DTR/RTS */
+ s = splimp ();
+ CT_LOCK (bd);
+ if (*(int*)data & TIOCM_DTR) ct_set_dtr (c, 1);
+ if (*(int*)data & TIOCM_RTS) ct_set_rts (c, 1);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case TIOCMBIC: /* Clear DTR/RTS */
+ s = splimp ();
+ CT_LOCK (bd);
+ if (*(int*)data & TIOCM_DTR) ct_set_dtr (c, 0);
+ if (*(int*)data & TIOCM_RTS) ct_set_rts (c, 0);
+ CT_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case TIOCMGET: /* Get modem status */
+ *(int*)data = ct_modem_status (c);
+ return 0;
+ }
+ return ENOTTY;
+}
+
#ifdef NETGRAPH
static int ng_ct_constructor (node_p node)
{
diff --git a/sys/dev/cx/if_cx.c b/sys/dev/cx/if_cx.c
index bdc15ad..8cf2912 100644
--- a/sys/dev/cx/if_cx.c
+++ b/sys/dev/cx/if_cx.c
@@ -230,452 +230,9 @@ static drv_t *channel [NCX*NCHAN];
static struct callout led_timo [NCX];
static struct callout timeout_handle;
-static int MY_SOFT_INTR;
-
-static int cx_open (struct cdev *dev, int flag, int mode, struct thread *td)
-{
- int unit;
- drv_t *d;
-
- d = dev->si_drv1;
- unit = d->chan->num;
-
- CX_DEBUG2 (d, ("cx_open unit=%d, flag=0x%x, mode=0x%x\n",
- unit, flag, mode));
-
- d->open_dev |= 0x1;
-
- CX_DEBUG2 (d, ("cx_open done\n"));
-
- return 0;
-}
-
-static int cx_close (struct cdev *dev, int flag, int mode, struct thread *td)
-{
- drv_t *d;
-
- d = dev->si_drv1;
- CX_DEBUG2 (d, ("cx_close\n"));
- d->open_dev &= ~0x1;
- return 0;
-}
-
-static int cx_modem_status (drv_t *d)
-{
- bdrv_t *bd = d->board->sys;
- int status = 0, s = splhigh ();
- CX_LOCK (bd);
- /* Already opened by someone or network interface is up? */
- if ((d->chan->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) &&
- (d->open_dev|0x2)) || (d->chan->mode != M_ASYNC && d->running))
- status = TIOCM_LE; /* always enabled while open */
-
- if (cx_get_dsr (d->chan)) status |= TIOCM_DSR;
- if (cx_get_cd (d->chan)) status |= TIOCM_CD;
- if (cx_get_cts (d->chan)) status |= TIOCM_CTS;
- if (d->chan->dtr) status |= TIOCM_DTR;
- if (d->chan->rts) status |= TIOCM_RTS;
- CX_UNLOCK (bd);
- splx (s);
- return status;
-}
-
-static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
-{
- drv_t *d;
- bdrv_t *bd;
- cx_chan_t *c;
- struct serial_statistics *st;
- int error, s;
- char mask[16];
-
- d = dev->si_drv1;
- c = d->chan;
-
- bd = d->board->sys;
-
- switch (cmd) {
- case SERIAL_GETREGISTERED:
- CX_DEBUG2 (d, ("ioctl: getregistered\n"));
- bzero (mask, sizeof(mask));
- for (s=0; s<NCX*NCHAN; ++s)
- if (channel [s])
- mask [s/8] |= 1 << (s & 7);
- bcopy (mask, data, sizeof (mask));
- return 0;
-
- case SERIAL_GETPORT:
- CX_DEBUG2 (d, ("ioctl: getport\n"));
- s = splhigh ();
- CX_LOCK (bd);
- *(int *)data = cx_get_port (c);
- CX_UNLOCK (bd);
- splx (s);
- if (*(int *)data<0)
- return (EINVAL);
- else
- return 0;
-
- case SERIAL_SETPORT:
- CX_DEBUG2 (d, ("ioctl: setproto\n"));
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
-
- s = splhigh ();
- CX_LOCK (bd);
- cx_set_port (c, *(int *)data);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
-#ifndef NETGRAPH
- case SERIAL_GETPROTO:
- CX_DEBUG2 (d, ("ioctl: getproto\n"));
- s = splhigh ();
- CX_LOCK (bd);
- strcpy ((char*)data, (c->mode == M_ASYNC) ? "async" :
- (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" :
- (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp");
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_SETPROTO:
- CX_DEBUG2 (d, ("ioctl: setproto\n"));
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if (c->mode == M_ASYNC)
- return EBUSY;
- if (d->ifp->if_drv_flags & IFF_DRV_RUNNING)
- return EBUSY;
- if (! strcmp ("cisco", (char*)data)) {
- IFP2SP(d->ifp)->pp_flags &= ~(PP_FR);
- IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE;
- d->ifp->if_flags |= PP_CISCO;
- } else if (! strcmp ("fr", (char*)data)) {
- d->ifp->if_flags &= ~(PP_CISCO);
- IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE;
- } else if (! strcmp ("ppp", (char*)data)) {
- IFP2SP(d->ifp)->pp_flags &= ~(PP_FR | PP_KEEPALIVE);
- d->ifp->if_flags &= ~(PP_CISCO);
- } else
- return EINVAL;
- return 0;
-
- case SERIAL_GETKEEPALIVE:
- CX_DEBUG2 (d, ("ioctl: getkeepalive\n"));
- if ((IFP2SP(d->ifp)->pp_flags & PP_FR) ||
- (d->ifp->if_flags & PP_CISCO) ||
- (c->mode == M_ASYNC))
- return EINVAL;
- s = splhigh ();
- CX_LOCK (bd);
- *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0;
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_SETKEEPALIVE:
- CX_DEBUG2 (d, ("ioctl: setkeepalive\n"));
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if ((IFP2SP(d->ifp)->pp_flags & PP_FR) ||
- (d->ifp->if_flags & PP_CISCO))
- return EINVAL;
- s = splhigh ();
- CX_LOCK (bd);
- if (*(int*)data)
- IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE;
- else
- IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE;
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-#endif /*NETGRAPH*/
-
- case SERIAL_GETMODE:
- CX_DEBUG2 (d, ("ioctl: getmode\n"));
- s = splhigh ();
- CX_LOCK (bd);
- *(int*)data = (c->mode == M_ASYNC) ?
- SERIAL_ASYNC : SERIAL_HDLC;
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_SETMODE:
- CX_DEBUG2 (d, ("ioctl: setmode\n"));
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
-
- /* Somebody is waiting for carrier? */
- if (d->lock)
- return EBUSY;
- /* /dev/ttyXX is already opened by someone? */
- if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) &&
- (d->open_dev|0x2))
- return EBUSY;
- /* Network interface is up?
- * Cannot change to async mode. */
- if (c->mode != M_ASYNC && d->running &&
- (*(int*)data == SERIAL_ASYNC))
- return EBUSY;
-
- s = splhigh ();
- CX_LOCK (bd);
- if (c->mode == M_HDLC && *(int*)data == SERIAL_ASYNC) {
- cx_set_mode (c, M_ASYNC);
- cx_enable_receive (c, 0);
- cx_enable_transmit (c, 0);
- } else if (c->mode == M_ASYNC && *(int*)data == SERIAL_HDLC) {
- cx_set_mode (c, M_HDLC);
- cx_enable_receive (c, 1);
- cx_enable_transmit (c, 1);
- }
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETSTAT:
- CX_DEBUG2 (d, ("ioctl: getestat\n"));
- st = (struct serial_statistics*) data;
- s = splhigh ();
- CX_LOCK (bd);
- st->rintr = c->rintr;
- st->tintr = c->tintr;
- st->mintr = c->mintr;
- st->ibytes = c->ibytes;
- st->ipkts = c->ipkts;
- st->ierrs = c->ierrs;
- st->obytes = c->obytes;
- st->opkts = c->opkts;
- st->oerrs = c->oerrs;
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_CLRSTAT:
- CX_DEBUG2 (d, ("ioctl: clrstat\n"));
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- s = splhigh ();
- CX_LOCK (bd);
- c->rintr = 0;
- c->tintr = 0;
- c->mintr = 0;
- c->ibytes = 0;
- c->ipkts = 0;
- c->ierrs = 0;
- c->obytes = 0;
- c->opkts = 0;
- c->oerrs = 0;
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETBAUD:
- CX_DEBUG2 (d, ("ioctl: getbaud\n"));
- if (c->mode == M_ASYNC)
- return EINVAL;
- s = splhigh ();
- CX_LOCK (bd);
- *(long*)data = cx_get_baud(c);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_SETBAUD:
- CX_DEBUG2 (d, ("ioctl: setbaud\n"));
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if (c->mode == M_ASYNC)
- return EINVAL;
- s = splhigh ();
- CX_LOCK (bd);
- cx_set_baud (c, *(long*)data);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETLOOP:
- CX_DEBUG2 (d, ("ioctl: getloop\n"));
- if (c->mode == M_ASYNC)
- return EINVAL;
- s = splhigh ();
- CX_LOCK (bd);
- *(int*)data = cx_get_loop (c);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_SETLOOP:
- CX_DEBUG2 (d, ("ioctl: setloop\n"));
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if (c->mode == M_ASYNC)
- return EINVAL;
- s = splhigh ();
- CX_LOCK (bd);
- cx_set_loop (c, *(int*)data);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETDPLL:
- CX_DEBUG2 (d, ("ioctl: getdpll\n"));
- if (c->mode == M_ASYNC)
- return EINVAL;
- s = splhigh ();
- CX_LOCK (bd);
- *(int*)data = cx_get_dpll (c);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_SETDPLL:
- CX_DEBUG2 (d, ("ioctl: setdpll\n"));
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if (c->mode == M_ASYNC)
- return EINVAL;
- s = splhigh ();
- CX_LOCK (bd);
- cx_set_dpll (c, *(int*)data);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETNRZI:
- CX_DEBUG2 (d, ("ioctl: getnrzi\n"));
- if (c->mode == M_ASYNC)
- return EINVAL;
- s = splhigh ();
- CX_LOCK (bd);
- *(int*)data = cx_get_nrzi (c);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_SETNRZI:
- CX_DEBUG2 (d, ("ioctl: setnrzi\n"));
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- if (c->mode == M_ASYNC)
- return EINVAL;
- s = splhigh ();
- CX_LOCK (bd);
- cx_set_nrzi (c, *(int*)data);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_GETDEBUG:
- CX_DEBUG2 (d, ("ioctl: getdebug\n"));
- s = splhigh ();
- CX_LOCK (bd);
- *(int*)data = c->debug;
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case SERIAL_SETDEBUG:
- CX_DEBUG2 (d, ("ioctl: setdebug\n"));
- /* Only for superuser! */
- error = suser (td);
- if (error)
- return error;
- s = splhigh ();
- CX_LOCK (bd);
- c->debug = *(int*)data;
- CX_UNLOCK (bd);
- splx (s);
-#ifndef NETGRAPH
- if (d->chan->debug)
- d->ifp->if_flags |= IFF_DEBUG;
- else
- d->ifp->if_flags &= (~IFF_DEBUG);
-#endif
- return 0;
- }
-
- switch (cmd) {
- case TIOCSDTR: /* Set DTR */
- CX_DEBUG2 (d, ("ioctl: tiocsdtr\n"));
- s = splhigh ();
- CX_LOCK (bd);
- cx_set_dtr (c, 1);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case TIOCCDTR: /* Clear DTR */
- CX_DEBUG2 (d, ("ioctl: tioccdtr\n"));
- s = splhigh ();
- CX_LOCK (bd);
- cx_set_dtr (c, 0);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case TIOCMSET: /* Set DTR/RTS */
- CX_DEBUG2 (d, ("ioctl: tiocmset\n"));
- s = splhigh ();
- CX_LOCK (bd);
- cx_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0);
- cx_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case TIOCMBIS: /* Add DTR/RTS */
- CX_DEBUG2 (d, ("ioctl: tiocmbis\n"));
- s = splhigh ();
- CX_LOCK (bd);
- if (*(int*)data & TIOCM_DTR) cx_set_dtr (c, 1);
- if (*(int*)data & TIOCM_RTS) cx_set_rts (c, 1);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case TIOCMBIC: /* Clear DTR/RTS */
- CX_DEBUG2 (d, ("ioctl: tiocmbic\n"));
- s = splhigh ();
- CX_LOCK (bd);
- if (*(int*)data & TIOCM_DTR) cx_set_dtr (c, 0);
- if (*(int*)data & TIOCM_RTS) cx_set_rts (c, 0);
- CX_UNLOCK (bd);
- splx (s);
- return 0;
-
- case TIOCMGET: /* Get modem status */
- CX_DEBUG2 (d, ("ioctl: tiocmget\n"));
- *(int*)data = cx_modem_status (d);
- return 0;
-
- }
-
- CX_DEBUG2 (d, ("ioctl: 0x%lx\n", cmd));
- return ENOTTY;
-}
-
+static int cx_open (struct cdev *dev, int flag, int mode, struct thread *td);
+static int cx_close (struct cdev *dev, int flag, int mode, struct thread *td);
+static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td);
static struct cdevsw cx_cdevsw = {
.d_version = D_VERSION,
.d_open = cx_open,
@@ -685,6 +242,8 @@ static struct cdevsw cx_cdevsw = {
.d_flags = D_TTY | D_NEEDGIANT,
};
+static int MY_SOFT_INTR;
+
/*
* Print the mbuf chain, for debug purposes only.
*/
@@ -1988,6 +1547,450 @@ static int cx_tmodem (struct tty *tp, int sigon, int sigoff)
return (0);
}
+static int cx_open (struct cdev *dev, int flag, int mode, struct thread *td)
+{
+ int unit;
+ drv_t *d;
+
+ d = dev->si_drv1;
+ unit = d->chan->num;
+
+ CX_DEBUG2 (d, ("cx_open unit=%d, flag=0x%x, mode=0x%x\n",
+ unit, flag, mode));
+
+ d->open_dev |= 0x1;
+
+ CX_DEBUG2 (d, ("cx_open done\n"));
+
+ return 0;
+}
+
+static int cx_close (struct cdev *dev, int flag, int mode, struct thread *td)
+{
+ drv_t *d;
+
+ d = dev->si_drv1;
+ CX_DEBUG2 (d, ("cx_close\n"));
+ d->open_dev &= ~0x1;
+ return 0;
+}
+
+static int cx_modem_status (drv_t *d)
+{
+ bdrv_t *bd = d->board->sys;
+ int status = 0, s = splhigh ();
+ CX_LOCK (bd);
+ /* Already opened by someone or network interface is up? */
+ if ((d->chan->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) &&
+ (d->open_dev|0x2)) || (d->chan->mode != M_ASYNC && d->running))
+ status = TIOCM_LE; /* always enabled while open */
+
+ if (cx_get_dsr (d->chan)) status |= TIOCM_DSR;
+ if (cx_get_cd (d->chan)) status |= TIOCM_CD;
+ if (cx_get_cts (d->chan)) status |= TIOCM_CTS;
+ if (d->chan->dtr) status |= TIOCM_DTR;
+ if (d->chan->rts) status |= TIOCM_RTS;
+ CX_UNLOCK (bd);
+ splx (s);
+ return status;
+}
+
+static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
+{
+ drv_t *d;
+ bdrv_t *bd;
+ cx_chan_t *c;
+ struct serial_statistics *st;
+ int error, s;
+ char mask[16];
+
+ d = dev->si_drv1;
+ c = d->chan;
+
+ bd = d->board->sys;
+
+ switch (cmd) {
+ case SERIAL_GETREGISTERED:
+ CX_DEBUG2 (d, ("ioctl: getregistered\n"));
+ bzero (mask, sizeof(mask));
+ for (s=0; s<NCX*NCHAN; ++s)
+ if (channel [s])
+ mask [s/8] |= 1 << (s & 7);
+ bcopy (mask, data, sizeof (mask));
+ return 0;
+
+ case SERIAL_GETPORT:
+ CX_DEBUG2 (d, ("ioctl: getport\n"));
+ s = splhigh ();
+ CX_LOCK (bd);
+ *(int *)data = cx_get_port (c);
+ CX_UNLOCK (bd);
+ splx (s);
+ if (*(int *)data<0)
+ return (EINVAL);
+ else
+ return 0;
+
+ case SERIAL_SETPORT:
+ CX_DEBUG2 (d, ("ioctl: setproto\n"));
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+
+ s = splhigh ();
+ CX_LOCK (bd);
+ cx_set_port (c, *(int *)data);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+#ifndef NETGRAPH
+ case SERIAL_GETPROTO:
+ CX_DEBUG2 (d, ("ioctl: getproto\n"));
+ s = splhigh ();
+ CX_LOCK (bd);
+ strcpy ((char*)data, (c->mode == M_ASYNC) ? "async" :
+ (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" :
+ (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp");
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_SETPROTO:
+ CX_DEBUG2 (d, ("ioctl: setproto\n"));
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if (c->mode == M_ASYNC)
+ return EBUSY;
+ if (d->ifp->if_drv_flags & IFF_DRV_RUNNING)
+ return EBUSY;
+ if (! strcmp ("cisco", (char*)data)) {
+ IFP2SP(d->ifp)->pp_flags &= ~(PP_FR);
+ IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE;
+ d->ifp->if_flags |= PP_CISCO;
+ } else if (! strcmp ("fr", (char*)data)) {
+ d->ifp->if_flags &= ~(PP_CISCO);
+ IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE;
+ } else if (! strcmp ("ppp", (char*)data)) {
+ IFP2SP(d->ifp)->pp_flags &= ~(PP_FR | PP_KEEPALIVE);
+ d->ifp->if_flags &= ~(PP_CISCO);
+ } else
+ return EINVAL;
+ return 0;
+
+ case SERIAL_GETKEEPALIVE:
+ CX_DEBUG2 (d, ("ioctl: getkeepalive\n"));
+ if ((IFP2SP(d->ifp)->pp_flags & PP_FR) ||
+ (d->ifp->if_flags & PP_CISCO) ||
+ (c->mode == M_ASYNC))
+ return EINVAL;
+ s = splhigh ();
+ CX_LOCK (bd);
+ *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0;
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_SETKEEPALIVE:
+ CX_DEBUG2 (d, ("ioctl: setkeepalive\n"));
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if ((IFP2SP(d->ifp)->pp_flags & PP_FR) ||
+ (d->ifp->if_flags & PP_CISCO))
+ return EINVAL;
+ s = splhigh ();
+ CX_LOCK (bd);
+ if (*(int*)data)
+ IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE;
+ else
+ IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE;
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+#endif /*NETGRAPH*/
+
+ case SERIAL_GETMODE:
+ CX_DEBUG2 (d, ("ioctl: getmode\n"));
+ s = splhigh ();
+ CX_LOCK (bd);
+ *(int*)data = (c->mode == M_ASYNC) ?
+ SERIAL_ASYNC : SERIAL_HDLC;
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_SETMODE:
+ CX_DEBUG2 (d, ("ioctl: setmode\n"));
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+
+ /* Somebody is waiting for carrier? */
+ if (d->lock)
+ return EBUSY;
+ /* /dev/ttyXX is already opened by someone? */
+ if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) &&
+ (d->open_dev|0x2))
+ return EBUSY;
+ /* Network interface is up?
+ * Cannot change to async mode. */
+ if (c->mode != M_ASYNC && d->running &&
+ (*(int*)data == SERIAL_ASYNC))
+ return EBUSY;
+
+ s = splhigh ();
+ CX_LOCK (bd);
+ if (c->mode == M_HDLC && *(int*)data == SERIAL_ASYNC) {
+ cx_set_mode (c, M_ASYNC);
+ cx_enable_receive (c, 0);
+ cx_enable_transmit (c, 0);
+ } else if (c->mode == M_ASYNC && *(int*)data == SERIAL_HDLC) {
+ cx_set_mode (c, M_HDLC);
+ cx_enable_receive (c, 1);
+ cx_enable_transmit (c, 1);
+ }
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETSTAT:
+ CX_DEBUG2 (d, ("ioctl: getestat\n"));
+ st = (struct serial_statistics*) data;
+ s = splhigh ();
+ CX_LOCK (bd);
+ st->rintr = c->rintr;
+ st->tintr = c->tintr;
+ st->mintr = c->mintr;
+ st->ibytes = c->ibytes;
+ st->ipkts = c->ipkts;
+ st->ierrs = c->ierrs;
+ st->obytes = c->obytes;
+ st->opkts = c->opkts;
+ st->oerrs = c->oerrs;
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_CLRSTAT:
+ CX_DEBUG2 (d, ("ioctl: clrstat\n"));
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ s = splhigh ();
+ CX_LOCK (bd);
+ c->rintr = 0;
+ c->tintr = 0;
+ c->mintr = 0;
+ c->ibytes = 0;
+ c->ipkts = 0;
+ c->ierrs = 0;
+ c->obytes = 0;
+ c->opkts = 0;
+ c->oerrs = 0;
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETBAUD:
+ CX_DEBUG2 (d, ("ioctl: getbaud\n"));
+ if (c->mode == M_ASYNC)
+ return EINVAL;
+ s = splhigh ();
+ CX_LOCK (bd);
+ *(long*)data = cx_get_baud(c);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_SETBAUD:
+ CX_DEBUG2 (d, ("ioctl: setbaud\n"));
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if (c->mode == M_ASYNC)
+ return EINVAL;
+ s = splhigh ();
+ CX_LOCK (bd);
+ cx_set_baud (c, *(long*)data);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETLOOP:
+ CX_DEBUG2 (d, ("ioctl: getloop\n"));
+ if (c->mode == M_ASYNC)
+ return EINVAL;
+ s = splhigh ();
+ CX_LOCK (bd);
+ *(int*)data = cx_get_loop (c);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_SETLOOP:
+ CX_DEBUG2 (d, ("ioctl: setloop\n"));
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if (c->mode == M_ASYNC)
+ return EINVAL;
+ s = splhigh ();
+ CX_LOCK (bd);
+ cx_set_loop (c, *(int*)data);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETDPLL:
+ CX_DEBUG2 (d, ("ioctl: getdpll\n"));
+ if (c->mode == M_ASYNC)
+ return EINVAL;
+ s = splhigh ();
+ CX_LOCK (bd);
+ *(int*)data = cx_get_dpll (c);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_SETDPLL:
+ CX_DEBUG2 (d, ("ioctl: setdpll\n"));
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if (c->mode == M_ASYNC)
+ return EINVAL;
+ s = splhigh ();
+ CX_LOCK (bd);
+ cx_set_dpll (c, *(int*)data);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETNRZI:
+ CX_DEBUG2 (d, ("ioctl: getnrzi\n"));
+ if (c->mode == M_ASYNC)
+ return EINVAL;
+ s = splhigh ();
+ CX_LOCK (bd);
+ *(int*)data = cx_get_nrzi (c);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_SETNRZI:
+ CX_DEBUG2 (d, ("ioctl: setnrzi\n"));
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ if (c->mode == M_ASYNC)
+ return EINVAL;
+ s = splhigh ();
+ CX_LOCK (bd);
+ cx_set_nrzi (c, *(int*)data);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_GETDEBUG:
+ CX_DEBUG2 (d, ("ioctl: getdebug\n"));
+ s = splhigh ();
+ CX_LOCK (bd);
+ *(int*)data = c->debug;
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case SERIAL_SETDEBUG:
+ CX_DEBUG2 (d, ("ioctl: setdebug\n"));
+ /* Only for superuser! */
+ error = suser (td);
+ if (error)
+ return error;
+ s = splhigh ();
+ CX_LOCK (bd);
+ c->debug = *(int*)data;
+ CX_UNLOCK (bd);
+ splx (s);
+#ifndef NETGRAPH
+ if (d->chan->debug)
+ d->ifp->if_flags |= IFF_DEBUG;
+ else
+ d->ifp->if_flags &= (~IFF_DEBUG);
+#endif
+ return 0;
+ }
+
+ switch (cmd) {
+ case TIOCSDTR: /* Set DTR */
+ CX_DEBUG2 (d, ("ioctl: tiocsdtr\n"));
+ s = splhigh ();
+ CX_LOCK (bd);
+ cx_set_dtr (c, 1);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case TIOCCDTR: /* Clear DTR */
+ CX_DEBUG2 (d, ("ioctl: tioccdtr\n"));
+ s = splhigh ();
+ CX_LOCK (bd);
+ cx_set_dtr (c, 0);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case TIOCMSET: /* Set DTR/RTS */
+ CX_DEBUG2 (d, ("ioctl: tiocmset\n"));
+ s = splhigh ();
+ CX_LOCK (bd);
+ cx_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0);
+ cx_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case TIOCMBIS: /* Add DTR/RTS */
+ CX_DEBUG2 (d, ("ioctl: tiocmbis\n"));
+ s = splhigh ();
+ CX_LOCK (bd);
+ if (*(int*)data & TIOCM_DTR) cx_set_dtr (c, 1);
+ if (*(int*)data & TIOCM_RTS) cx_set_rts (c, 1);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case TIOCMBIC: /* Clear DTR/RTS */
+ CX_DEBUG2 (d, ("ioctl: tiocmbic\n"));
+ s = splhigh ();
+ CX_LOCK (bd);
+ if (*(int*)data & TIOCM_DTR) cx_set_dtr (c, 0);
+ if (*(int*)data & TIOCM_RTS) cx_set_rts (c, 0);
+ CX_UNLOCK (bd);
+ splx (s);
+ return 0;
+
+ case TIOCMGET: /* Get modem status */
+ CX_DEBUG2 (d, ("ioctl: tiocmget\n"));
+ *(int*)data = cx_modem_status (d);
+ return 0;
+
+ }
+
+ CX_DEBUG2 (d, ("ioctl: 0x%lx\n", cmd));
+ return ENOTTY;
+}
+
void cx_softintr (void *unused)
{
drv_t *d;
OpenPOWER on IntegriCloud