1139749Simp/*- 2126177Srik * Cronyx-Tau adapter driver for FreeBSD. 3126177Srik * Supports PPP/HDLC and Cisco/HDLC protocol in synchronous mode, 4250460Seadler * and asynchronous channels with full modem control. 5126177Srik * Keepalive protocol implemented in both Cisco and PPP modes. 6126177Srik * 7126177Srik * Copyright (C) 1994-2002 Cronyx Engineering. 8126177Srik * Author: Serge Vakulenko, <vak@cronyx.ru> 9126177Srik * 10126177Srik * Copyright (C) 1999-2004 Cronyx Engineering. 11126177Srik * Author: Roman Kurakin, <rik@cronyx.ru> 12126177Srik * 13126177Srik * This software is distributed with NO WARRANTIES, not even the implied 14126177Srik * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15126177Srik * 16126177Srik * Authors grant any other persons or organisations a permission to use, 17126177Srik * modify and redistribute this software in source and binary forms, 18126177Srik * as long as this message is kept with the software, all derivative 19126177Srik * works or modified versions. 20126177Srik * 21130985Srik * Cronyx Id: if_ct.c,v 1.1.2.31 2004/06/23 17:09:13 rik Exp $ 22126177Srik */ 23130985Srik 24126177Srik#include <sys/cdefs.h> 25126177Srik__FBSDID("$FreeBSD$"); 26126177Srik 27126177Srik#include <sys/param.h> 28126177Srik#include <sys/proc.h> 29126177Srik#include <sys/systm.h> 30126177Srik#include <sys/kernel.h> 31129879Sphk#include <sys/module.h> 32126177Srik#include <sys/mbuf.h> 33126177Srik#include <sys/sockio.h> 34126177Srik#include <sys/malloc.h> 35164033Srwatson#include <sys/priv.h> 36126177Srik#include <sys/socket.h> 37138823Srik#include <sys/sysctl.h> 38126177Srik#include <sys/conf.h> 39126177Srik#include <sys/errno.h> 40126177Srik#include <sys/tty.h> 41130971Srik#include <sys/bus.h> 42130971Srik#include <machine/bus.h> 43130971Srik#include <sys/rman.h> 44130971Srik#include <isa/isavar.h> 45126177Srik#include <sys/interrupt.h> 46126177Srik#include <vm/vm.h> 47126177Srik#include <vm/pmap.h> 48126177Srik#include <net/if.h> 49126177Srik#include <machine/cpufunc.h> 50126177Srik#include <machine/cserial.h> 51126177Srik#include <machine/resource.h> 52126177Srik#include <dev/cx/machdep.h> 53126177Srik#include <dev/ctau/ctddk.h> 54126177Srik#include <dev/cx/cronyxfw.h> 55126177Srik#include "opt_ng_cronyx.h" 56126177Srik#ifdef NETGRAPH_CRONYX 57126177Srik# include "opt_netgraph.h" 58126177Srik# include <netgraph/ng_message.h> 59126177Srik# include <netgraph/netgraph.h> 60126177Srik# include <dev/ctau/ng_ct.h> 61126177Srik#else 62126177Srik# include <net/if_types.h> 63126177Srik# include <net/if_sppp.h> 64126177Srik# define PP_CISCO IFF_LINK2 65126177Srik# include <net/bpf.h> 66126177Srik#endif 67138651Srik 68138651Srik#define NCTAU 1 69126177Srik 70129031Srik/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 71129031Srik#ifndef PP_FR 72129031Srik#define PP_FR 0 73129031Srik#endif 74129031Srik 75126177Srik#define CT_DEBUG(d,s) ({if (d->chan->debug) {\ 76126177Srik printf ("%s: ", d->name); printf s;}}) 77126177Srik#define CT_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 78126177Srik printf ("%s: ", d->name); printf s;}}) 79138823Srik 80138823Srik#define CT_LOCK_NAME "ctX" 81138823Srik 82188662Srwatson#define CT_LOCK(_bd) mtx_lock (&(_bd)->ct_mtx) 83188662Srwatson#define CT_UNLOCK(_bd) mtx_unlock (&(_bd)->ct_mtx) 84188662Srwatson#define CT_LOCK_ASSERT(_bd) mtx_assert (&(_bd)->ct_mtx, MA_OWNED) 85138823Srik 86126177Srikstatic void ct_identify __P((driver_t *, device_t)); 87126177Srikstatic int ct_probe __P((device_t)); 88126177Srikstatic int ct_attach __P((device_t)); 89126177Srikstatic int ct_detach __P((device_t)); 90126177Srik 91126177Srikstatic device_method_t ct_isa_methods [] = { 92126177Srik DEVMETHOD(device_identify, ct_identify), 93126177Srik DEVMETHOD(device_probe, ct_probe), 94126177Srik DEVMETHOD(device_attach, ct_attach), 95126177Srik DEVMETHOD(device_detach, ct_detach), 96246128Ssbz 97246128Ssbz DEVMETHOD_END 98126177Srik}; 99126177Srik 100130985Sriktypedef struct _ct_dma_mem_t { 101130985Srik unsigned long phys; 102130985Srik void *virt; 103130985Srik size_t size; 104130985Srik bus_dma_tag_t dmat; 105130985Srik bus_dmamap_t mapp; 106130985Srik} ct_dma_mem_t; 107126177Srik 108126177Sriktypedef struct _drv_t { 109126177Srik char name [8]; 110126177Srik ct_chan_t *chan; 111126177Srik ct_board_t *board; 112138823Srik struct _bdrv_t *bd; 113130985Srik ct_dma_mem_t dmamem; 114126177Srik int running; 115126177Srik#ifdef NETGRAPH 116193813Simp char nodename [NG_NODESIZ]; 117126177Srik hook_p hook; 118126177Srik hook_p debug_hook; 119126177Srik node_p node; 120126177Srik struct ifqueue queue; 121126177Srik struct ifqueue hi_queue; 122126177Srik#else 123138823Srik struct ifqueue queue; 124147256Sbrooks struct ifnet *ifp; 125126177Srik#endif 126199407Sjhb short timeout; 127199407Sjhb struct callout timeout_handle; 128138823Srik struct cdev *devt; 129126177Srik} drv_t; 130126177Srik 131130985Sriktypedef struct _bdrv_t { 132130985Srik ct_board_t *board; 133130985Srik struct resource *base_res; 134130985Srik struct resource *drq_res; 135130985Srik struct resource *irq_res; 136130985Srik int base_rid; 137130985Srik int drq_rid; 138130985Srik int irq_rid; 139130985Srik void *intrhand; 140130985Srik drv_t channel [NCHAN]; 141138823Srik struct mtx ct_mtx; 142130985Srik} bdrv_t; 143130985Srik 144130985Srikstatic driver_t ct_isa_driver = { 145130985Srik "ct", 146130985Srik ct_isa_methods, 147130985Srik sizeof (bdrv_t), 148130985Srik}; 149130985Srik 150130985Srikstatic devclass_t ct_devclass; 151130985Srik 152126177Srikstatic void ct_receive (ct_chan_t *c, char *data, int len); 153126177Srikstatic void ct_transmit (ct_chan_t *c, void *attachment, int len); 154126177Srikstatic void ct_error (ct_chan_t *c, int data); 155126177Srikstatic void ct_up (drv_t *d); 156126177Srikstatic void ct_start (drv_t *d); 157126177Srikstatic void ct_down (drv_t *d); 158126177Srikstatic void ct_watchdog (drv_t *d); 159199407Sjhbstatic void ct_watchdog_timer (void *arg); 160126177Srik#ifdef NETGRAPH 161126177Srikextern struct ng_type typestruct; 162126177Srik#else 163126177Srikstatic void ct_ifstart (struct ifnet *ifp); 164126177Srikstatic void ct_tlf (struct sppp *sp); 165126177Srikstatic void ct_tls (struct sppp *sp); 166126177Srikstatic int ct_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 167126177Srikstatic void ct_initialize (void *softc); 168126177Srik#endif 169126177Srik 170126491Srikstatic ct_board_t *adapter [NCTAU]; 171126491Srikstatic drv_t *channel [NCTAU*NCHAN]; 172138823Srikstatic struct callout led_timo [NCTAU]; 173138823Srikstatic struct callout timeout_handle; 174126177Srik 175150622Srikstatic int ct_open (struct cdev *dev, int oflags, int devtype, struct thread *td); 176150622Srikstatic int ct_close (struct cdev *dev, int fflag, int devtype, struct thread *td); 177150622Srikstatic int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td); 178149847Sobrienstatic struct cdevsw ct_cdevsw = { 179149847Sobrien .d_version = D_VERSION, 180149847Sobrien .d_open = ct_open, 181149847Sobrien .d_close = ct_close, 182149847Sobrien .d_ioctl = ct_ioctl, 183149847Sobrien .d_name = "ct", 184149847Sobrien}; 185149847Sobrien 186149847Sobrien/* 187126177Srik * Print the mbuf chain, for debug purposes only. 188126177Srik */ 189126177Srikstatic void printmbuf (struct mbuf *m) 190126177Srik{ 191126177Srik printf ("mbuf:"); 192126177Srik for (; m; m=m->m_next) { 193126177Srik if (m->m_flags & M_PKTHDR) 194126177Srik printf (" HDR %d:", m->m_pkthdr.len); 195126177Srik if (m->m_flags & M_EXT) 196126177Srik printf (" EXT:"); 197126177Srik printf (" %d", m->m_len); 198126177Srik } 199126177Srik printf ("\n"); 200126177Srik} 201126177Srik 202126177Srik/* 203126177Srik * Make an mbuf from data. 204126177Srik */ 205126177Srikstatic struct mbuf *makembuf (void *buf, u_int len) 206126177Srik{ 207126177Srik struct mbuf *m; 208126177Srik 209243857Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 210126177Srik if (! m) 211126177Srik return 0; 212243857Sglebius MCLGET (m, M_NOWAIT); 213126177Srik if (! (m->m_flags & M_EXT)) { 214126177Srik m_freem (m); 215126177Srik return 0; 216126177Srik } 217126177Srik m->m_pkthdr.len = m->m_len = len; 218126177Srik bcopy (buf, mtod (m, caddr_t), len); 219126177Srik return m; 220126177Srik} 221126177Srik 222126177Srikstatic void ct_timeout (void *arg) 223126177Srik{ 224126177Srik drv_t *d; 225138823Srik int s, i, k; 226126177Srik 227138823Srik for (i = 0; i < NCTAU; ++i) { 228138823Srik if (adapter[i] == NULL) 229126177Srik continue; 230138823Srik for (k = 0; k < NCHAN; k++) { 231138823Srik d = channel[i * NCHAN + k]; 232138823Srik if (! d) 233138823Srik continue; 234138823Srik if (d->chan->mode != M_G703) 235138823Srik continue; 236138823Srik s = splimp (); 237138823Srik CT_LOCK ((bdrv_t *)d->bd); 238138823Srik ct_g703_timer (d->chan); 239138823Srik CT_UNLOCK ((bdrv_t *)d->bd); 240138823Srik splx (s); 241138823Srik } 242126177Srik } 243138823Srik 244138823Srik callout_reset (&timeout_handle, hz, ct_timeout, 0); 245126177Srik} 246126177Srik 247126177Srikstatic void ct_led_off (void *arg) 248126177Srik{ 249126177Srik ct_board_t *b = arg; 250138823Srik bdrv_t *bd = ((drv_t *)b->chan->sys)->bd; 251126177Srik int s = splimp (); 252126177Srik 253138823Srik CT_LOCK (bd); 254126177Srik ct_led (b, 0); 255138823Srik CT_UNLOCK (bd); 256126177Srik splx (s); 257126177Srik} 258126177Srik 259126177Srik/* 260172568Skevlo * Activate interrupt handler from DDK. 261126177Srik */ 262126177Srikstatic void ct_intr (void *arg) 263126177Srik{ 264126177Srik bdrv_t *bd = arg; 265126177Srik ct_board_t *b = bd->board; 266138823Srik#ifndef NETGRAPH 267138823Srik int i; 268138823Srik#endif 269126177Srik int s = splimp (); 270126177Srik 271138823Srik CT_LOCK (bd); 272126177Srik /* Turn LED on. */ 273126177Srik ct_led (b, 1); 274126177Srik 275126177Srik ct_int_handler (b); 276126177Srik 277126177Srik /* Turn LED off 50 msec later. */ 278138823Srik callout_reset (&led_timo[b->num], hz/20, ct_led_off, b); 279138823Srik CT_UNLOCK (bd); 280126177Srik splx (s); 281138823Srik 282138823Srik#ifndef NETGRAPH 283138823Srik /* Pass packets in a lock-free state */ 284138823Srik for (i = 0; i < NCHAN && b->chan[i].type; i++) { 285138823Srik drv_t *d = b->chan[i].sys; 286138823Srik struct mbuf *m; 287147858Srik if (!d || !d->running) 288147858Srik continue; 289138823Srik while (_IF_QLEN(&d->queue)) { 290138823Srik IF_DEQUEUE (&d->queue,m); 291138823Srik if (!m) 292138823Srik continue; 293147256Sbrooks sppp_input (d->ifp, m); 294138823Srik } 295138823Srik } 296138823Srik#endif 297126177Srik} 298126177Srik 299126177Srikstatic int probe_irq (ct_board_t *b, int irq) 300126177Srik{ 301126177Srik int mask, busy, cnt; 302126177Srik 303126177Srik /* Clear pending irq, if any. */ 304126177Srik ct_probe_irq (b, -irq); 305126177Srik DELAY (100); 306126177Srik for (cnt=0; cnt<5; ++cnt) { 307126177Srik /* Get the mask of pending irqs, assuming they are busy. 308126177Srik * Activate the adapter on given irq. */ 309126177Srik busy = ct_probe_irq (b, irq); 310126177Srik DELAY (1000); 311126177Srik 312126177Srik /* Get the mask of active irqs. 313126177Srik * Deactivate our irq. */ 314126177Srik mask = ct_probe_irq (b, -irq); 315126177Srik DELAY (100); 316126177Srik if ((mask & ~busy) == 1 << irq) { 317126177Srik ct_probe_irq (b, 0); 318126177Srik /* printf ("ct%d: irq %d ok, mask=0x%04x, busy=0x%04x\n", 319126177Srik b->num, irq, mask, busy); */ 320126177Srik return 1; 321126177Srik } 322126177Srik } 323126491Srik /* printf ("ct%d: irq %d not functional, mask=0x%04x, busy=0x%04x\n", 324126177Srik b->num, irq, mask, busy); */ 325126177Srik ct_probe_irq (b, 0); 326126177Srik return 0; 327126177Srik} 328126177Srik 329126177Srikstatic short porttab [] = { 330126177Srik 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 331126177Srik 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 332126177Srik }; 333126177Srikstatic char dmatab [] = { 7, 6, 5, 0 }; 334126177Srikstatic char irqtab [] = { 5, 10, 11, 7, 3, 15, 12, 0 }; 335126177Srik 336126177Srikstatic int ct_is_free_res (device_t dev, int rid, int type, u_long start, 337126177Srik u_long end, u_long count) 338126177Srik{ 339126177Srik struct resource *res; 340126177Srik 341126177Srik if (!(res = bus_alloc_resource (dev, type, &rid, start, end, count, 342126177Srik RF_ALLOCATED))) 343126177Srik return 0; 344126177Srik 345126177Srik bus_release_resource (dev, type, rid, res); 346126177Srik 347126177Srik return 1; 348126177Srik} 349126177Srik 350126177Srikstatic void ct_identify (driver_t *driver, device_t dev) 351126177Srik{ 352126177Srik u_long iobase, rescount; 353126177Srik int devcount; 354126177Srik device_t *devices; 355126177Srik device_t child; 356126177Srik devclass_t my_devclass; 357126177Srik int i, k; 358126177Srik 359126177Srik if ((my_devclass = devclass_find ("ct")) == NULL) 360126177Srik return; 361126177Srik 362126177Srik devclass_get_devices (my_devclass, &devices, &devcount); 363126177Srik 364126177Srik if (devcount == 0) { 365126177Srik /* We should find all devices by our self. We could alter other 366126177Srik * devices, but we don't have a choise 367126177Srik */ 368126177Srik for (i = 0; (iobase = porttab [i]) != 0; i++) { 369133647Srik if (!ct_is_free_res (dev, 0, SYS_RES_IOPORT, 370126177Srik iobase, iobase + NPORT, NPORT)) 371126177Srik continue; 372126177Srik if (ct_probe_board (iobase, -1, -1) == 0) 373126177Srik continue; 374126177Srik 375126177Srik devcount++; 376126177Srik child = BUS_ADD_CHILD (dev, ISA_ORDER_SPECULATIVE, "ct", 377126177Srik -1); 378126177Srik 379126177Srik if (child == NULL) 380126177Srik return; 381126177Srik 382126177Srik device_set_desc_copy (child, "Cronyx Tau-ISA"); 383126177Srik device_set_driver (child, driver); 384126177Srik bus_set_resource (child, SYS_RES_IOPORT, 0, 385126177Srik iobase, NPORT); 386126177Srik 387126491Srik if (devcount >= NCTAU) 388126177Srik break; 389126177Srik } 390126177Srik } else { 391126177Srik static short porttab [] = { 392126177Srik 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 393126177Srik 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 394126177Srik }; 395126177Srik /* Lets check user choise. 396126177Srik */ 397126177Srik for (k = 0; k < devcount; k++) { 398126177Srik if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0, 399126177Srik &iobase, &rescount) != 0) 400126177Srik continue; 401126177Srik 402126177Srik for (i = 0; porttab [i] != 0; i++) { 403126177Srik if (porttab [i] != iobase) 404126177Srik continue; 405126177Srik 406133647Srik if (!ct_is_free_res (devices[k], 0, SYS_RES_IOPORT, 407126177Srik iobase, iobase + NPORT, NPORT)) 408126177Srik continue; 409126177Srik 410126177Srik if (ct_probe_board (iobase, -1, -1) == 0) 411126177Srik continue; 412126177Srik porttab [i] = -1; 413126177Srik device_set_desc_copy (devices[k], "Cronyx Tau-ISA"); 414126177Srik break; 415126177Srik } 416126177Srik if (porttab [i] == 0) { 417126177Srik device_delete_child ( 418126177Srik device_get_parent (devices[k]), 419126177Srik devices [k]); 420126177Srik devices[k] = 0; 421126177Srik continue; 422126177Srik } 423126177Srik } 424126177Srik for (k = 0; k < devcount; k++) { 425126177Srik if (devices[k] == 0) 426126177Srik continue; 427126177Srik if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0, 428126177Srik &iobase, &rescount) == 0) 429126177Srik continue; 430126177Srik for (i = 0; (iobase = porttab [i]) != 0; i++) { 431126177Srik if (porttab [i] == -1) 432126177Srik continue; 433133647Srik if (!ct_is_free_res (devices[k], 0, SYS_RES_IOPORT, 434126177Srik iobase, iobase + NPORT, NPORT)) 435126177Srik continue; 436126177Srik if (ct_probe_board (iobase, -1, -1) == 0) 437126177Srik continue; 438126177Srik 439126177Srik bus_set_resource (devices[k], SYS_RES_IOPORT, 0, 440126177Srik iobase, NPORT); 441126177Srik porttab [i] = -1; 442126177Srik device_set_desc_copy (devices[k], "Cronyx Tau-ISA"); 443126177Srik break; 444126177Srik } 445126177Srik if (porttab [i] == 0) { 446126177Srik device_delete_child ( 447126177Srik device_get_parent (devices[k]), 448126177Srik devices [k]); 449126177Srik } 450126177Srik } 451126177Srik free (devices, M_TEMP); 452126177Srik } 453126177Srik 454126177Srik return; 455126177Srik} 456126177Srik 457126177Srikstatic int ct_probe (device_t dev) 458126177Srik{ 459126177Srik int unit = device_get_unit (dev); 460126177Srik u_long iobase, rescount; 461126177Srik 462126177Srik if (!device_get_desc (dev) || 463126177Srik strcmp (device_get_desc (dev), "Cronyx Tau-ISA")) 464126177Srik return ENXIO; 465126177Srik 466126177Srik/* KASSERT ((bd != NULL), ("ct%d: NULL device softc\n", unit));*/ 467126177Srik if (bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount) != 0) { 468126177Srik printf ("ct%d: Couldn't get IOPORT\n", unit); 469126177Srik return ENXIO; 470126177Srik } 471126177Srik 472133647Srik if (!ct_is_free_res (dev, 0, SYS_RES_IOPORT, 473126177Srik iobase, iobase + NPORT, NPORT)) { 474126177Srik printf ("ct%d: Resource IOPORT isn't free\n", unit); 475126177Srik return ENXIO; 476126177Srik } 477126177Srik 478126177Srik if (!ct_probe_board (iobase, -1, -1)) { 479126177Srik printf ("ct%d: probing for Tau-ISA at %lx faild\n", unit, iobase); 480126177Srik return ENXIO; 481126177Srik } 482126177Srik 483126177Srik return 0; 484126177Srik} 485126177Srik 486130985Srikstatic void 487130985Srikct_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 488130985Srik{ 489130985Srik unsigned long *addr; 490130985Srik 491130985Srik if (error) 492130985Srik return; 493130985Srik 494130985Srik KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 495130985Srik addr = arg; 496130985Srik *addr = segs->ds_addr; 497130985Srik} 498130985Srik 499130985Srikstatic int 500130985Srikct_bus_dma_mem_alloc (int bnum, int cnum, ct_dma_mem_t *dmem) 501130985Srik{ 502130985Srik int error; 503130985Srik 504130985Srik error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_24BIT, 505130985Srik BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 506130985Srik dmem->size, 0, NULL, NULL, &dmem->dmat); 507130985Srik if (error) { 508130985Srik if (cnum >= 0) printf ("ct%d-%d: ", bnum, cnum); 509130985Srik else printf ("ct%d: ", bnum); 510130985Srik printf ("couldn't allocate tag for dma memory\n"); 511130985Srik return 0; 512130985Srik } 513130985Srik error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 514130985Srik BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 515130985Srik if (error) { 516130985Srik if (cnum >= 0) printf ("ct%d-%d: ", bnum, cnum); 517130985Srik else printf ("ct%d: ", bnum); 518130985Srik printf ("couldn't allocate mem for dma memory\n"); 519130985Srik bus_dma_tag_destroy (dmem->dmat); 520130985Srik return 0; 521130985Srik } 522130985Srik error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 523130985Srik dmem->size, ct_bus_dmamap_addr, &dmem->phys, 0); 524130985Srik if (error) { 525130985Srik if (cnum >= 0) printf ("ct%d-%d: ", bnum, cnum); 526130985Srik else printf ("ct%d: ", bnum); 527130985Srik printf ("couldn't load mem map for dma memory\n"); 528130985Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 529130985Srik bus_dma_tag_destroy (dmem->dmat); 530130985Srik return 0; 531130985Srik } 532130985Srik return 1; 533130985Srik} 534130985Srik 535130985Srikstatic void 536130985Srikct_bus_dma_mem_free (ct_dma_mem_t *dmem) 537130985Srik{ 538130985Srik bus_dmamap_unload (dmem->dmat, dmem->mapp); 539130985Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 540130985Srik bus_dma_tag_destroy (dmem->dmat); 541130985Srik} 542130985Srik 543126177Srik/* 544126177Srik * The adapter is present, initialize the driver structures. 545126177Srik */ 546126177Srikstatic int ct_attach (device_t dev) 547126177Srik{ 548126177Srik bdrv_t *bd = device_get_softc (dev); 549126177Srik u_long iobase, drq, irq, rescount; 550126177Srik int unit = device_get_unit (dev); 551138823Srik char *ct_ln = CT_LOCK_NAME; 552126177Srik ct_board_t *b; 553126177Srik ct_chan_t *c; 554126177Srik drv_t *d; 555130971Srik int i; 556130971Srik int s; 557126177Srik 558126177Srik KASSERT ((bd != NULL), ("ct%d: NULL device softc\n", unit)); 559126177Srik 560126177Srik bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount); 561126177Srik bd->base_rid = 0; 562126177Srik bd->base_res = bus_alloc_resource (dev, SYS_RES_IOPORT, &bd->base_rid, 563126177Srik iobase, iobase + NPORT, NPORT, RF_ACTIVE); 564126177Srik if (! bd->base_res) { 565126177Srik printf ("ct%d: cannot alloc base address\n", unit); 566126177Srik return ENXIO; 567126177Srik } 568126177Srik 569126177Srik if (bus_get_resource (dev, SYS_RES_DRQ, 0, &drq, &rescount) != 0) { 570126177Srik for (i = 0; (drq = dmatab [i]) != 0; i++) { 571133647Srik if (!ct_is_free_res (dev, 0, SYS_RES_DRQ, 572126177Srik drq, drq + 1, 1)) 573126177Srik continue; 574126177Srik bus_set_resource (dev, SYS_RES_DRQ, 0, drq, 1); 575126177Srik break; 576126177Srik } 577126177Srik 578126177Srik if (dmatab[i] == 0) { 579126177Srik bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 580126177Srik bd->base_res); 581126177Srik printf ("ct%d: Couldn't get DRQ\n", unit); 582126177Srik return ENXIO; 583126177Srik } 584126177Srik } 585126177Srik 586126177Srik bd->drq_rid = 0; 587126177Srik bd->drq_res = bus_alloc_resource (dev, SYS_RES_DRQ, &bd->drq_rid, 588126177Srik drq, drq + 1, 1, RF_ACTIVE); 589126177Srik if (! bd->drq_res) { 590126177Srik printf ("ct%d: cannot allocate drq\n", unit); 591126177Srik bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 592126177Srik bd->base_res); 593126177Srik return ENXIO; 594126177Srik } 595126177Srik 596126177Srik if (bus_get_resource (dev, SYS_RES_IRQ, 0, &irq, &rescount) != 0) { 597126177Srik for (i = 0; (irq = irqtab [i]) != 0; i++) { 598133647Srik if (!ct_is_free_res (dev, 0, SYS_RES_IRQ, 599126177Srik irq, irq + 1, 1)) 600126177Srik continue; 601126177Srik bus_set_resource (dev, SYS_RES_IRQ, 0, irq, 1); 602126177Srik break; 603126177Srik } 604126177Srik 605126177Srik if (irqtab[i] == 0) { 606126177Srik bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 607126177Srik bd->drq_res); 608126177Srik bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 609126177Srik bd->base_res); 610126177Srik printf ("ct%d: Couldn't get IRQ\n", unit); 611126177Srik return ENXIO; 612126177Srik } 613126177Srik } 614126177Srik 615126177Srik bd->irq_rid = 0; 616126177Srik bd->irq_res = bus_alloc_resource (dev, SYS_RES_IRQ, &bd->irq_rid, 617126177Srik irq, irq + 1, 1, RF_ACTIVE); 618126177Srik if (! bd->irq_res) { 619126177Srik printf ("ct%d: Couldn't allocate irq\n", unit); 620126177Srik bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 621126177Srik bd->drq_res); 622126177Srik bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 623126177Srik bd->base_res); 624126177Srik return ENXIO; 625126177Srik } 626126177Srik 627126177Srik b = malloc (sizeof (ct_board_t), M_DEVBUF, M_WAITOK); 628126177Srik if (!b) { 629126177Srik printf ("ct:%d: Couldn't allocate memory\n", unit); 630126177Srik return (ENXIO); 631126177Srik } 632126177Srik adapter[unit] = b; 633126177Srik bzero (b, sizeof(ct_board_t)); 634126177Srik 635126177Srik if (! ct_open_board (b, unit, iobase, irq, drq)) { 636126177Srik printf ("ct%d: error loading firmware\n", unit); 637126177Srik free (b, M_DEVBUF); 638126177Srik bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 639126177Srik bd->irq_res); 640126177Srik bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 641126177Srik bd->drq_res); 642126177Srik bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 643126177Srik bd->base_res); 644126177Srik return ENXIO; 645126177Srik } 646126177Srik 647126177Srik bd->board = b; 648126177Srik 649138823Srik ct_ln[2] = '0' + unit; 650138823Srik mtx_init (&bd->ct_mtx, ct_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); 651126177Srik if (! probe_irq (b, irq)) { 652126177Srik printf ("ct%d: irq %ld not functional\n", unit, irq); 653126177Srik bd->board = 0; 654126177Srik adapter [unit] = 0; 655126177Srik free (b, M_DEVBUF); 656126177Srik bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 657126177Srik bd->irq_res); 658126177Srik bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 659126177Srik bd->drq_res); 660126177Srik bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 661126177Srik bd->base_res); 662138823Srik mtx_destroy (&bd->ct_mtx); 663126177Srik return ENXIO; 664126177Srik } 665126177Srik 666188662Srwatson callout_init (&led_timo[unit], CALLOUT_MPSAFE); 667126177Srik s = splimp (); 668138823Srik if (bus_setup_intr (dev, bd->irq_res, 669188662Srwatson INTR_TYPE_NET|INTR_MPSAFE, 670166901Spiso NULL, ct_intr, bd, &bd->intrhand)) { 671126177Srik printf ("ct%d: Can't setup irq %ld\n", unit, irq); 672126177Srik bd->board = 0; 673126177Srik adapter [unit] = 0; 674126177Srik free (b, M_DEVBUF); 675126177Srik bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 676126177Srik bd->irq_res); 677126177Srik bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 678126177Srik bd->drq_res); 679126177Srik bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 680126177Srik bd->base_res); 681138823Srik mtx_destroy (&bd->ct_mtx); 682126177Srik splx (s); 683126177Srik return ENXIO; 684126177Srik } 685138823Srik 686138823Srik CT_LOCK (bd); 687126177Srik ct_init_board (b, b->num, b->port, irq, drq, b->type, b->osc); 688126177Srik ct_setup_board (b, 0, 0, 0); 689138823Srik CT_UNLOCK (bd); 690126177Srik 691126177Srik printf ("ct%d: <Cronyx-%s>, clock %s MHz\n", b->num, b->name, 692126177Srik b->osc == 20000000 ? "20" : "16.384"); 693126177Srik 694138823Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 695130985Srik d = &bd->channel[c->num]; 696130985Srik d->dmamem.size = sizeof(ct_buf_t); 697130985Srik if (! ct_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 698130985Srik continue; 699126177Srik d->board = b; 700126177Srik d->chan = c; 701138823Srik d->bd = bd; 702126177Srik c->sys = d; 703138823Srik channel [b->num*NCHAN + c->num] = d; 704138823Srik sprintf (d->name, "ct%d.%d", b->num, c->num); 705199407Sjhb callout_init (&d->timeout_handle, CALLOUT_MPSAFE); 706126177Srik 707126177Srik#ifdef NETGRAPH 708126177Srik if (ng_make_node_common (&typestruct, &d->node) != 0) { 709126177Srik printf ("%s: cannot make common node\n", d->name); 710126177Srik channel [b->num*NCHAN + c->num] = 0; 711126177Srik c->sys = 0; 712130985Srik ct_bus_dma_mem_free (&d->dmamem); 713126177Srik continue; 714126177Srik } 715126177Srik NG_NODE_SET_PRIVATE (d->node, d); 716126177Srik sprintf (d->nodename, "%s%d", NG_CT_NODE_TYPE, 717126177Srik c->board->num*NCHAN + c->num); 718126177Srik if (ng_name_node (d->node, d->nodename)) { 719126177Srik printf ("%s: cannot name node\n", d->nodename); 720126177Srik NG_NODE_UNREF (d->node); 721126177Srik channel [b->num*NCHAN + c->num] = 0; 722126177Srik c->sys = 0; 723130985Srik ct_bus_dma_mem_free (&d->dmamem); 724126177Srik continue; 725126177Srik } 726207554Ssobomax d->queue.ifq_maxlen = ifqmaxlen; 727207554Ssobomax d->hi_queue.ifq_maxlen = ifqmaxlen; 728126177Srik mtx_init (&d->queue.ifq_mtx, "ct_queue", NULL, MTX_DEF); 729199407Sjhb mtx_init (&d->hi_queue.ifq_mtx, "ct_queue_hi", NULL, MTX_DEF); 730126177Srik#else /*NETGRAPH*/ 731147256Sbrooks d->ifp = if_alloc(IFT_PPP); 732147256Sbrooks if (d->ifp == NULL) { 733147256Sbrooks printf ("%s: cannot if_alloc common interface\n", 734147256Sbrooks d->name); 735147256Sbrooks channel [b->num*NCHAN + c->num] = 0; 736147256Sbrooks c->sys = 0; 737147256Sbrooks ct_bus_dma_mem_free (&d->dmamem); 738147256Sbrooks continue; 739147256Sbrooks } 740147856Srik d->ifp->if_softc = d; 741147256Sbrooks if_initname (d->ifp, "ct", b->num * NCHAN + c->num); 742147856Srik d->ifp->if_mtu = PP_MTU; 743147256Sbrooks d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 744147256Sbrooks d->ifp->if_ioctl = ct_sioctl; 745147256Sbrooks d->ifp->if_start = ct_ifstart; 746147856Srik d->ifp->if_init = ct_initialize; 747138823Srik d->queue.ifq_maxlen = NBUF; 748138823Srik mtx_init (&d->queue.ifq_mtx, "ct_queue", NULL, MTX_DEF); 749147256Sbrooks sppp_attach (d->ifp); 750147256Sbrooks if_attach (d->ifp); 751147856Srik IFP2SP(d->ifp)->pp_tlf = ct_tlf; 752147856Srik IFP2SP(d->ifp)->pp_tls = ct_tls; 753126177Srik /* If BPF is in the kernel, call the attach for it. 754126177Srik * Header size is 4 bytes. */ 755147256Sbrooks bpfattach (d->ifp, DLT_PPP, 4); 756126177Srik#endif /*NETGRAPH*/ 757138823Srik CT_LOCK (bd); 758130985Srik ct_start_chan (c, d->dmamem.virt, d->dmamem.phys); 759126177Srik ct_register_receive (c, &ct_receive); 760126177Srik ct_register_transmit (c, &ct_transmit); 761126177Srik ct_register_error (c, &ct_error); 762138823Srik CT_UNLOCK (bd); 763126177Srik d->devt = make_dev (&ct_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 764126177Srik GID_WHEEL, 0600, "ct%d", b->num*NCHAN+c->num); 765126177Srik } 766126177Srik splx (s); 767126177Srik 768126177Srik return 0; 769126177Srik} 770126177Srik 771126177Srikstatic int ct_detach (device_t dev) 772126177Srik{ 773126177Srik bdrv_t *bd = device_get_softc (dev); 774126177Srik ct_board_t *b = bd->board; 775126177Srik ct_chan_t *c; 776138823Srik int s; 777126177Srik 778138823Srik KASSERT (mtx_initialized (&bd->ct_mtx), ("ct mutex not initialized")); 779138823Srik 780138823Srik s = splimp (); 781138823Srik CT_LOCK (bd); 782126177Srik /* Check if the device is busy (open). */ 783126177Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 784126177Srik drv_t *d = (drv_t*) c->sys; 785126177Srik 786126177Srik if (!d || !d->chan->type) 787126177Srik continue; 788126177Srik 789126177Srik if (d->running) { 790138823Srik CT_UNLOCK (bd); 791126177Srik splx (s); 792126177Srik return EBUSY; 793126177Srik } 794126177Srik } 795126177Srik 796126177Srik /* Deactivate the timeout routine. */ 797138823Srik callout_stop (&led_timo[b->num]); 798126177Srik 799138823Srik CT_UNLOCK (bd); 800138823Srik 801126177Srik bus_teardown_intr (dev, bd->irq_res, bd->intrhand); 802126177Srik bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, bd->irq_res); 803126177Srik 804126177Srik bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, bd->drq_res); 805126177Srik 806126177Srik bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, bd->base_res); 807126177Srik 808138823Srik CT_LOCK (bd); 809126177Srik ct_close_board (b); 810138823Srik CT_UNLOCK (bd); 811126177Srik 812126177Srik /* Detach the interfaces, free buffer memory. */ 813126177Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 814126177Srik drv_t *d = (drv_t*) c->sys; 815126177Srik 816126177Srik if (!d || !d->chan->type) 817126177Srik continue; 818126177Srik 819199407Sjhb callout_stop (&d->timeout_handle); 820126177Srik#ifdef NETGRAPH 821126177Srik if (d->node) { 822126177Srik ng_rmnode_self (d->node); 823126177Srik NG_NODE_UNREF (d->node); 824126177Srik d->node = NULL; 825126177Srik } 826126177Srik mtx_destroy (&d->queue.ifq_mtx); 827126177Srik mtx_destroy (&d->hi_queue.ifq_mtx); 828126177Srik#else 829126177Srik /* Detach from the packet filter list of interfaces. */ 830147256Sbrooks bpfdetach (d->ifp); 831138823Srik 832126177Srik /* Detach from the sync PPP list. */ 833147256Sbrooks sppp_detach (d->ifp); 834126177Srik 835147256Sbrooks if_detach (d->ifp); 836147256Sbrooks if_free (d->ifp); 837138823Srik IF_DRAIN (&d->queue); 838138823Srik mtx_destroy (&d->queue.ifq_mtx); 839126177Srik#endif 840126177Srik destroy_dev (d->devt); 841126177Srik } 842126177Srik 843138823Srik CT_LOCK (bd); 844126177Srik ct_led_off (b); 845138823Srik CT_UNLOCK (bd); 846138823Srik callout_drain (&led_timo[b->num]); 847126177Srik splx (s); 848126177Srik 849126177Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 850126177Srik drv_t *d = (drv_t*) c->sys; 851126177Srik 852126177Srik if (!d || !d->chan->type) 853126177Srik continue; 854199407Sjhb callout_drain(&d->timeout_handle); 855126177Srik 856126177Srik /* Deallocate buffers. */ 857130985Srik ct_bus_dma_mem_free (&d->dmamem); 858126177Srik } 859126177Srik bd->board = 0; 860126177Srik adapter [b->num] = 0; 861126177Srik free (b, M_DEVBUF); 862126177Srik 863138823Srik mtx_destroy (&bd->ct_mtx); 864138823Srik 865126177Srik return 0; 866126177Srik} 867126177Srik 868126177Srik#ifndef NETGRAPH 869126177Srikstatic void ct_ifstart (struct ifnet *ifp) 870126177Srik{ 871133645Srik drv_t *d = ifp->if_softc; 872138823Srik bdrv_t *bd = d->bd; 873138823Srik 874138823Srik CT_LOCK (bd); 875126177Srik ct_start (d); 876138823Srik CT_UNLOCK (bd); 877126177Srik} 878126177Srik 879126177Srikstatic void ct_tlf (struct sppp *sp) 880126177Srik{ 881147256Sbrooks drv_t *d = SP2IFP(sp)->if_softc; 882126177Srik 883126177Srik CT_DEBUG (d, ("ct_tlf\n")); 884126177Srik/* ct_set_dtr (d->chan, 0);*/ 885126177Srik/* ct_set_rts (d->chan, 0);*/ 886147256Sbrooks if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 887138352Srik sp->pp_down (sp); 888126177Srik} 889126177Srik 890126177Srikstatic void ct_tls (struct sppp *sp) 891126177Srik{ 892147256Sbrooks drv_t *d = SP2IFP(sp)->if_softc; 893126177Srik 894126177Srik CT_DEBUG (d, ("ct_tls\n")); 895147256Sbrooks if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 896138352Srik sp->pp_up (sp); 897126177Srik} 898126177Srik 899126177Srik/* 900126177Srik * Initialization of interface. 901126177Srik * Ii seems to be never called by upper level. 902126177Srik */ 903126177Srikstatic void ct_initialize (void *softc) 904126177Srik{ 905126177Srik drv_t *d = softc; 906126177Srik 907126177Srik CT_DEBUG (d, ("ct_initialize\n")); 908126177Srik} 909126177Srik 910126177Srik/* 911126177Srik * Process an ioctl request. 912126177Srik */ 913126177Srikstatic int ct_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 914126177Srik{ 915126177Srik drv_t *d = ifp->if_softc; 916138823Srik bdrv_t *bd = d->bd; 917126177Srik int error, s, was_up, should_be_up; 918126177Srik 919148887Srwatson was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 920126177Srik error = sppp_ioctl (ifp, cmd, data); 921126177Srik if (error) 922126177Srik return error; 923126177Srik 924126177Srik if (! (ifp->if_flags & IFF_DEBUG)) 925126177Srik d->chan->debug = 0; 926180132Srik else 927180132Srik d->chan->debug = d->chan->debug_shadow; 928126177Srik 929126177Srik switch (cmd) { 930133645Srik default: CT_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 931126177Srik case SIOCADDMULTI: CT_DEBUG2 (d, ("SIOCADDMULTI\n")); return 0; 932126177Srik case SIOCDELMULTI: CT_DEBUG2 (d, ("SIOCDELMULTI\n")); return 0; 933126177Srik case SIOCSIFFLAGS: CT_DEBUG2 (d, ("SIOCSIFFLAGS\n")); break; 934126177Srik case SIOCSIFADDR: CT_DEBUG2 (d, ("SIOCSIFADDR\n")); break; 935126177Srik } 936126177Srik 937126177Srik /* We get here only in case of SIFFLAGS or SIFADDR. */ 938126177Srik s = splimp (); 939138823Srik CT_LOCK (bd); 940148887Srwatson should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 941126177Srik if (! was_up && should_be_up) { 942126177Srik /* Interface goes up -- start it. */ 943126177Srik ct_up (d); 944126177Srik ct_start (d); 945126177Srik } else if (was_up && ! should_be_up) { 946126177Srik /* Interface is going down -- stop it. */ 947147256Sbrooks /* if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 948126177Srik ct_down (d); 949126177Srik } 950138823Srik CT_UNLOCK (bd); 951126177Srik splx (s); 952126177Srik return 0; 953126177Srik} 954126177Srik#endif /*NETGRAPH*/ 955126177Srik 956126177Srik/* 957126177Srik * Stop the interface. Called on splimp(). 958126177Srik */ 959126177Srikstatic void ct_down (drv_t *d) 960126177Srik{ 961126177Srik int s = splimp (); 962126177Srik CT_DEBUG (d, ("ct_down\n")); 963126177Srik ct_set_dtr (d->chan, 0); 964126177Srik ct_set_rts (d->chan, 0); 965126177Srik d->running = 0; 966199407Sjhb callout_stop (&d->timeout_handle); 967126177Srik splx (s); 968126177Srik} 969126177Srik 970126177Srik/* 971126177Srik * Start the interface. Called on splimp(). 972126177Srik */ 973126177Srikstatic void ct_up (drv_t *d) 974126177Srik{ 975126177Srik int s = splimp (); 976126177Srik CT_DEBUG (d, ("ct_up\n")); 977126177Srik ct_set_dtr (d->chan, 1); 978126177Srik ct_set_rts (d->chan, 1); 979126177Srik d->running = 1; 980126177Srik splx (s); 981126177Srik} 982126177Srik 983126177Srik/* 984126177Srik * Start output on the (slave) interface. Get another datagram to send 985126177Srik * off of the interface queue, and copy it to the interface 986126177Srik * before starting the output. 987126177Srik */ 988126177Srikstatic void ct_send (drv_t *d) 989126177Srik{ 990126177Srik struct mbuf *m; 991126177Srik u_short len; 992126177Srik 993126177Srik CT_DEBUG2 (d, ("ct_send, tn=%d\n", d->chan->tn)); 994126177Srik 995126177Srik /* No output if the interface is down. */ 996126177Srik if (! d->running) 997126177Srik return; 998126177Srik 999126177Srik /* No output if the modem is off. */ 1000126177Srik if (! ct_get_dsr (d->chan) && !ct_get_loop (d->chan)) 1001126177Srik return; 1002126177Srik 1003126177Srik while (ct_buf_free (d->chan)) { 1004126177Srik /* Get the packet to send. */ 1005126177Srik#ifdef NETGRAPH 1006126177Srik IF_DEQUEUE (&d->hi_queue, m); 1007126177Srik if (! m) 1008126177Srik IF_DEQUEUE (&d->queue, m); 1009126177Srik#else 1010147256Sbrooks m = sppp_dequeue (d->ifp); 1011126177Srik#endif 1012126177Srik if (! m) 1013126177Srik return; 1014130971Srik#ifndef NETGRAPH 1015165632Sjhb BPF_MTAP (d->ifp, m); 1016126177Srik#endif 1017147862Srik len = m_length (m, NULL); 1018126177Srik if (! m->m_next) 1019126177Srik ct_send_packet (d->chan, (u_char*)mtod (m, caddr_t), 1020126177Srik len, 0); 1021126177Srik else { 1022126177Srik m_copydata (m, 0, len, d->chan->tbuf[d->chan->te]); 1023126177Srik ct_send_packet (d->chan, d->chan->tbuf[d->chan->te], 1024126177Srik len, 0); 1025126177Srik } 1026126177Srik m_freem (m); 1027126177Srik 1028126177Srik /* Set up transmit timeout, if the transmit ring is not empty. 1029126177Srik * Transmit timeout is 10 seconds. */ 1030126177Srik d->timeout = 10; 1031126177Srik } 1032126177Srik#ifndef NETGRAPH 1033148887Srwatson d->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1034126177Srik#endif 1035126177Srik} 1036126177Srik 1037126177Srik/* 1038126177Srik * Start output on the interface. 1039126177Srik * Always called on splimp(). 1040126177Srik */ 1041126177Srikstatic void ct_start (drv_t *d) 1042126177Srik{ 1043126177Srik int s = splimp (); 1044126177Srik 1045126177Srik if (d->running) { 1046126177Srik if (! d->chan->dtr) 1047126177Srik ct_set_dtr (d->chan, 1); 1048126177Srik if (! d->chan->rts) 1049126177Srik ct_set_rts (d->chan, 1); 1050126177Srik ct_send (d); 1051199407Sjhb callout_reset (&d->timeout_handle, hz, ct_watchdog_timer, d); 1052126177Srik } 1053126177Srik 1054126177Srik splx (s); 1055126177Srik} 1056126177Srik 1057126177Srik/* 1058126177Srik * Handle transmit timeouts. 1059126177Srik * Recover after lost transmit interrupts. 1060126177Srik * Always called on splimp(). 1061126177Srik */ 1062126177Srikstatic void ct_watchdog (drv_t *d) 1063126177Srik{ 1064126177Srik 1065126177Srik CT_DEBUG (d, ("device timeout\n")); 1066126177Srik if (d->running) { 1067126177Srik ct_setup_chan (d->chan); 1068126177Srik ct_start_chan (d->chan, 0, 0); 1069126177Srik ct_set_dtr (d->chan, 1); 1070126177Srik ct_set_rts (d->chan, 1); 1071126177Srik ct_start (d); 1072126177Srik } 1073199407Sjhb} 1074199407Sjhb 1075199407Sjhbstatic void ct_watchdog_timer (void *arg) 1076199407Sjhb{ 1077199407Sjhb drv_t *d = arg; 1078199407Sjhb bdrv_t *bd = d->bd; 1079199407Sjhb 1080199407Sjhb CT_LOCK (bd); 1081199407Sjhb if (d->timeout == 1) 1082199407Sjhb ct_watchdog (d); 1083199407Sjhb if (d->timeout) 1084199407Sjhb d->timeout--; 1085199407Sjhb callout_reset (&d->timeout_handle, hz, ct_watchdog_timer, d); 1086138823Srik CT_UNLOCK (bd); 1087126177Srik} 1088126177Srik 1089126177Srik/* 1090126177Srik * Transmit callback function. 1091126177Srik */ 1092126177Srikstatic void ct_transmit (ct_chan_t *c, void *attachment, int len) 1093126177Srik{ 1094126177Srik drv_t *d = c->sys; 1095126177Srik 1096126177Srik if (!d) 1097126177Srik return; 1098126177Srik d->timeout = 0; 1099199407Sjhb#ifndef NETGRAPH 1100147256Sbrooks ++d->ifp->if_opackets; 1101148887Srwatson d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1102126177Srik#endif 1103126177Srik ct_start (d); 1104126177Srik} 1105126177Srik 1106126177Srik/* 1107126177Srik * Process the received packet. 1108126177Srik */ 1109126177Srikstatic void ct_receive (ct_chan_t *c, char *data, int len) 1110126177Srik{ 1111126177Srik drv_t *d = c->sys; 1112126177Srik struct mbuf *m; 1113138651Srik#ifdef NETGRAPH 1114126177Srik int error; 1115126177Srik#endif 1116126177Srik 1117126177Srik if (!d || !d->running) 1118126177Srik return; 1119126177Srik 1120126177Srik m = makembuf (data, len); 1121126177Srik if (! m) { 1122126177Srik CT_DEBUG (d, ("no memory for packet\n")); 1123126177Srik#ifndef NETGRAPH 1124147256Sbrooks ++d->ifp->if_iqdrops; 1125126177Srik#endif 1126126177Srik return; 1127126177Srik } 1128126177Srik if (c->debug > 1) 1129126177Srik printmbuf (m); 1130126177Srik#ifdef NETGRAPH 1131126177Srik m->m_pkthdr.rcvif = 0; 1132126177Srik NG_SEND_DATA_ONLY (error, d->hook, m); 1133126177Srik#else 1134147256Sbrooks ++d->ifp->if_ipackets; 1135147256Sbrooks m->m_pkthdr.rcvif = d->ifp; 1136126177Srik /* Check if there's a BPF listener on this interface. 1137126177Srik * If so, hand off the raw packet to bpf. */ 1138165632Sjhb BPF_TAP (d->ifp, data, len); 1139138823Srik IF_ENQUEUE (&d->queue, m); 1140126177Srik#endif 1141126177Srik} 1142126177Srik 1143126177Srik/* 1144126177Srik * Error callback function. 1145126177Srik */ 1146126177Srikstatic void ct_error (ct_chan_t *c, int data) 1147126177Srik{ 1148126177Srik drv_t *d = c->sys; 1149126177Srik 1150126177Srik if (!d) 1151126177Srik return; 1152126177Srik 1153126177Srik switch (data) { 1154126177Srik case CT_FRAME: 1155126177Srik CT_DEBUG (d, ("frame error\n")); 1156126177Srik#ifndef NETGRAPH 1157147256Sbrooks ++d->ifp->if_ierrors; 1158126177Srik#endif 1159126177Srik break; 1160126177Srik case CT_CRC: 1161126177Srik CT_DEBUG (d, ("crc error\n")); 1162126177Srik#ifndef NETGRAPH 1163147256Sbrooks ++d->ifp->if_ierrors; 1164126177Srik#endif 1165126177Srik break; 1166126177Srik case CT_OVERRUN: 1167126177Srik CT_DEBUG (d, ("overrun error\n")); 1168126177Srik#ifndef NETGRAPH 1169147256Sbrooks ++d->ifp->if_collisions; 1170147256Sbrooks ++d->ifp->if_ierrors; 1171126177Srik#endif 1172126177Srik break; 1173126177Srik case CT_OVERFLOW: 1174126177Srik CT_DEBUG (d, ("overflow error\n")); 1175126177Srik#ifndef NETGRAPH 1176147256Sbrooks ++d->ifp->if_ierrors; 1177126177Srik#endif 1178126177Srik break; 1179126177Srik case CT_UNDERRUN: 1180126177Srik CT_DEBUG (d, ("underrun error\n")); 1181126177Srik d->timeout = 0; 1182199407Sjhb#ifndef NETGRAPH 1183147256Sbrooks ++d->ifp->if_oerrors; 1184148887Srwatson d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1185126177Srik#endif 1186126177Srik ct_start (d); 1187126177Srik break; 1188126177Srik default: 1189126177Srik CT_DEBUG (d, ("error #%d\n", data)); 1190126177Srik } 1191126177Srik} 1192126177Srik 1193150622Srikstatic int ct_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 1194150622Srik{ 1195150622Srik drv_t *d; 1196150622Srik 1197183397Sed if (dev2unit(dev) >= NCTAU*NCHAN || ! (d = channel[dev2unit(dev)])) 1198150622Srik return ENXIO; 1199150622Srik 1200150622Srik CT_DEBUG2 (d, ("ct_open\n")); 1201150622Srik return 0; 1202150622Srik} 1203150622Srik 1204150622Srikstatic int ct_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 1205150622Srik{ 1206183397Sed drv_t *d = channel [dev2unit(dev)]; 1207150622Srik 1208150622Srik if (!d) 1209150622Srik return 0; 1210150622Srik 1211150622Srik CT_DEBUG2 (d, ("ct_close\n")); 1212150622Srik return 0; 1213150622Srik} 1214150622Srik 1215150622Srikstatic int ct_modem_status (ct_chan_t *c) 1216150622Srik{ 1217150622Srik drv_t *d = c->sys; 1218150622Srik bdrv_t *bd; 1219150622Srik int status, s; 1220150622Srik 1221150622Srik if (!d) 1222150622Srik return 0; 1223150622Srik 1224150622Srik bd = d->bd; 1225150622Srik 1226150622Srik status = d->running ? TIOCM_LE : 0; 1227150622Srik s = splimp (); 1228150622Srik CT_LOCK (bd); 1229150622Srik if (ct_get_cd (c)) status |= TIOCM_CD; 1230150622Srik if (ct_get_cts (c)) status |= TIOCM_CTS; 1231150622Srik if (ct_get_dsr (c)) status |= TIOCM_DSR; 1232150622Srik if (c->dtr) status |= TIOCM_DTR; 1233150622Srik if (c->rts) status |= TIOCM_RTS; 1234150622Srik CT_UNLOCK (bd); 1235150622Srik splx (s); 1236150622Srik return status; 1237150622Srik} 1238150622Srik 1239150622Srik/* 1240150622Srik * Process an ioctl request on /dev/cronyx/ctauN. 1241150622Srik */ 1242150622Srikstatic int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1243150622Srik{ 1244183397Sed drv_t *d = channel [dev2unit (dev)]; 1245150622Srik bdrv_t *bd; 1246150622Srik ct_chan_t *c; 1247150622Srik struct serial_statistics *st; 1248150622Srik struct e1_statistics *opte1; 1249150622Srik int error, s; 1250150622Srik char mask[16]; 1251150622Srik 1252150622Srik if (!d || !d->chan) 1253150622Srik return 0; 1254150622Srik 1255150622Srik bd = d->bd; 1256150622Srik c = d->chan; 1257150622Srik 1258150622Srik switch (cmd) { 1259150622Srik case SERIAL_GETREGISTERED: 1260150622Srik bzero (mask, sizeof(mask)); 1261150622Srik for (s=0; s<NCTAU*NCHAN; ++s) 1262150622Srik if (channel [s]) 1263150622Srik mask [s/8] |= 1 << (s & 7); 1264150622Srik bcopy (mask, data, sizeof (mask)); 1265150622Srik return 0; 1266150622Srik 1267150622Srik#ifndef NETGRAPH 1268150622Srik case SERIAL_GETPROTO: 1269150622Srik strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" : 1270150622Srik (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp"); 1271150622Srik return 0; 1272150622Srik 1273150622Srik case SERIAL_SETPROTO: 1274150622Srik /* Only for superuser! */ 1275164033Srwatson error = priv_check (td, PRIV_DRIVER); 1276150622Srik if (error) 1277150622Srik return error; 1278150622Srik if (d->ifp->if_drv_flags & IFF_DRV_RUNNING) 1279150622Srik return EBUSY; 1280150622Srik if (! strcmp ("cisco", (char*)data)) { 1281150622Srik IFP2SP(d->ifp)->pp_flags &= ~(PP_FR); 1282150622Srik IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1283150622Srik d->ifp->if_flags |= PP_CISCO; 1284150622Srik } else if (! strcmp ("fr", (char*)data)) { 1285150622Srik d->ifp->if_flags &= ~(PP_CISCO); 1286150622Srik IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE; 1287150622Srik } else if (! strcmp ("ppp", (char*)data)) { 1288150622Srik IFP2SP(d->ifp)->pp_flags &= ~(PP_FR | PP_KEEPALIVE); 1289150622Srik d->ifp->if_flags &= ~(PP_CISCO); 1290150622Srik } else 1291150622Srik return EINVAL; 1292150622Srik return 0; 1293150622Srik 1294150622Srik case SERIAL_GETKEEPALIVE: 1295150622Srik if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1296150622Srik (d->ifp->if_flags & PP_CISCO)) 1297150622Srik return EINVAL; 1298150622Srik *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0; 1299150622Srik return 0; 1300150622Srik 1301150622Srik case SERIAL_SETKEEPALIVE: 1302150622Srik /* Only for superuser! */ 1303164033Srwatson error = priv_check (td, PRIV_DRIVER); 1304150622Srik if (error) 1305150622Srik return error; 1306150622Srik if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1307150622Srik (d->ifp->if_flags & PP_CISCO)) 1308150622Srik return EINVAL; 1309150622Srik if (*(int*)data) 1310150622Srik IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1311150622Srik else 1312150622Srik IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1313150622Srik return 0; 1314150622Srik#endif /*NETGRAPH*/ 1315150622Srik 1316150622Srik case SERIAL_GETMODE: 1317150622Srik *(int*)data = SERIAL_HDLC; 1318150622Srik return 0; 1319150622Srik 1320150622Srik case SERIAL_GETCFG: 1321150622Srik if (c->mode == M_HDLC) 1322150622Srik return EINVAL; 1323150622Srik switch (ct_get_config (c->board)) { 1324150622Srik default: *(char*)data = 'a'; break; 1325150622Srik case CFG_B: *(char*)data = 'b'; break; 1326150622Srik case CFG_C: *(char*)data = 'c'; break; 1327150622Srik } 1328150622Srik return 0; 1329150622Srik 1330150622Srik case SERIAL_SETCFG: 1331150622Srik /* Only for superuser! */ 1332164033Srwatson error = priv_check (td, PRIV_DRIVER); 1333150622Srik if (error) 1334150622Srik return error; 1335150622Srik if (c->mode == M_HDLC) 1336150622Srik return EINVAL; 1337150622Srik s = splimp (); 1338150622Srik CT_LOCK (bd); 1339150622Srik switch (*(char*)data) { 1340150622Srik case 'a': ct_set_config (c->board, CFG_A); break; 1341150622Srik case 'b': ct_set_config (c->board, CFG_B); break; 1342150622Srik case 'c': ct_set_config (c->board, CFG_C); break; 1343150622Srik } 1344150622Srik CT_UNLOCK (bd); 1345150622Srik splx (s); 1346150622Srik return 0; 1347150622Srik 1348150622Srik case SERIAL_GETSTAT: 1349150622Srik st = (struct serial_statistics*) data; 1350150622Srik st->rintr = c->rintr; 1351150622Srik st->tintr = c->tintr; 1352150622Srik st->mintr = c->mintr; 1353150622Srik st->ibytes = c->ibytes; 1354150622Srik st->ipkts = c->ipkts; 1355150622Srik st->ierrs = c->ierrs; 1356150622Srik st->obytes = c->obytes; 1357150622Srik st->opkts = c->opkts; 1358150622Srik st->oerrs = c->oerrs; 1359150622Srik return 0; 1360150622Srik 1361150622Srik case SERIAL_GETESTAT: 1362150622Srik opte1 = (struct e1_statistics*)data; 1363150622Srik opte1->status = c->status; 1364150622Srik opte1->cursec = c->cursec; 1365150622Srik opte1->totsec = c->totsec + c->cursec; 1366150622Srik 1367150622Srik opte1->currnt.bpv = c->currnt.bpv; 1368150622Srik opte1->currnt.fse = c->currnt.fse; 1369150622Srik opte1->currnt.crce = c->currnt.crce; 1370150622Srik opte1->currnt.rcrce = c->currnt.rcrce; 1371150622Srik opte1->currnt.uas = c->currnt.uas; 1372150622Srik opte1->currnt.les = c->currnt.les; 1373150622Srik opte1->currnt.es = c->currnt.es; 1374150622Srik opte1->currnt.bes = c->currnt.bes; 1375150622Srik opte1->currnt.ses = c->currnt.ses; 1376150622Srik opte1->currnt.oofs = c->currnt.oofs; 1377150622Srik opte1->currnt.css = c->currnt.css; 1378150622Srik opte1->currnt.dm = c->currnt.dm; 1379150622Srik 1380150622Srik opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1381150622Srik opte1->total.fse = c->total.fse + c->currnt.fse; 1382150622Srik opte1->total.crce = c->total.crce + c->currnt.crce; 1383150622Srik opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1384150622Srik opte1->total.uas = c->total.uas + c->currnt.uas; 1385150622Srik opte1->total.les = c->total.les + c->currnt.les; 1386150622Srik opte1->total.es = c->total.es + c->currnt.es; 1387150622Srik opte1->total.bes = c->total.bes + c->currnt.bes; 1388150622Srik opte1->total.ses = c->total.ses + c->currnt.ses; 1389150622Srik opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1390150622Srik opte1->total.css = c->total.css + c->currnt.css; 1391150622Srik opte1->total.dm = c->total.dm + c->currnt.dm; 1392150622Srik for (s=0; s<48; ++s) { 1393150622Srik opte1->interval[s].bpv = c->interval[s].bpv; 1394150622Srik opte1->interval[s].fse = c->interval[s].fse; 1395150622Srik opte1->interval[s].crce = c->interval[s].crce; 1396150622Srik opte1->interval[s].rcrce = c->interval[s].rcrce; 1397150622Srik opte1->interval[s].uas = c->interval[s].uas; 1398150622Srik opte1->interval[s].les = c->interval[s].les; 1399150622Srik opte1->interval[s].es = c->interval[s].es; 1400150622Srik opte1->interval[s].bes = c->interval[s].bes; 1401150622Srik opte1->interval[s].ses = c->interval[s].ses; 1402150622Srik opte1->interval[s].oofs = c->interval[s].oofs; 1403150622Srik opte1->interval[s].css = c->interval[s].css; 1404150622Srik opte1->interval[s].dm = c->interval[s].dm; 1405150622Srik } 1406150622Srik return 0; 1407150622Srik 1408150622Srik case SERIAL_CLRSTAT: 1409150622Srik /* Only for superuser! */ 1410164033Srwatson error = priv_check (td, PRIV_DRIVER); 1411150622Srik if (error) 1412150622Srik return error; 1413150622Srik c->rintr = 0; 1414150622Srik c->tintr = 0; 1415150622Srik c->mintr = 0; 1416150622Srik c->ibytes = 0; 1417150622Srik c->ipkts = 0; 1418150622Srik c->ierrs = 0; 1419150622Srik c->obytes = 0; 1420150622Srik c->opkts = 0; 1421150622Srik c->oerrs = 0; 1422150622Srik bzero (&c->currnt, sizeof (c->currnt)); 1423150622Srik bzero (&c->total, sizeof (c->total)); 1424150622Srik bzero (c->interval, sizeof (c->interval)); 1425150622Srik return 0; 1426150622Srik 1427150622Srik case SERIAL_GETBAUD: 1428150622Srik *(long*)data = ct_get_baud(c); 1429150622Srik return 0; 1430150622Srik 1431150622Srik case SERIAL_SETBAUD: 1432150622Srik /* Only for superuser! */ 1433164033Srwatson error = priv_check (td, PRIV_DRIVER); 1434150622Srik if (error) 1435150622Srik return error; 1436150622Srik s = splimp (); 1437150622Srik CT_LOCK (bd); 1438150622Srik ct_set_baud (c, *(long*)data); 1439150622Srik CT_UNLOCK (bd); 1440150622Srik splx (s); 1441150622Srik return 0; 1442150622Srik 1443150622Srik case SERIAL_GETLOOP: 1444150622Srik *(int*)data = ct_get_loop (c); 1445150622Srik return 0; 1446150622Srik 1447150622Srik case SERIAL_SETLOOP: 1448150622Srik /* Only for superuser! */ 1449164033Srwatson error = priv_check (td, PRIV_DRIVER); 1450150622Srik if (error) 1451150622Srik return error; 1452150622Srik s = splimp (); 1453150622Srik CT_LOCK (bd); 1454150622Srik ct_set_loop (c, *(int*)data); 1455150622Srik CT_UNLOCK (bd); 1456150622Srik splx (s); 1457150622Srik return 0; 1458150622Srik 1459150622Srik case SERIAL_GETDPLL: 1460150622Srik if (c->mode == M_E1 || c->mode == M_G703) 1461150622Srik return EINVAL; 1462150622Srik *(int*)data = ct_get_dpll (c); 1463150622Srik return 0; 1464150622Srik 1465150622Srik case SERIAL_SETDPLL: 1466150622Srik /* Only for superuser! */ 1467164033Srwatson error = priv_check (td, PRIV_DRIVER); 1468150622Srik if (error) 1469150622Srik return error; 1470150622Srik if (c->mode == M_E1 || c->mode == M_G703) 1471150622Srik return EINVAL; 1472150622Srik s = splimp (); 1473150622Srik CT_LOCK (bd); 1474150622Srik ct_set_dpll (c, *(int*)data); 1475150622Srik CT_UNLOCK (bd); 1476150622Srik splx (s); 1477150622Srik return 0; 1478150622Srik 1479150622Srik case SERIAL_GETNRZI: 1480150622Srik if (c->mode == M_E1 || c->mode == M_G703) 1481150622Srik return EINVAL; 1482150622Srik *(int*)data = ct_get_nrzi (c); 1483150622Srik return 0; 1484150622Srik 1485150622Srik case SERIAL_SETNRZI: 1486150622Srik /* Only for superuser! */ 1487164033Srwatson error = priv_check (td, PRIV_DRIVER); 1488150622Srik if (error) 1489150622Srik return error; 1490150622Srik if (c->mode == M_E1 || c->mode == M_G703) 1491150622Srik return EINVAL; 1492150622Srik s = splimp (); 1493150622Srik CT_LOCK (bd); 1494150622Srik ct_set_nrzi (c, *(int*)data); 1495150622Srik CT_UNLOCK (bd); 1496150622Srik splx (s); 1497150622Srik return 0; 1498150622Srik 1499150622Srik case SERIAL_GETDEBUG: 1500150622Srik *(int*)data = c->debug; 1501150622Srik return 0; 1502150622Srik 1503150622Srik case SERIAL_SETDEBUG: 1504150622Srik /* Only for superuser! */ 1505164033Srwatson error = priv_check (td, PRIV_DRIVER); 1506150622Srik if (error) 1507150622Srik return error; 1508180132Srik#ifndef NETGRAPH 1509180132Srik /* 1510180132Srik * The debug_shadow is always greater than zero for logic 1511180132Srik * simplicity. For switching debug off the IFF_DEBUG is 1512180132Srik * responsible. 1513180132Srik */ 1514180132Srik c->debug_shadow = (*(int*)data) ? (*(int*)data) : 1; 1515180132Srik if (d->ifp->if_flags & IFF_DEBUG) 1516180132Srik c->debug = c->debug_shadow; 1517180132Srik#else 1518150622Srik c->debug = *(int*)data; 1519150622Srik#endif 1520150622Srik return 0; 1521150622Srik 1522150622Srik case SERIAL_GETHIGAIN: 1523150622Srik if (c->mode != M_E1) 1524150622Srik return EINVAL; 1525150622Srik *(int*)data = ct_get_higain (c); 1526150622Srik return 0; 1527150622Srik 1528150622Srik case SERIAL_SETHIGAIN: 1529150622Srik /* Only for superuser! */ 1530164033Srwatson error = priv_check (td, PRIV_DRIVER); 1531150622Srik if (error) 1532150622Srik return error; 1533150622Srik s = splimp (); 1534150622Srik CT_LOCK (bd); 1535150622Srik ct_set_higain (c, *(int*)data); 1536150622Srik CT_UNLOCK (bd); 1537150622Srik splx (s); 1538150622Srik return 0; 1539150622Srik 1540150622Srik case SERIAL_GETPHONY: 1541150622Srik CT_DEBUG2 (d, ("ioctl: getphony\n")); 1542150622Srik if (c->mode != M_E1) 1543150622Srik return EINVAL; 1544150622Srik *(int*)data = c->gopt.phony; 1545150622Srik return 0; 1546150622Srik 1547150622Srik case SERIAL_SETPHONY: 1548150622Srik CT_DEBUG2 (d, ("ioctl: setphony\n")); 1549150622Srik if (c->mode != M_E1) 1550150622Srik return EINVAL; 1551150622Srik /* Only for superuser! */ 1552164033Srwatson error = priv_check (td, PRIV_DRIVER); 1553150622Srik if (error) 1554150622Srik return error; 1555150622Srik s = splimp (); 1556150622Srik CT_LOCK (bd); 1557150622Srik ct_set_phony (c, *(int*)data); 1558150622Srik CT_UNLOCK (bd); 1559150622Srik splx (s); 1560150622Srik return 0; 1561150622Srik 1562150622Srik case SERIAL_GETCLK: 1563150622Srik if (c->mode != M_E1 && c->mode != M_G703) 1564150622Srik return EINVAL; 1565150622Srik switch (ct_get_clk(c)) { 1566150622Srik default: *(int*)data = E1CLK_INTERNAL; break; 1567150622Srik case GCLK_RCV: *(int*)data = E1CLK_RECEIVE; break; 1568150622Srik case GCLK_RCLKO: *(int*)data = c->num ? 1569150622Srik E1CLK_RECEIVE_CHAN0 : E1CLK_RECEIVE_CHAN1; break; 1570150622Srik } 1571150622Srik return 0; 1572150622Srik 1573150622Srik case SERIAL_SETCLK: 1574150622Srik /* Only for superuser! */ 1575164033Srwatson error = priv_check (td, PRIV_DRIVER); 1576150622Srik if (error) 1577150622Srik return error; 1578150622Srik s = splimp (); 1579150622Srik CT_LOCK (bd); 1580150622Srik switch (*(int*)data) { 1581150622Srik default: ct_set_clk (c, GCLK_INT); break; 1582150622Srik case E1CLK_RECEIVE: ct_set_clk (c, GCLK_RCV); break; 1583150622Srik case E1CLK_RECEIVE_CHAN0: 1584150622Srik case E1CLK_RECEIVE_CHAN1: 1585150622Srik ct_set_clk (c, GCLK_RCLKO); break; 1586150622Srik } 1587150622Srik CT_UNLOCK (bd); 1588150622Srik splx (s); 1589150622Srik return 0; 1590150622Srik 1591150622Srik case SERIAL_GETTIMESLOTS: 1592150622Srik if (c->mode != M_E1) 1593150622Srik return EINVAL; 1594150622Srik *(long*)data = ct_get_ts (c); 1595150622Srik return 0; 1596150622Srik 1597150622Srik case SERIAL_SETTIMESLOTS: 1598150622Srik /* Only for superuser! */ 1599164033Srwatson error = priv_check (td, PRIV_DRIVER); 1600150622Srik if (error) 1601150622Srik return error; 1602150622Srik s = splimp (); 1603150622Srik CT_LOCK (bd); 1604150622Srik ct_set_ts (c, *(long*)data); 1605150622Srik CT_UNLOCK (bd); 1606150622Srik splx (s); 1607150622Srik return 0; 1608150622Srik 1609150622Srik case SERIAL_GETSUBCHAN: 1610150622Srik if (c->mode != M_E1) 1611150622Srik return EINVAL; 1612150622Srik *(long*)data = ct_get_subchan (c->board); 1613150622Srik return 0; 1614150622Srik 1615150622Srik case SERIAL_SETSUBCHAN: 1616150622Srik /* Only for superuser! */ 1617164033Srwatson error = priv_check (td, PRIV_DRIVER); 1618150622Srik if (error) 1619150622Srik return error; 1620150622Srik s = splimp (); 1621150622Srik CT_LOCK (bd); 1622150622Srik ct_set_subchan (c->board, *(long*)data); 1623150622Srik CT_UNLOCK (bd); 1624150622Srik splx (s); 1625150622Srik return 0; 1626150622Srik 1627150622Srik case SERIAL_GETINVCLK: 1628150622Srik case SERIAL_GETINVTCLK: 1629150622Srik if (c->mode == M_E1 || c->mode == M_G703) 1630150622Srik return EINVAL; 1631150622Srik *(int*)data = ct_get_invtxc (c); 1632150622Srik return 0; 1633150622Srik 1634150622Srik case SERIAL_GETINVRCLK: 1635150622Srik if (c->mode == M_E1 || c->mode == M_G703) 1636150622Srik return EINVAL; 1637150622Srik *(int*)data = ct_get_invrxc (c); 1638150622Srik return 0; 1639150622Srik 1640150622Srik case SERIAL_SETINVCLK: 1641150622Srik case SERIAL_SETINVTCLK: 1642150622Srik /* Only for superuser! */ 1643164033Srwatson error = priv_check (td, PRIV_DRIVER); 1644150622Srik if (error) 1645150622Srik return error; 1646150622Srik if (c->mode == M_E1 || c->mode == M_G703) 1647150622Srik return EINVAL; 1648150622Srik s = splimp (); 1649150622Srik CT_LOCK (bd); 1650150622Srik ct_set_invtxc (c, *(int*)data); 1651150622Srik CT_UNLOCK (bd); 1652150622Srik splx (s); 1653150622Srik return 0; 1654150622Srik 1655150622Srik case SERIAL_SETINVRCLK: 1656150622Srik /* Only for superuser! */ 1657164033Srwatson error = priv_check (td, PRIV_DRIVER); 1658150622Srik if (error) 1659150622Srik return error; 1660150622Srik if (c->mode == M_E1 || c->mode == M_G703) 1661150622Srik return EINVAL; 1662150622Srik s = splimp (); 1663150622Srik CT_LOCK (bd); 1664150622Srik ct_set_invrxc (c, *(int*)data); 1665150622Srik CT_UNLOCK (bd); 1666150622Srik splx (s); 1667150622Srik return 0; 1668150622Srik 1669150622Srik case SERIAL_GETLEVEL: 1670150622Srik if (c->mode != M_G703) 1671150622Srik return EINVAL; 1672150622Srik s = splimp (); 1673150622Srik CT_LOCK (bd); 1674150622Srik *(int*)data = ct_get_lq (c); 1675150622Srik CT_UNLOCK (bd); 1676150622Srik splx (s); 1677150622Srik return 0; 1678150622Srik 1679150622Srik case TIOCSDTR: /* Set DTR */ 1680150622Srik s = splimp (); 1681150622Srik CT_LOCK (bd); 1682150622Srik ct_set_dtr (c, 1); 1683150622Srik CT_UNLOCK (bd); 1684150622Srik splx (s); 1685150622Srik return 0; 1686150622Srik 1687150622Srik case TIOCCDTR: /* Clear DTR */ 1688150622Srik s = splimp (); 1689150622Srik CT_LOCK (bd); 1690150622Srik ct_set_dtr (c, 0); 1691150622Srik CT_UNLOCK (bd); 1692150622Srik splx (s); 1693150622Srik return 0; 1694150622Srik 1695150622Srik case TIOCMSET: /* Set DTR/RTS */ 1696150622Srik s = splimp (); 1697150622Srik CT_LOCK (bd); 1698150622Srik ct_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1699150622Srik ct_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1700150622Srik CT_UNLOCK (bd); 1701150622Srik splx (s); 1702150622Srik return 0; 1703150622Srik 1704150622Srik case TIOCMBIS: /* Add DTR/RTS */ 1705150622Srik s = splimp (); 1706150622Srik CT_LOCK (bd); 1707150622Srik if (*(int*)data & TIOCM_DTR) ct_set_dtr (c, 1); 1708150622Srik if (*(int*)data & TIOCM_RTS) ct_set_rts (c, 1); 1709150622Srik CT_UNLOCK (bd); 1710150622Srik splx (s); 1711150622Srik return 0; 1712150622Srik 1713150622Srik case TIOCMBIC: /* Clear DTR/RTS */ 1714150622Srik s = splimp (); 1715150622Srik CT_LOCK (bd); 1716150622Srik if (*(int*)data & TIOCM_DTR) ct_set_dtr (c, 0); 1717150622Srik if (*(int*)data & TIOCM_RTS) ct_set_rts (c, 0); 1718150622Srik CT_UNLOCK (bd); 1719150622Srik splx (s); 1720150622Srik return 0; 1721150622Srik 1722150622Srik case TIOCMGET: /* Get modem status */ 1723150622Srik *(int*)data = ct_modem_status (c); 1724150622Srik return 0; 1725150622Srik } 1726150622Srik return ENOTTY; 1727150622Srik} 1728150622Srik 1729126177Srik#ifdef NETGRAPH 1730126177Srikstatic int ng_ct_constructor (node_p node) 1731126177Srik{ 1732126177Srik drv_t *d = NG_NODE_PRIVATE (node); 1733126177Srik CT_DEBUG (d, ("Constructor\n")); 1734126177Srik return EINVAL; 1735126177Srik} 1736126177Srik 1737126177Srikstatic int ng_ct_newhook (node_p node, hook_p hook, const char *name) 1738126177Srik{ 1739126177Srik int s; 1740126177Srik drv_t *d = NG_NODE_PRIVATE (node); 1741126177Srik 1742126177Srik if (!d) 1743126177Srik return EINVAL; 1744126177Srik 1745138823Srik bdrv_t *bd = d->bd; 1746138823Srik 1747126177Srik /* Attach debug hook */ 1748126177Srik if (strcmp (name, NG_CT_HOOK_DEBUG) == 0) { 1749126177Srik NG_HOOK_SET_PRIVATE (hook, NULL); 1750126177Srik d->debug_hook = hook; 1751126177Srik return 0; 1752126177Srik } 1753126177Srik 1754126177Srik /* Check for raw hook */ 1755126177Srik if (strcmp (name, NG_CT_HOOK_RAW) != 0) 1756126177Srik return EINVAL; 1757126177Srik 1758126177Srik NG_HOOK_SET_PRIVATE (hook, d); 1759126177Srik d->hook = hook; 1760126177Srik s = splimp (); 1761138823Srik CT_LOCK (bd); 1762126177Srik ct_up (d); 1763138823Srik CT_UNLOCK (bd); 1764126177Srik splx (s); 1765126177Srik return 0; 1766126177Srik} 1767126177Srik 1768126177Srikstatic char *format_timeslots (u_long s) 1769126177Srik{ 1770126177Srik static char buf [100]; 1771126177Srik char *p = buf; 1772126177Srik int i; 1773126177Srik 1774126177Srik for (i=1; i<32; ++i) 1775126177Srik if ((s >> i) & 1) { 1776126177Srik int prev = (i > 1) & (s >> (i-1)); 1777126177Srik int next = (i < 31) & (s >> (i+1)); 1778126177Srik 1779126177Srik if (prev) { 1780126177Srik if (next) 1781126177Srik continue; 1782126177Srik *p++ = '-'; 1783126177Srik } else if (p > buf) 1784126177Srik *p++ = ','; 1785126177Srik 1786126177Srik if (i >= 10) 1787126177Srik *p++ = '0' + i / 10; 1788126177Srik *p++ = '0' + i % 10; 1789126177Srik } 1790126177Srik *p = 0; 1791126177Srik return buf; 1792126177Srik} 1793126177Srik 1794126177Srikstatic int print_modems (char *s, ct_chan_t *c, int need_header) 1795126177Srik{ 1796126177Srik int status = ct_modem_status (c); 1797126177Srik int length = 0; 1798126177Srik 1799126177Srik if (need_header) 1800126177Srik length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1801126177Srik length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1802126177Srik status & TIOCM_LE ? "On" : "-", 1803126177Srik status & TIOCM_DTR ? "On" : "-", 1804126177Srik status & TIOCM_DSR ? "On" : "-", 1805126177Srik status & TIOCM_RTS ? "On" : "-", 1806126177Srik status & TIOCM_CTS ? "On" : "-", 1807126177Srik status & TIOCM_CD ? "On" : "-"); 1808126177Srik return length; 1809126177Srik} 1810126177Srik 1811126177Srikstatic int print_stats (char *s, ct_chan_t *c, int need_header) 1812126177Srik{ 1813126177Srik struct serial_statistics st; 1814126177Srik int length = 0; 1815126177Srik 1816133645Srik st.rintr = c->rintr; 1817133645Srik st.tintr = c->tintr; 1818133645Srik st.mintr = c->mintr; 1819133645Srik st.ibytes = c->ibytes; 1820133645Srik st.ipkts = c->ipkts; 1821133645Srik st.ierrs = c->ierrs; 1822133645Srik st.obytes = c->obytes; 1823133645Srik st.opkts = c->opkts; 1824133645Srik st.oerrs = c->oerrs; 1825126177Srik if (need_header) 1826126177Srik length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1827126177Srik length += sprintf (s + length, "%7ld %7ld %7ld %8ld %7ld %7ld %8ld %7ld %7ld\n", 1828126177Srik st.rintr, st.tintr, st.mintr, st.ibytes, st.ipkts, 1829126177Srik st.ierrs, st.obytes, st.opkts, st.oerrs); 1830126177Srik return length; 1831126177Srik} 1832126177Srik 1833126177Srikstatic char *format_e1_status (u_char status) 1834126177Srik{ 1835126177Srik static char buf [80]; 1836126177Srik 1837126177Srik if (status & E1_NOALARM) 1838126177Srik return "Ok"; 1839126177Srik buf[0] = 0; 1840126177Srik if (status & E1_LOS) strcat (buf, ",LOS"); 1841126177Srik if (status & E1_AIS) strcat (buf, ",AIS"); 1842126177Srik if (status & E1_LOF) strcat (buf, ",LOF"); 1843126177Srik if (status & E1_LOMF) strcat (buf, ",LOMF"); 1844126177Srik if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1845126177Srik if (status & E1_AIS16) strcat (buf, ",AIS16"); 1846126177Srik if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1847126177Srik if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1848126177Srik if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1849126177Srik if (buf[0] == ',') 1850126177Srik return buf+1; 1851126177Srik return "Unknown"; 1852126177Srik} 1853126177Srik 1854126177Srikstatic int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1855126177Srik{ 1856126177Srik int n, length = 0; 1857126177Srik 1858126177Srik if (numerator < 1 || divider < 1) { 1859126177Srik length += sprintf (s+length, leftalign ? "/- " : " -"); 1860126177Srik return length; 1861126177Srik } 1862126177Srik n = (int) (0.5 + 1000.0 * numerator / divider); 1863126177Srik if (n < 1000) { 1864126177Srik length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1865126177Srik return length; 1866126177Srik } 1867126177Srik *(s + length) = leftalign ? '/' : ' '; 1868126177Srik length ++; 1869126177Srik 1870133645Srik if (n >= 1000000) n = (n+500) / 1000 * 1000; 1871126177Srik else if (n >= 100000) n = (n+50) / 100 * 100; 1872126177Srik else if (n >= 10000) n = (n+5) / 10 * 10; 1873126177Srik 1874126177Srik switch (n) { 1875126177Srik case 1000: length += printf (s+length, ".999"); return length; 1876126177Srik case 10000: n = 9990; break; 1877126177Srik case 100000: n = 99900; break; 1878126177Srik case 1000000: n = 999000; break; 1879126177Srik } 1880133645Srik if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1881126177Srik else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1882126177Srik else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1883133645Srik else length += sprintf (s+length, "%d", n/1000); 1884126177Srik 1885126177Srik return length; 1886126177Srik} 1887126177Srik 1888126177Srikstatic int print_e1_stats (char *s, ct_chan_t *c) 1889126177Srik{ 1890126177Srik struct e1_counters total; 1891126177Srik u_long totsec; 1892126177Srik int length = 0; 1893126177Srik 1894126177Srik totsec = c->totsec + c->cursec; 1895126177Srik total.bpv = c->total.bpv + c->currnt.bpv; 1896126177Srik total.fse = c->total.fse + c->currnt.fse; 1897126177Srik total.crce = c->total.crce + c->currnt.crce; 1898126177Srik total.rcrce = c->total.rcrce + c->currnt.rcrce; 1899126177Srik total.uas = c->total.uas + c->currnt.uas; 1900126177Srik total.les = c->total.les + c->currnt.les; 1901126177Srik total.es = c->total.es + c->currnt.es; 1902126177Srik total.bes = c->total.bes + c->currnt.bes; 1903126177Srik total.ses = c->total.ses + c->currnt.ses; 1904126177Srik total.oofs = c->total.oofs + c->currnt.oofs; 1905126177Srik total.css = c->total.css + c->currnt.css; 1906126177Srik total.dm = c->total.dm + c->currnt.dm; 1907126177Srik 1908126177Srik length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1909126177Srik 1910126177Srik /* Unavailable seconds, degraded minutes */ 1911126177Srik length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1912126177Srik length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1913126177Srik 1914126177Srik /* Bipolar violations, frame sync errors */ 1915126177Srik length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 1916126177Srik length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 1917126177Srik 1918126177Srik /* CRC errors, remote CRC errors (E-bit) */ 1919126177Srik length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 1920126177Srik length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 1921126177Srik 1922126177Srik /* Errored seconds, line errored seconds */ 1923126177Srik length += print_frac (s + length, 0, c->currnt.es, c->cursec); 1924126177Srik length += print_frac (s + length, 1, c->currnt.les, c->cursec); 1925126177Srik 1926126177Srik /* Severely errored seconds, burst errored seconds */ 1927126177Srik length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 1928126177Srik length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 1929126177Srik 1930126177Srik /* Out of frame seconds, controlled slip seconds */ 1931126177Srik length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 1932126177Srik length += print_frac (s + length, 1, c->currnt.css, c->cursec); 1933126177Srik 1934126177Srik length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 1935126177Srik 1936126177Srik /* Print total statistics. */ 1937126177Srik length += print_frac (s + length, 0, total.uas, totsec); 1938126177Srik length += print_frac (s + length, 1, 60 * total.dm, totsec); 1939126177Srik 1940126177Srik length += print_frac (s + length, 0, total.bpv, totsec); 1941126177Srik length += print_frac (s + length, 1, total.fse, totsec); 1942126177Srik 1943126177Srik length += print_frac (s + length, 0, total.crce, totsec); 1944126177Srik length += print_frac (s + length, 1, total.rcrce, totsec); 1945126177Srik 1946126177Srik length += print_frac (s + length, 0, total.es, totsec); 1947126177Srik length += print_frac (s + length, 1, total.les, totsec); 1948126177Srik 1949126177Srik length += print_frac (s + length, 0, total.ses, totsec); 1950126177Srik length += print_frac (s + length, 1, total.bes, totsec); 1951126177Srik 1952126177Srik length += print_frac (s + length, 0, total.oofs, totsec); 1953126177Srik length += print_frac (s + length, 1, total.css, totsec); 1954126177Srik 1955126177Srik length += sprintf (s + length, " -- Total\n"); 1956126177Srik return length; 1957126177Srik} 1958126177Srik 1959126177Srikstatic int print_chan (char *s, ct_chan_t *c) 1960126177Srik{ 1961126177Srik drv_t *d = c->sys; 1962138823Srik bdrv_t *bd = d->bd; 1963126177Srik int length = 0; 1964126177Srik 1965126177Srik length += sprintf (s + length, "ct%d", c->board->num * NCHAN + c->num); 1966126177Srik if (d->chan->debug) 1967126177Srik length += sprintf (s + length, " debug=%d", d->chan->debug); 1968126177Srik 1969126177Srik switch (ct_get_config (c->board)) { 1970126177Srik case CFG_A: length += sprintf (s + length, " cfg=A"); break; 1971126177Srik case CFG_B: length += sprintf (s + length, " cfg=B"); break; 1972126177Srik case CFG_C: length += sprintf (s + length, " cfg=C"); break; 1973126177Srik default: length += sprintf (s + length, " cfg=unknown"); break; 1974126177Srik } 1975126177Srik 1976126177Srik if (ct_get_baud (c)) 1977126177Srik length += sprintf (s + length, " %ld", ct_get_baud (c)); 1978126177Srik else 1979126177Srik length += sprintf (s + length, " extclock"); 1980126177Srik 1981126177Srik if (c->mode == M_E1 || c->mode == M_G703) 1982126177Srik switch (ct_get_clk(c)) { 1983126177Srik case GCLK_INT : length += sprintf (s + length, " syn=int"); break; 1984126177Srik case GCLK_RCV : length += sprintf (s + length, " syn=rcv"); break; 1985126177Srik case GCLK_RCLKO : length += sprintf (s + length, " syn=xrcv"); break; 1986126177Srik } 1987126177Srik if (c->mode == M_HDLC) { 1988126177Srik length += sprintf (s + length, " dpll=%s", ct_get_dpll (c) ? "on" : "off"); 1989126177Srik length += sprintf (s + length, " nrzi=%s", ct_get_nrzi (c) ? "on" : "off"); 1990126177Srik length += sprintf (s + length, " invtclk=%s", ct_get_invtxc (c) ? "on" : "off"); 1991126177Srik length += sprintf (s + length, " invrclk=%s", ct_get_invrxc (c) ? "on" : "off"); 1992126177Srik } 1993126177Srik if (c->mode == M_E1) 1994126177Srik length += sprintf (s + length, " higain=%s", ct_get_higain (c)? "on" : "off"); 1995126177Srik 1996126177Srik length += sprintf (s + length, " loop=%s", ct_get_loop (c) ? "on" : "off"); 1997126177Srik 1998126177Srik if (c->mode == M_E1) 1999126177Srik length += sprintf (s + length, " ts=%s", format_timeslots (ct_get_ts(c))); 2000126177Srik if (c->mode == M_E1 && ct_get_config (c->board) != CFG_A) 2001126177Srik length += sprintf (s + length, " pass=%s", format_timeslots (ct_get_subchan(c->board))); 2002126177Srik if (c->mode == M_G703) { 2003126177Srik int lq, x; 2004126177Srik 2005126177Srik x = splimp (); 2006138823Srik CT_LOCK (bd); 2007126177Srik lq = ct_get_lq (c); 2008138823Srik CT_UNLOCK (bd); 2009126177Srik splx (x); 2010126177Srik length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2011126177Srik } 2012126177Srik length += sprintf (s + length, "\n"); 2013126177Srik return length; 2014126177Srik} 2015126177Srik 2016126177Srikstatic int ng_ct_rcvmsg (node_p node, item_p item, hook_p lasthook) 2017126177Srik{ 2018126177Srik drv_t *d = NG_NODE_PRIVATE (node); 2019126177Srik struct ng_mesg *msg; 2020126177Srik struct ng_mesg *resp = NULL; 2021126177Srik int error = 0; 2022126177Srik 2023126177Srik if (!d) 2024126177Srik return EINVAL; 2025126177Srik 2026126177Srik CT_DEBUG (d, ("Rcvmsg\n")); 2027126177Srik NGI_GET_MSG (item, msg); 2028126177Srik switch (msg->header.typecookie) { 2029126177Srik default: 2030126177Srik error = EINVAL; 2031126177Srik break; 2032126177Srik 2033126177Srik case NGM_CT_COOKIE: 2034126177Srik printf ("Don't forget to implement\n"); 2035126177Srik error = EINVAL; 2036126177Srik break; 2037126177Srik 2038126177Srik case NGM_GENERIC_COOKIE: 2039126177Srik switch (msg->header.cmd) { 2040126177Srik default: 2041126177Srik error = EINVAL; 2042126177Srik break; 2043126177Srik 2044126177Srik case NGM_TEXT_STATUS: { 2045126177Srik char *s; 2046126177Srik int l = 0; 2047126177Srik int dl = sizeof (struct ng_mesg) + 730; 2048126177Srik 2049126177Srik NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2050126177Srik if (! resp) { 2051126177Srik error = ENOMEM; 2052126177Srik break; 2053126177Srik } 2054126177Srik s = (resp)->data; 2055126177Srik l += print_chan (s + l, d->chan); 2056126177Srik l += print_stats (s + l, d->chan, 1); 2057126177Srik l += print_modems (s + l, d->chan, 1); 2058126177Srik l += print_e1_stats (s + l, d->chan); 2059193813Simp strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRSIZ); 2060126177Srik } 2061126177Srik break; 2062126177Srik } 2063126177Srik break; 2064126177Srik } 2065126177Srik NG_RESPOND_MSG (error, node, item, resp); 2066126177Srik NG_FREE_MSG (msg); 2067126177Srik return error; 2068126177Srik} 2069126177Srik 2070126177Srikstatic int ng_ct_rcvdata (hook_p hook, item_p item) 2071126177Srik{ 2072126177Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2073126177Srik struct mbuf *m; 2074131108Sjulian struct ng_tag_prio *ptag; 2075138823Srik bdrv_t *bd; 2076126177Srik struct ifqueue *q; 2077126177Srik int s; 2078126177Srik 2079126177Srik if (!d) 2080126177Srik return ENETDOWN; 2081126177Srik 2082138823Srik bd = d->bd; 2083126177Srik NGI_GET_M (item, m); 2084126177Srik NG_FREE_ITEM (item); 2085126177Srik if (! NG_HOOK_PRIVATE (hook) || ! d) { 2086126177Srik NG_FREE_M (m); 2087126177Srik return ENETDOWN; 2088126177Srik } 2089131108Sjulian 2090131108Sjulian /* Check for high priority data */ 2091131108Sjulian if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2092131108Sjulian NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2093131108Sjulian q = &d->hi_queue; 2094131108Sjulian else 2095131108Sjulian q = &d->queue; 2096131108Sjulian 2097126177Srik s = splimp (); 2098138823Srik CT_LOCK (bd); 2099126177Srik IF_LOCK (q); 2100126177Srik if (_IF_QFULL (q)) { 2101126177Srik _IF_DROP (q); 2102126177Srik IF_UNLOCK (q); 2103138823Srik CT_UNLOCK (bd); 2104126177Srik splx (s); 2105126177Srik NG_FREE_M (m); 2106126177Srik return ENOBUFS; 2107126177Srik } 2108126177Srik _IF_ENQUEUE (q, m); 2109126177Srik IF_UNLOCK (q); 2110126177Srik ct_start (d); 2111138823Srik CT_UNLOCK (bd); 2112126177Srik splx (s); 2113126177Srik return 0; 2114126177Srik} 2115126177Srik 2116126177Srikstatic int ng_ct_rmnode (node_p node) 2117126177Srik{ 2118126177Srik drv_t *d = NG_NODE_PRIVATE (node); 2119138823Srik bdrv_t *bd; 2120126177Srik 2121126177Srik CT_DEBUG (d, ("Rmnode\n")); 2122126177Srik if (d && d->running) { 2123138823Srik bd = d->bd; 2124126177Srik int s = splimp (); 2125138823Srik CT_LOCK (bd); 2126126177Srik ct_down (d); 2127138823Srik CT_UNLOCK (bd); 2128126177Srik splx (s); 2129126177Srik } 2130126177Srik#ifdef KLD_MODULE 2131132464Sjulian if (node->nd_flags & NGF_REALLY_DIE) { 2132126177Srik NG_NODE_SET_PRIVATE (node, NULL); 2133126177Srik NG_NODE_UNREF (node); 2134126177Srik } 2135132464Sjulian NG_NODE_REVIVE(node); /* Persistant node */ 2136126177Srik#endif 2137126177Srik return 0; 2138126177Srik} 2139126177Srik 2140126177Srikstatic int ng_ct_connect (hook_p hook) 2141126177Srik{ 2142126177Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2143126177Srik 2144126177Srik if (!d) 2145126177Srik return 0; 2146126177Srik 2147199407Sjhb callout_reset (&d->timeout_handle, hz, ct_watchdog_timer, d); 2148126177Srik return 0; 2149126177Srik} 2150126177Srik 2151126177Srikstatic int ng_ct_disconnect (hook_p hook) 2152126177Srik{ 2153126177Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2154138823Srik bdrv_t *bd; 2155138823Srik 2156126177Srik if (!d) 2157126177Srik return 0; 2158138823Srik 2159138823Srik bd = d->bd; 2160138823Srik 2161138823Srik CT_LOCK (bd); 2162126177Srik if (NG_HOOK_PRIVATE (hook)) 2163126177Srik ct_down (d); 2164138823Srik CT_UNLOCK (bd); 2165138823Srik /* If we were wait it than it reasserted now, just stop it. */ 2166138823Srik if (!callout_drain (&d->timeout_handle)) 2167138823Srik callout_stop (&d->timeout_handle); 2168126177Srik return 0; 2169126177Srik} 2170126177Srik#endif 2171126177Srik 2172126177Srikstatic int ct_modevent (module_t mod, int type, void *unused) 2173126177Srik{ 2174126177Srik static int load_count = 0; 2175126177Srik 2176126177Srik switch (type) { 2177126177Srik case MOD_LOAD: 2178138651Srik#ifdef NETGRAPH 2179126177Srik if (ng_newtype (&typestruct)) 2180126177Srik printf ("Failed to register ng_ct\n"); 2181126177Srik#endif 2182126177Srik ++load_count; 2183188662Srwatson callout_init (&timeout_handle, CALLOUT_MPSAFE); 2184138823Srik callout_reset (&timeout_handle, hz*5, ct_timeout, 0); 2185126177Srik break; 2186126177Srik case MOD_UNLOAD: 2187126177Srik if (load_count == 1) { 2188126177Srik printf ("Removing device entry for Tau-ISA\n"); 2189138651Srik#ifdef NETGRAPH 2190126177Srik ng_rmtype (&typestruct); 2191126177Srik#endif 2192126177Srik } 2193138823Srik /* If we were wait it than it reasserted now, just stop it. */ 2194138823Srik if (!callout_drain (&timeout_handle)) 2195138823Srik callout_stop (&timeout_handle); 2196126177Srik --load_count; 2197126177Srik break; 2198126177Srik case MOD_SHUTDOWN: 2199126177Srik break; 2200126177Srik } 2201126177Srik return 0; 2202126177Srik} 2203126177Srik 2204126177Srik#ifdef NETGRAPH 2205126177Srikstatic struct ng_type typestruct = { 2206129837Srik .version = NG_ABI_VERSION, 2207129837Srik .name = NG_CT_NODE_TYPE, 2208129837Srik .constructor = ng_ct_constructor, 2209129837Srik .rcvmsg = ng_ct_rcvmsg, 2210129837Srik .shutdown = ng_ct_rmnode, 2211129837Srik .newhook = ng_ct_newhook, 2212129837Srik .connect = ng_ct_connect, 2213129837Srik .rcvdata = ng_ct_rcvdata, 2214130985Srik .disconnect = ng_ct_disconnect, 2215126177Srik}; 2216126177Srik#endif /*NETGRAPH*/ 2217126177Srik 2218126177Srik#ifdef NETGRAPH 2219126177SrikMODULE_DEPEND (ng_ct, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2220126177Srik#else 2221126177SrikMODULE_DEPEND (ct, sppp, 1, 1, 1); 2222126177Srik#endif 2223126177SrikDRIVER_MODULE (ct, isa, ct_isa_driver, ct_devclass, ct_modevent, NULL); 2224138823SrikMODULE_VERSION (ct, 1); 2225