if_ce.c revision 243857
1154899Srik/* 2154899Srik * Cronyx-Tau32-PCI adapter driver for FreeBSD. 3154899Srik * 4154899Srik * Copyright (C) 2003-2005 Cronyx Engineering. 5154899Srik * Copyright (C) 2003-2005 Kurakin Roman, <rik@FreeBSD.org> 6154899Srik * 7154899Srik * This software is distributed with NO WARRANTIES, not even the implied 8154899Srik * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9154899Srik * 10154899Srik * Authors grant any other persons or organisations a permission to use, 11154899Srik * modify and redistribute this software in source and binary forms, 12154899Srik * as long as this message is kept with the software, all derivative 13154899Srik * works or modified versions. 14154899Srik * 15154899Srik * $Cronyx: if_ce.c,v 1.9.2.8 2005/11/21 14:17:44 rik Exp $ 16154899Srik */ 17154899Srik 18154899Srik#include <sys/cdefs.h> 19154899Srik__FBSDID("$FreeBSD: head/sys/dev/ce/if_ce.c 243857 2012-12-04 09:32:43Z glebius $"); 20154899Srik 21154899Srik#include <sys/param.h> 22154899Srik 23154899Srik#if __FreeBSD_version >= 500000 24154899Srik# define NPCI 1 25154899Srik#else 26154899Srik# include "pci.h" 27154899Srik#endif 28154899Srik 29154899Srik#if NPCI > 0 30154899Srik 31154899Srik#include <sys/ucred.h> 32164033Srwatson#include <sys/priv.h> 33154899Srik#include <sys/proc.h> 34154899Srik#include <sys/systm.h> 35154899Srik#include <sys/mbuf.h> 36154899Srik#include <sys/kernel.h> 37154899Srik#include <sys/module.h> 38154899Srik#include <sys/conf.h> 39154899Srik#include <sys/malloc.h> 40154899Srik#include <sys/socket.h> 41154899Srik#include <sys/sockio.h> 42154899Srik#if __FreeBSD_version >= 504000 43154899Srik#include <sys/sysctl.h> 44154899Srik#endif 45154899Srik#include <sys/tty.h> 46154899Srik#include <sys/bus.h> 47154899Srik#include <vm/vm.h> 48154899Srik#include <vm/pmap.h> 49154899Srik#include <net/if.h> 50154899Srik#if __FreeBSD_version > 501000 51154899Srik# include <dev/pci/pcivar.h> 52154899Srik# include <dev/pci/pcireg.h> 53154899Srik#else 54154899Srik# include <pci/pcivar.h> 55154899Srik# include <pci/pcireg.h> 56154899Srik#endif 57154899Srik#include <machine/bus.h> 58154899Srik#include <sys/rman.h> 59154899Srik#include "opt_ng_cronyx.h" 60154899Srik#ifdef NETGRAPH_CRONYX 61154899Srik# include "opt_netgraph.h" 62154899Srik# ifndef NETGRAPH 63154899Srik# error #option NETGRAPH missed from configuration 64154899Srik# endif 65154899Srik# include <netgraph/ng_message.h> 66154899Srik# include <netgraph/netgraph.h> 67154899Srik# include <dev/ce/ng_ce.h> 68154899Srik#else 69154899Srik# include <net/if_types.h> 70154899Srik# include <net/if_sppp.h> 71154899Srik# define PP_CISCO IFF_LINK2 72154899Srik# include <net/bpf.h> 73154899Srik#endif 74154899Srik#include <dev/cx/machdep.h> 75154899Srik#include <dev/ce/ceddk.h> 76154899Srik#include <machine/cserial.h> 77154899Srik#include <machine/resource.h> 78154899Srik#include <machine/pmap.h> 79154899Srik 80154899Srik/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 81154899Srik#ifndef PP_FR 82154899Srik#define PP_FR 0 83154899Srik#endif 84154899Srik 85154899Srik#ifndef IFP2SP 86154899Srik#define IFP2SP(ifp) ((struct sppp*)ifp) 87154899Srik#endif 88154899Srik#ifndef SP2IFP 89154899Srik#define SP2IFP(sp) ((struct ifnet*)sp) 90154899Srik#endif 91154899Srik 92154899Srik#ifndef PCIR_BAR 93154899Srik#define PCIR_BAR(x) (PCIR_MAPS + (x) * 4) 94154899Srik#endif 95154899Srik 96154899Srik/* define as our previous return value */ 97154899Srik#ifndef BUS_PROBE_DEFAULT 98154899Srik#define BUS_PROBE_DEFAULT 0 99154899Srik#endif 100154899Srik 101154899Srik#define CE_DEBUG(d,s) ({if (d->chan->debug) {\ 102154899Srik printf ("%s: ", d->name); printf s;}}) 103154899Srik#define CE_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 104154899Srik printf ("%s: ", d->name); printf s;}}) 105154899Srik 106154899Srik#ifndef CALLOUT_MPSAFE 107154899Srik#define CALLOUT_MPSAFE 0 108154899Srik#endif 109154899Srik 110154899Srik#ifndef IF_DRAIN 111154899Srik#define IF_DRAIN(ifq) do { \ 112154899Srik struct mbuf *m; \ 113154899Srik for (;;) { \ 114154899Srik IF_DEQUEUE(ifq, m); \ 115154899Srik if (m == NULL) \ 116154899Srik break; \ 117154899Srik m_freem(m); \ 118154899Srik } \ 119154899Srik} while (0) 120154899Srik#endif 121154899Srik 122154899Srik#ifndef _IF_QLEN 123154899Srik#define _IF_QLEN(ifq) ((ifq)->ifq_len) 124154899Srik#endif 125154899Srik 126154899Srik#ifndef callout_drain 127154899Srik#define callout_drain callout_stop 128154899Srik#endif 129154899Srik 130154899Srik#define CE_LOCK_NAME "ceX" 131154899Srik 132188663Srwatson#define CE_LOCK(_bd) mtx_lock (&(_bd)->ce_mtx) 133188663Srwatson#define CE_UNLOCK(_bd) mtx_unlock (&(_bd)->ce_mtx) 134188663Srwatson#define CE_LOCK_ASSERT(_bd) mtx_assert (&(_bd)->ce_mtx, MA_OWNED) 135154899Srik 136154899Srik#define CDEV_MAJOR 185 137154899Srik 138154899Srikstatic int ce_probe __P((device_t)); 139154899Srikstatic int ce_attach __P((device_t)); 140154899Srikstatic int ce_detach __P((device_t)); 141154899Srik 142154899Srikstatic device_method_t ce_methods[] = { 143154899Srik /* Device interface */ 144154899Srik DEVMETHOD(device_probe, ce_probe), 145154899Srik DEVMETHOD(device_attach, ce_attach), 146154899Srik DEVMETHOD(device_detach, ce_detach), 147154899Srik 148154899Srik {0, 0} 149154899Srik}; 150154899Srik 151154899Sriktypedef struct _ce_dma_mem_t { 152154899Srik unsigned long phys; 153154899Srik void *virt; 154154899Srik size_t size; 155154899Srik#if __FreeBSD_version >= 500000 156154899Srik bus_dma_tag_t dmat; 157154899Srik bus_dmamap_t mapp; 158154899Srik#endif 159154899Srik} ce_dma_mem_t; 160154899Srik 161154899Sriktypedef struct _drv_t { 162154899Srik char name [8]; 163154899Srik int running; 164154899Srik ce_board_t *board; 165154899Srik ce_chan_t *chan; 166154899Srik struct ifqueue rqueue; 167154899Srik#ifdef NETGRAPH 168193813Simp char nodename [NG_NODESIZE]; 169154899Srik hook_p hook; 170154899Srik hook_p debug_hook; 171154899Srik node_p node; 172154899Srik struct ifqueue queue; 173154899Srik struct ifqueue hi_queue; 174154899Srik#else 175154899Srik struct ifnet *ifp; 176154899Srik#endif 177199407Sjhb short timeout; 178199407Sjhb struct callout timeout_handle; 179154899Srik#if __FreeBSD_version >= 500000 180154899Srik struct cdev *devt; 181154899Srik#else /* __FreeBSD_version < 500000 */ 182154899Srik dev_t devt; 183154899Srik#endif 184154899Srik ce_dma_mem_t dmamem; 185154899Srik} drv_t; 186154899Srik 187154899Sriktypedef struct _bdrv_t { 188154899Srik ce_board_t *board; 189154899Srik struct resource *ce_res; 190154899Srik struct resource *ce_irq; 191154899Srik void *ce_intrhand; 192154899Srik ce_dma_mem_t dmamem; 193154899Srik drv_t channel [NCHAN]; 194154899Srik#if __FreeBSD_version >= 504000 195154899Srik struct mtx ce_mtx; 196154899Srik#endif 197154899Srik} bdrv_t; 198154899Srik 199154899Srikstatic driver_t ce_driver = { 200154899Srik "ce", 201154899Srik ce_methods, 202154899Srik sizeof(bdrv_t), 203154899Srik}; 204154899Srik 205154899Srikstatic devclass_t ce_devclass; 206154899Srik 207154899Srikstatic void ce_receive (ce_chan_t *c, unsigned char *data, int len); 208154899Srikstatic void ce_transmit (ce_chan_t *c, void *attachment, int len); 209154899Srikstatic void ce_error (ce_chan_t *c, int data); 210154899Srikstatic void ce_up (drv_t *d); 211154899Srikstatic void ce_start (drv_t *d); 212154899Srikstatic void ce_down (drv_t *d); 213154899Srikstatic void ce_watchdog (drv_t *d); 214199407Sjhbstatic void ce_watchdog_timer (void *arg); 215154899Srik#ifdef NETGRAPH 216154899Srikextern struct ng_type typestruct; 217154899Srik#else 218154899Srikstatic void ce_ifstart (struct ifnet *ifp); 219154899Srikstatic void ce_tlf (struct sppp *sp); 220154899Srikstatic void ce_tls (struct sppp *sp); 221154899Srikstatic int ce_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 222154899Srikstatic void ce_initialize (void *softc); 223154899Srik#endif 224154899Srik 225154899Srikstatic ce_board_t *adapter [NBRD]; 226154899Srikstatic drv_t *channel [NBRD*NCHAN]; 227154899Srikstatic struct callout led_timo [NBRD]; 228154899Srikstatic struct callout timeout_handle; 229154899Srik 230154899Srikstatic int ce_destroy = 0; 231154899Srik 232155065Srik#if __FreeBSD_version < 500000 233155065Srikstatic int ce_open (dev_t dev, int oflags, int devtype, struct proc *p); 234155065Srikstatic int ce_close (dev_t dev, int fflag, int devtype, struct proc *p); 235155065Srikstatic int ce_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p); 236155065Srik#else 237155065Srikstatic int ce_open (struct cdev *dev, int oflags, int devtype, struct thread *td); 238155065Srikstatic int ce_close (struct cdev *dev, int fflag, int devtype, struct thread *td); 239155065Srikstatic int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td); 240155065Srik#endif 241155065Srik#if __FreeBSD_version < 500000 242155065Srikstatic struct cdevsw ce_cdevsw = { 243155065Srik ce_open, ce_close, noread, nowrite, 244155065Srik ce_ioctl, nopoll, nommap, nostrategy, 245155065Srik "ce", CDEV_MAJOR, nodump, nopsize, 246155065Srik D_NAGGED, -1 247155065Srik }; 248155065Srik#elif __FreeBSD_version == 500000 249155065Srikstatic struct cdevsw ce_cdevsw = { 250155065Srik ce_open, ce_close, noread, nowrite, 251155065Srik ce_ioctl, nopoll, nommap, nostrategy, 252155065Srik "ce", CDEV_MAJOR, nodump, nopsize, 253155065Srik D_NAGGED, 254155065Srik }; 255155065Srik#elif __FreeBSD_version <= 501000 256155065Srikstatic struct cdevsw ce_cdevsw = { 257155065Srik .d_open = ce_open, 258155065Srik .d_close = ce_close, 259155065Srik .d_read = noread, 260155065Srik .d_write = nowrite, 261155065Srik .d_ioctl = ce_ioctl, 262155065Srik .d_poll = nopoll, 263155065Srik .d_mmap = nommap, 264155065Srik .d_strategy = nostrategy, 265155065Srik .d_name = "ce", 266155065Srik .d_maj = CDEV_MAJOR, 267155065Srik .d_dump = nodump, 268155065Srik .d_flags = D_NAGGED, 269155065Srik}; 270155065Srik#elif __FreeBSD_version < 502103 271155065Srikstatic struct cdevsw ce_cdevsw = { 272155065Srik .d_open = ce_open, 273155065Srik .d_close = ce_close, 274155065Srik .d_ioctl = ce_ioctl, 275155065Srik .d_name = "ce", 276155065Srik .d_maj = CDEV_MAJOR, 277155065Srik .d_flags = D_NAGGED, 278155065Srik}; 279155065Srik#elif __FreeBSD_version < 600000 280155065Srikstatic struct cdevsw ce_cdevsw = { 281155065Srik .d_version = D_VERSION, 282155065Srik .d_open = ce_open, 283155065Srik .d_close = ce_close, 284155065Srik .d_ioctl = ce_ioctl, 285155065Srik .d_name = "ce", 286155065Srik .d_maj = CDEV_MAJOR, 287155065Srik .d_flags = D_NEEDGIANT, 288155065Srik}; 289155065Srik#else /* __FreeBSD_version >= 600000 */ 290155065Srikstatic struct cdevsw ce_cdevsw = { 291155065Srik .d_version = D_VERSION, 292155065Srik .d_open = ce_open, 293155065Srik .d_close = ce_close, 294155065Srik .d_ioctl = ce_ioctl, 295155065Srik .d_name = "ce", 296155065Srik}; 297155065Srik#endif 298155065Srik 299154899Srik/* 300154899Srik * Print the mbuf chain, for debug purposes only. 301154899Srik */ 302154899Srikstatic void printmbuf (struct mbuf *m) 303154899Srik{ 304154899Srik printf ("mbuf:"); 305154899Srik for (; m; m=m->m_next) { 306154899Srik if (m->m_flags & M_PKTHDR) 307154899Srik printf (" HDR %d:", m->m_pkthdr.len); 308154899Srik if (m->m_flags & M_EXT) 309154899Srik printf (" EXT:"); 310154899Srik printf (" %d", m->m_len); 311154899Srik } 312154899Srik printf ("\n"); 313154899Srik} 314154899Srik 315154899Srik/* 316154899Srik * Make an mbuf from data. 317154899Srik */ 318154899Srikstatic struct mbuf *makembuf (void *buf, unsigned len) 319154899Srik{ 320154899Srik struct mbuf *m; 321154899Srik 322243857Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 323154899Srik if (! m) 324154899Srik return 0; 325243857Sglebius MCLGET (m, M_NOWAIT); 326154899Srik if (! (m->m_flags & M_EXT)) { 327154899Srik m_freem (m); 328154899Srik return 0; 329154899Srik } 330154899Srik m->m_pkthdr.len = m->m_len = len; 331154899Srik bcopy (buf, mtod (m, caddr_t), len); 332154899Srik return m; 333154899Srik} 334154899Srik 335154899Srikstatic int ce_probe (device_t dev) 336154899Srik{ 337154899Srik if ((pci_get_vendor (dev) == TAU32_PCI_VENDOR_ID) && 338154899Srik (pci_get_device (dev) == TAU32_PCI_DEVICE_ID)) { 339154899Srik device_set_desc (dev, "Cronyx-Tau32-PCI serial adapter"); 340154899Srik return BUS_PROBE_DEFAULT; 341154899Srik } 342154899Srik return ENXIO; 343154899Srik} 344154899Srik 345154899Srikstatic void ce_timeout (void *arg) 346154899Srik{ 347154899Srik drv_t *d; 348154899Srik int s, i, k; 349154899Srik 350154899Srik for (i = 0; i < NBRD; ++i) { 351154899Srik if (adapter[i] == NULL) 352154899Srik continue; 353154899Srik for (k = 0; k < NCHAN; ++k) { 354154899Srik s = splimp (); 355154899Srik if (ce_destroy) { 356154899Srik splx (s); 357154899Srik return; 358154899Srik } 359154899Srik d = channel[i * NCHAN + k]; 360154899Srik if (!d) { 361154899Srik splx (s); 362154899Srik continue; 363154899Srik } 364154899Srik CE_LOCK ((bdrv_t *)d->board->sys); 365154899Srik switch (d->chan->type) { 366154899Srik case T_E1: 367154899Srik ce_e1_timer (d->chan); 368154899Srik break; 369154899Srik default: 370154899Srik break; 371154899Srik } 372154899Srik CE_UNLOCK ((bdrv_t *)d->board->sys); 373154899Srik splx (s); 374154899Srik } 375154899Srik } 376154899Srik s = splimp (); 377154899Srik if (!ce_destroy) 378154899Srik callout_reset (&timeout_handle, hz, ce_timeout, 0); 379154899Srik splx (s); 380154899Srik} 381154899Srik 382154899Srikstatic void ce_led_off (void *arg) 383154899Srik{ 384154899Srik ce_board_t *b = arg; 385154899Srik bdrv_t *bd = (bdrv_t *) b->sys; 386154899Srik int s; 387154899Srik s = splimp (); 388154899Srik if (ce_destroy) { 389154899Srik splx (s); 390154899Srik return; 391154899Srik } 392154899Srik CE_LOCK (bd); 393154899Srik TAU32_LedSet (b->ddk.pControllerObject, 0); 394154899Srik CE_UNLOCK (bd); 395154899Srik splx (s); 396154899Srik} 397154899Srik 398154899Srikstatic void ce_intr (void *arg) 399154899Srik{ 400154899Srik bdrv_t *bd = arg; 401154899Srik ce_board_t *b = bd->board; 402154899Srik int s; 403154899Srik int i; 404154899Srik#if __FreeBSD_version >= 500000 && defined NETGRAPH 405154899Srik int error; 406154899Srik#endif 407154899Srik s = splimp (); 408154899Srik if (ce_destroy) { 409154899Srik splx (s); 410154899Srik return; 411154899Srik } 412154899Srik CE_LOCK (bd); 413154899Srik /* Turn LED on. */ 414154899Srik TAU32_LedSet (b->ddk.pControllerObject, 1); 415154899Srik 416154899Srik TAU32_HandleInterrupt (b->ddk.pControllerObject); 417154899Srik 418154899Srik /* Turn LED off 50 msec later. */ 419154899Srik callout_reset (&led_timo[b->num], hz/20, ce_led_off, b); 420154899Srik CE_UNLOCK (bd); 421154899Srik splx (s); 422154899Srik 423154899Srik /* Pass packets in a lock-free state */ 424154899Srik for (i = 0; i < NCHAN && b->chan[i].type; i++) { 425154899Srik drv_t *d = b->chan[i].sys; 426154899Srik struct mbuf *m; 427154899Srik if (!d || !d->running) 428154899Srik continue; 429154899Srik while (_IF_QLEN(&d->rqueue)) { 430154899Srik IF_DEQUEUE (&d->rqueue,m); 431154899Srik if (!m) 432154899Srik continue; 433154899Srik#ifdef NETGRAPH 434154899Srik if (d->hook) { 435154899Srik#if __FreeBSD_version >= 500000 436154899Srik NG_SEND_DATA_ONLY (error, d->hook, m); 437154899Srik#else 438154899Srik ng_queue_data (d->hook, m, 0); 439154899Srik#endif 440154899Srik } else { 441154899Srik IF_DRAIN (&d->rqueue); 442154899Srik } 443154899Srik#else 444154899Srik sppp_input (d->ifp, m); 445154899Srik#endif 446154899Srik } 447154899Srik } 448154899Srik} 449154899Srik 450154899Srik#if __FreeBSD_version >= 500000 451154899Srikstatic void 452154899Srikce_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 453154899Srik{ 454154899Srik unsigned long *addr; 455154899Srik 456154899Srik if (error) 457154899Srik return; 458154899Srik 459154899Srik KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 460154899Srik addr = arg; 461154899Srik *addr = segs->ds_addr; 462154899Srik} 463154899Srik 464154899Srik#ifndef BUS_DMA_ZERO 465154899Srik#define BUS_DMA_ZERO 0 466154899Srik#endif 467154899Srik 468154899Srikstatic int 469154899Srikce_bus_dma_mem_alloc (int bnum, int cnum, ce_dma_mem_t *dmem) 470154899Srik{ 471154899Srik int error; 472154899Srik 473154899Srik error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 474154899Srik BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 475154899Srik dmem->size, 0, 476154899Srik#if __FreeBSD_version >= 502000 477154899Srik NULL, NULL, 478154899Srik#endif 479154899Srik &dmem->dmat); 480154899Srik if (error) { 481154899Srik if (cnum >= 0) printf ("ce%d-%d: ", bnum, cnum); 482154899Srik else printf ("ce%d: ", bnum); 483154899Srik printf ("couldn't allocate tag for dma memory\n"); 484154899Srik return 0; 485154899Srik } 486154899Srik error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 487154899Srik BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 488154899Srik if (error) { 489154899Srik if (cnum >= 0) printf ("ce%d-%d: ", bnum, cnum); 490154899Srik else printf ("ce%d: ", bnum); 491154899Srik printf ("couldn't allocate mem for dma memory\n"); 492154899Srik bus_dma_tag_destroy (dmem->dmat); 493154899Srik return 0; 494154899Srik } 495154899Srik error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 496154899Srik dmem->size, ce_bus_dmamap_addr, &dmem->phys, 0); 497154899Srik if (error) { 498154899Srik if (cnum >= 0) printf ("ce%d-%d: ", bnum, cnum); 499154899Srik else printf ("ce%d: ", bnum); 500154899Srik printf ("couldn't load mem map for dma memory\n"); 501154899Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 502154899Srik bus_dma_tag_destroy (dmem->dmat); 503154899Srik return 0; 504154899Srik } 505154899Srik#if __FreeBSD_version >= 502000 506154899Srik bzero (dmem->virt, dmem->size); 507154899Srik#endif 508154899Srik return 1; 509154899Srik} 510154899Srik 511154899Srikstatic void 512154899Srikce_bus_dma_mem_free (ce_dma_mem_t *dmem) 513154899Srik{ 514154899Srik bus_dmamap_unload (dmem->dmat, dmem->mapp); 515154899Srik bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 516154899Srik bus_dma_tag_destroy (dmem->dmat); 517154899Srik} 518154899Srik#else 519154899Srikstatic int 520154899Srikce_bus_dma_mem_alloc (int bnum, int cnum, ce_dma_mem_t *dmem) 521154899Srik{ 522154899Srik dmem->virt = contigmalloc (dmem->size, M_DEVBUF, M_WAITOK, 523154899Srik 0x100000, 0xffffffff, 16, 0); 524154899Srik if (dmem->virt == NULL) { 525154899Srik if (cnum >= 0) printf ("ce%d-%d: ", bnum, cnum); 526154899Srik else printf ("ce%d: ", bnum); 527154899Srik printf ("couldn't allocate dma memory\n"); 528154899Srik return 0; 529154899Srik } 530154899Srik dmem->phys = vtophys (dmem->virt); 531154899Srik bzero (dmem->virt, dmem->size); 532154899Srik return 1; 533154899Srik} 534154899Srik 535154899Srikstatic void 536154899Srikce_bus_dma_mem_free (ce_dma_mem_t *dmem) 537154899Srik{ 538154899Srik contigfree (dmem->virt, dmem->size, M_DEVBUF); 539154899Srik} 540154899Srik#endif 541154899Srik 542154899Srik/* 543154899Srik * Called if the probe succeeded. 544154899Srik */ 545154899Srikstatic int ce_attach (device_t dev) 546154899Srik{ 547154899Srik bdrv_t *bd = device_get_softc (dev); 548154899Srik int unit = device_get_unit (dev); 549154899Srik#if __FreeBSD_version >= 504000 550154899Srik char *ce_ln = CE_LOCK_NAME; 551154899Srik#endif 552154899Srik vm_offset_t vbase; 553154899Srik int rid, error; 554154899Srik ce_board_t *b; 555154899Srik ce_chan_t *c; 556154899Srik drv_t *d; 557154899Srik int s; 558154899Srik 559154899Srik b = malloc (sizeof(ce_board_t), M_DEVBUF, M_WAITOK); 560154899Srik if (!b) { 561154899Srik printf ("ce%d: couldn't allocate memory\n", unit); 562154899Srik return (ENXIO); 563154899Srik } 564154899Srik bzero (b, sizeof(ce_board_t)); 565154899Srik 566154899Srik b->ddk.sys = &b; 567154899Srik 568154899Srik#if __FreeBSD_version >= 440000 569154899Srik pci_enable_busmaster (dev); 570154899Srik#endif 571154899Srik 572154899Srik bd->dmamem.size = TAU32_ControllerObjectSize; 573154899Srik if (! ce_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { 574154899Srik free (b, M_DEVBUF); 575154899Srik return (ENXIO); 576154899Srik } 577154899Srik b->ddk.pControllerObject = bd->dmamem.virt; 578154899Srik 579154899Srik bd->board = b; 580154899Srik b->sys = bd; 581154899Srik rid = PCIR_BAR(0); 582154899Srik bd->ce_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 583154899Srik 0, ~0, 1, RF_ACTIVE); 584154899Srik if (! bd->ce_res) { 585154899Srik printf ("ce%d: cannot map memory\n", unit); 586154899Srik ce_bus_dma_mem_free (&bd->dmamem); 587154899Srik free (b, M_DEVBUF); 588154899Srik return (ENXIO); 589154899Srik } 590154899Srik vbase = (vm_offset_t) rman_get_virtual (bd->ce_res); 591154899Srik 592154899Srik b->ddk.PciBar1VirtualAddress = (void *)vbase; 593154899Srik b->ddk.ControllerObjectPhysicalAddress = bd->dmamem.phys; 594154899Srik b->ddk.pErrorNotifyCallback = ce_error_callback; 595154899Srik b->ddk.pStatusNotifyCallback = ce_status_callback; 596154899Srik b->num = unit; 597154899Srik 598154899Srik TAU32_BeforeReset(&b->ddk); 599154899Srik pci_write_config (dev, TAU32_PCI_RESET_ADDRESS, TAU32_PCI_RESET_ON, 4); 600154899Srik pci_write_config (dev, TAU32_PCI_RESET_ADDRESS, TAU32_PCI_RESET_OFF, 4); 601154899Srik 602154899Srik if(!TAU32_Initialize(&b->ddk, 0)) 603154899Srik { 604154899Srik printf ("ce%d: init adapter error 0x%08x, bus dead bits 0x%08lx\n", 605154899Srik unit, b->ddk.InitErrors, b->ddk.DeadBits); 606154899Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->ce_res); 607154899Srik ce_bus_dma_mem_free (&bd->dmamem); 608154899Srik free (b, M_DEVBUF); 609154899Srik return (ENXIO); 610154899Srik } 611154899Srik 612154899Srik s = splimp (); 613154899Srik 614154899Srik ce_init_board (b); 615154899Srik 616154899Srik rid = 0; 617154899Srik bd->ce_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 618154899Srik RF_SHAREABLE | RF_ACTIVE); 619154899Srik if (! bd->ce_irq) { 620154899Srik printf ("ce%d: cannot map interrupt\n", unit); 621154899Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->ce_res); 622154899Srik ce_bus_dma_mem_free (&bd->dmamem); 623154899Srik free (b, M_DEVBUF); 624154899Srik splx (s); 625154899Srik return (ENXIO); 626154899Srik } 627154899Srik#if __FreeBSD_version >= 500000 628188663Srwatson callout_init (&led_timo[unit], CALLOUT_MPSAFE); 629154899Srik#else 630154899Srik callout_init (&led_timo[unit]); 631154899Srik#endif 632154899Srik error = bus_setup_intr (dev, bd->ce_irq, 633154899Srik#if __FreeBSD_version >= 500013 634188663Srwatson INTR_TYPE_NET|INTR_MPSAFE, 635154899Srik#else 636154899Srik INTR_TYPE_NET, 637154899Srik#endif 638166901Spiso NULL, ce_intr, bd, &bd->ce_intrhand); 639154899Srik if (error) { 640154899Srik printf ("ce%d: cannot set up irq\n", unit); 641154899Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->ce_irq); 642154899Srik bus_release_resource (dev, SYS_RES_MEMORY, 643154899Srik PCIR_BAR(0), bd->ce_res); 644154899Srik ce_bus_dma_mem_free (&bd->dmamem); 645154899Srik free (b, M_DEVBUF); 646154899Srik splx (s); 647154899Srik return (ENXIO); 648154899Srik } 649154899Srik 650154899Srik switch (b->ddk.Model) { 651154899Srik case 1: strcpy (b->name, TAU32_BASE_NAME); break; 652154899Srik case 2: strcpy (b->name, TAU32_LITE_NAME); break; 653154899Srik case 3: strcpy (b->name, TAU32_ADPCM_NAME); break; 654154899Srik default: strcpy (b->name, TAU32_UNKNOWN_NAME); break; 655154899Srik } 656154899Srik 657154899Srik printf ("ce%d: %s\n", unit, b->name); 658154899Srik 659154899Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 660154899Srik c->num = (c - b->chan); 661154899Srik c->board = b; 662154899Srik 663154899Srik d = &bd->channel[c->num]; 664154899Srik d->dmamem.size = sizeof(ce_buf_t); 665154899Srik if (! ce_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 666154899Srik continue; 667154899Srik 668154899Srik channel [b->num * NCHAN + c->num] = d; 669154899Srik sprintf (d->name, "ce%d.%d", b->num, c->num); 670154899Srik d->board = b; 671154899Srik d->chan = c; 672154899Srik c->sys = d; 673154899Srik } 674154899Srik 675154899Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 676154899Srik if (c->sys == NULL) 677154899Srik continue; 678154899Srik d = c->sys; 679154899Srik 680199407Sjhb callout_init (&d->timeout_handle, CALLOUT_MPSAFE); 681154899Srik#ifdef NETGRAPH 682154899Srik if (ng_make_node_common (&typestruct, &d->node) != 0) { 683154899Srik printf ("%s: cannot make common node\n", d->name); 684154899Srik d->node = NULL; 685154899Srik continue; 686154899Srik } 687154899Srik#if __FreeBSD_version >= 500000 688154899Srik NG_NODE_SET_PRIVATE (d->node, d); 689154899Srik#else 690154899Srik d->node->private = d; 691154899Srik#endif 692154899Srik sprintf (d->nodename, "%s%d", NG_CE_NODE_TYPE, 693154899Srik c->board->num * NCHAN + c->num); 694154899Srik if (ng_name_node (d->node, d->nodename)) { 695154899Srik printf ("%s: cannot name node\n", d->nodename); 696154899Srik#if __FreeBSD_version >= 500000 697154899Srik NG_NODE_UNREF (d->node); 698154899Srik#else 699154899Srik ng_rmnode (d->node); 700154899Srik ng_unref (d->node); 701154899Srik#endif 702154899Srik continue; 703154899Srik } 704207554Ssobomax d->queue.ifq_maxlen = ifqmaxlen; 705207554Ssobomax d->hi_queue.ifq_maxlen = ifqmaxlen; 706207554Ssobomax d->rqueue.ifq_maxlen = ifqmaxlen; 707154899Srik#if __FreeBSD_version >= 500000 708154899Srik mtx_init (&d->queue.ifq_mtx, "ce_queue", NULL, MTX_DEF); 709154899Srik mtx_init (&d->hi_queue.ifq_mtx, "ce_queue_hi", NULL, MTX_DEF); 710154899Srik mtx_init (&d->rqueue.ifq_mtx, "ce_rqueue", NULL, MTX_DEF); 711154899Srik#endif 712154899Srik#else /*NETGRAPH*/ 713154899Srik#if __FreeBSD_version >= 600031 714154899Srik d->ifp = if_alloc(IFT_PPP); 715154899Srik#else 716154899Srik d->ifp = malloc (sizeof(struct sppp), M_DEVBUF, M_WAITOK); 717154899Srik bzero (d->ifp, sizeof(struct sppp)); 718154899Srik#endif 719154899Srik if (!d->ifp) { 720154899Srik printf ("%s: cannot if_alloc() interface\n", d->name); 721154899Srik continue; 722154899Srik } 723154899Srik d->ifp->if_softc = d; 724154899Srik#if __FreeBSD_version > 501000 725154899Srik if_initname (d->ifp, "ce", b->num * NCHAN + c->num); 726154899Srik#else 727154899Srik d->ifp->if_unit = b->num * NCHAN + c->num; 728154899Srik d->ifp->if_name = "ce"; 729154899Srik#endif 730154899Srik d->ifp->if_mtu = PP_MTU; 731154899Srik d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 732154899Srik d->ifp->if_ioctl = ce_sioctl; 733154899Srik d->ifp->if_start = ce_ifstart; 734154899Srik d->ifp->if_init = ce_initialize; 735207554Ssobomax d->rqueue.ifq_maxlen = ifqmaxlen; 736154899Srik#if __FreeBSD_version >= 500000 737154899Srik mtx_init (&d->rqueue.ifq_mtx, "ce_rqueue", NULL, MTX_DEF); 738154899Srik#endif 739154899Srik sppp_attach (d->ifp); 740154899Srik if_attach (d->ifp); 741154899Srik IFP2SP(d->ifp)->pp_tlf = ce_tlf; 742154899Srik IFP2SP(d->ifp)->pp_tls = ce_tls; 743154899Srik /* If BPF is in the kernel, call the attach for it. 744154899Srik * The header size of PPP or Cisco/HDLC is 4 bytes. */ 745154899Srik bpfattach (d->ifp, DLT_PPP, 4); 746154899Srik#endif /*NETGRAPH*/ 747154899Srik ce_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); 748154899Srik 749154899Srik /* Register callback functions. */ 750154899Srik ce_register_transmit (c, &ce_transmit); 751154899Srik ce_register_receive (c, &ce_receive); 752154899Srik ce_register_error (c, &ce_error); 753154899Srik d->devt = make_dev (&ce_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 754154899Srik GID_WHEEL, 0600, "ce%d", b->num*NCHAN+c->num); 755154899Srik } 756154899Srik 757154899Srik#if __FreeBSD_version >= 504000 758154899Srik ce_ln[2] = '0' + unit; 759154899Srik mtx_init (&bd->ce_mtx, ce_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); 760154899Srik#endif 761154899Srik CE_LOCK (bd); 762154899Srik TAU32_EnableInterrupts(b->ddk.pControllerObject); 763154899Srik adapter[unit] = b; 764154899Srik CE_UNLOCK (bd); 765154899Srik splx (s); 766154899Srik 767154899Srik return 0; 768154899Srik} 769154899Srik 770154899Srikstatic int ce_detach (device_t dev) 771154899Srik{ 772154899Srik bdrv_t *bd = device_get_softc (dev); 773154899Srik ce_board_t *b = bd->board; 774154899Srik ce_chan_t *c; 775154899Srik int s; 776154899Srik 777154899Srik#if __FreeBSD_version >= 504000 778154899Srik KASSERT (mtx_initialized (&bd->ce_mtx), ("ce mutex not initialized")); 779154899Srik#endif 780154899Srik s = splimp (); 781154899Srik CE_LOCK (bd); 782154899Srik /* Check if the device is busy (open). */ 783154899Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 784154899Srik drv_t *d = (drv_t*) c->sys; 785154899Srik 786154899Srik /* XXX Non existen chan! */ 787154899Srik if (! d || ! d->chan) 788154899Srik continue; 789154899Srik if (d->running) { 790154899Srik CE_UNLOCK (bd); 791154899Srik splx (s); 792154899Srik return EBUSY; 793154899Srik } 794154899Srik } 795154899Srik 796154899Srik /* Ok, we can unload driver */ 797154899Srik /* At first we should disable interrupts */ 798154899Srik ce_destroy = 1; 799154899Srik TAU32_DisableInterrupts(b->ddk.pControllerObject); 800154899Srik 801154899Srik callout_stop (&led_timo[b->num]); 802154899Srik 803154899Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 804154899Srik drv_t *d = (drv_t*) c->sys; 805154899Srik 806154899Srik if (! d || ! d->chan) 807154899Srik continue; 808199407Sjhb callout_stop (&d->timeout_handle); 809154899Srik#ifndef NETGRAPH 810154899Srik /* Detach from the packet filter list of interfaces. */ 811154899Srik bpfdetach (d->ifp); 812167882Srik 813154899Srik /* Detach from the sync PPP list. */ 814154899Srik sppp_detach (d->ifp); 815154899Srik 816154899Srik /* Detach from the system list of interfaces. */ 817154899Srik if_detach (d->ifp); 818154899Srik#if __FreeBSD_version > 600031 819154899Srik if_free(d->ifp); 820154899Srik#else 821154899Srik free (d->ifp, M_DEVBUF); 822154899Srik#endif 823154899Srik 824154899Srik IF_DRAIN (&d->rqueue); 825154899Srik#if __FreeBSD_version >= 500000 826154899Srik mtx_destroy (&d->rqueue.ifq_mtx); 827154899Srik#endif 828154899Srik#else 829154899Srik#if __FreeBSD_version >= 500000 830154899Srik if (d->node) { 831154899Srik ng_rmnode_self (d->node); 832154899Srik NG_NODE_UNREF (d->node); 833154899Srik d->node = NULL; 834154899Srik } 835154899Srik IF_DRAIN (&d->rqueue); 836154899Srik mtx_destroy (&d->queue.ifq_mtx); 837154899Srik mtx_destroy (&d->hi_queue.ifq_mtx); 838154899Srik mtx_destroy (&d->rqueue.ifq_mtx); 839154899Srik#else 840154899Srik ng_rmnode (d->node); 841154899Srik d->node = 0; 842154899Srik#endif 843154899Srik#endif 844154899Srik destroy_dev (d->devt); 845154899Srik } 846154899Srik 847154899Srik CE_UNLOCK (bd); 848154899Srik splx (s); 849154899Srik 850154899Srik callout_drain (&led_timo[b->num]); 851154899Srik 852154899Srik /* Disable the interrupt request. */ 853154899Srik bus_teardown_intr (dev, bd->ce_irq, bd->ce_intrhand); 854154899Srik bus_release_resource (dev, SYS_RES_IRQ, 0, bd->ce_irq); 855154899Srik TAU32_DestructiveHalt (b->ddk.pControllerObject, 0); 856154899Srik bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->ce_res); 857154899Srik 858154899Srik for (c = b->chan; c < b->chan + NCHAN; ++c) { 859154899Srik drv_t *d = (drv_t*) c->sys; 860154899Srik 861154899Srik if (! d || ! d->chan) 862154899Srik continue; 863199407Sjhb callout_drain (&d->timeout_handle); 864154899Srik channel [b->num * NCHAN + c->num] = 0; 865154899Srik /* Deallocate buffers. */ 866154899Srik ce_bus_dma_mem_free (&d->dmamem); 867154899Srik } 868154899Srik adapter [b->num] = 0; 869154899Srik ce_bus_dma_mem_free (&bd->dmamem); 870154899Srik free (b, M_DEVBUF); 871154899Srik#if __FreeBSD_version >= 504000 872154899Srik mtx_destroy (&bd->ce_mtx); 873154899Srik#endif 874154899Srik return 0; 875154899Srik} 876154899Srik 877154899Srik#ifndef NETGRAPH 878154899Srikstatic void ce_ifstart (struct ifnet *ifp) 879154899Srik{ 880154899Srik drv_t *d = ifp->if_softc; 881154899Srik bdrv_t *bd = d->board->sys; 882154899Srik 883154899Srik CE_LOCK (bd); 884154899Srik ce_start (d); 885154899Srik CE_UNLOCK (bd); 886154899Srik} 887154899Srik 888154899Srikstatic void ce_tlf (struct sppp *sp) 889154899Srik{ 890154899Srik drv_t *d = SP2IFP(sp)->if_softc; 891154899Srik 892154899Srik CE_DEBUG2 (d, ("ce_tlf\n")); 893154899Srik sp->pp_down (sp); 894154899Srik} 895154899Srik 896154899Srikstatic void ce_tls (struct sppp *sp) 897154899Srik{ 898154899Srik drv_t *d = SP2IFP(sp)->if_softc; 899154899Srik 900154899Srik CE_DEBUG2 (d, ("ce_tls\n")); 901154899Srik sp->pp_up (sp); 902154899Srik} 903154899Srik 904154899Srik/* 905154899Srik * Process an ioctl request. 906154899Srik */ 907154899Srikstatic int ce_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 908154899Srik{ 909154899Srik drv_t *d = ifp->if_softc; 910154899Srik bdrv_t *bd = d->board->sys; 911154899Srik int error, s, was_up, should_be_up; 912154899Srik 913154899Srik#if __FreeBSD_version >= 600034 914154899Srik was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 915154899Srik#else 916154899Srik was_up = (ifp->if_flags & IFF_RUNNING) != 0; 917154899Srik#endif 918154899Srik error = sppp_ioctl (ifp, cmd, data); 919154899Srik 920154899Srik if (error) 921154899Srik return error; 922154899Srik 923154899Srik if (! (ifp->if_flags & IFF_DEBUG)) 924154899Srik d->chan->debug = 0; 925180132Srik else 926180132Srik d->chan->debug = d->chan->debug_shadow; 927154899Srik 928154899Srik switch (cmd) { 929154899Srik default: CE_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 930154899Srik case SIOCADDMULTI: CE_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 931154899Srik case SIOCDELMULTI: CE_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 932154899Srik case SIOCSIFFLAGS: CE_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 933154899Srik case SIOCSIFADDR: CE_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 934154899Srik } 935154899Srik 936154899Srik /* We get here only in case of SIFFLAGS or SIFADDR. */ 937154899Srik s = splimp (); 938154899Srik CE_LOCK (bd); 939154899Srik#if __FreeBSD_version >= 600034 940154899Srik should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 941154899Srik#else 942154899Srik should_be_up = (ifp->if_flags & IFF_RUNNING) != 0; 943154899Srik#endif 944154899Srik if (! was_up && should_be_up) { 945154899Srik /* Interface goes up -- start it. */ 946154899Srik ce_up (d); 947154899Srik ce_start (d); 948154899Srik } else if (was_up && ! should_be_up) { 949154899Srik /* Interface is going down -- stop it. */ 950154899Srik/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 951154899Srik ce_down (d); 952154899Srik } 953154899Srik CE_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 954154899Srik CE_UNLOCK (bd); 955154899Srik splx (s); 956154899Srik return 0; 957154899Srik} 958154899Srik 959154899Srik/* 960154899Srik * Initialization of interface. 961154899Srik * It seems to be never called by upper level? 962154899Srik */ 963154899Srikstatic void ce_initialize (void *softc) 964154899Srik{ 965154899Srik drv_t *d = softc; 966154899Srik 967154899Srik CE_DEBUG (d, ("ce_initialize\n")); 968154899Srik} 969154899Srik#endif /*NETGRAPH*/ 970154899Srik 971154899Srik/* 972154899Srik * Stop the interface. Called on splimp(). 973154899Srik */ 974154899Srikstatic void ce_down (drv_t *d) 975154899Srik{ 976154899Srik CE_DEBUG (d, ("ce_down\n")); 977154899Srik /* Interface is going down -- stop it. */ 978154899Srik ce_set_dtr (d->chan, 0); 979154899Srik ce_set_rts (d->chan, 0); 980154899Srik 981154899Srik d->running = 0; 982199407Sjhb callout_stop (&d->timeout_handle); 983154899Srik} 984154899Srik 985154899Srik/* 986154899Srik * Start the interface. Called on splimp(). 987154899Srik */ 988154899Srikstatic void ce_up (drv_t *d) 989154899Srik{ 990154899Srik CE_DEBUG (d, ("ce_up\n")); 991154899Srik ce_set_dtr (d->chan, 1); 992154899Srik ce_set_rts (d->chan, 1); 993154899Srik 994154899Srik d->running = 1; 995154899Srik} 996154899Srik 997154899Srik/* 998154899Srik * Start output on the interface. Get another datagram to send 999154899Srik * off of the interface queue, and copy it to the interface 1000154899Srik * before starting the output. 1001154899Srik */ 1002154899Srikstatic void ce_send (drv_t *d) 1003154899Srik{ 1004154899Srik struct mbuf *m; 1005154899Srik u_short len; 1006154899Srik 1007154899Srik CE_DEBUG2 (d, ("ce_send\n")); 1008154899Srik 1009154899Srik /* No output if the interface is down. */ 1010154899Srik if (! d->running) 1011154899Srik return; 1012154899Srik 1013154899Srik while (ce_transmit_space (d->chan)) { 1014154899Srik /* Get the packet to send. */ 1015154899Srik#ifdef NETGRAPH 1016154899Srik IF_DEQUEUE (&d->hi_queue, m); 1017154899Srik if (! m) 1018154899Srik IF_DEQUEUE (&d->queue, m); 1019154899Srik#else 1020154899Srik m = sppp_dequeue (d->ifp); 1021154899Srik#endif 1022154899Srik if (! m) 1023154899Srik return; 1024154899Srik#ifndef NETGRAPH 1025154899Srik#if __FreeBSD_version >= 500000 1026165632Sjhb BPF_MTAP (d->ifp, m); 1027154899Srik#else 1028165632Sjhb if (d->ifp->if_bpf) 1029154899Srik bpf_mtap (d->ifp, m); 1030154899Srik#endif 1031154899Srik#endif 1032154899Srik#if __FreeBSD_version >= 490000 1033154899Srik len = m_length (m, NULL); 1034154899Srik#else 1035154899Srik len = m->m_pkthdr.len; 1036154899Srik#endif 1037154899Srik if (len >= BUFSZ) 1038154899Srik printf ("%s: too long packet: %d bytes: ", 1039154899Srik d->name, len); 1040154899Srik else if (! m->m_next) 1041154899Srik ce_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 1042154899Srik else { 1043154899Srik ce_buf_item_t *item = (ce_buf_item_t*)d->chan->tx_queue; 1044154899Srik m_copydata (m, 0, len, item->buf); 1045154899Srik ce_send_packet (d->chan, item->buf, len, 0); 1046154899Srik } 1047154899Srik m_freem (m); 1048154899Srik /* Set up transmit timeout, if the transmit ring is not empty.*/ 1049154899Srik d->timeout = 10; 1050154899Srik } 1051154899Srik#ifndef NETGRAPH 1052154899Srik#if __FreeBSD_version >= 600034 1053154899Srik d->ifp->if_flags |= IFF_DRV_OACTIVE; 1054154899Srik#else 1055154899Srik d->ifp->if_flags |= IFF_OACTIVE; 1056154899Srik#endif 1057154899Srik#endif 1058154899Srik} 1059154899Srik 1060154899Srik/* 1061154899Srik * Start output on the interface. 1062154899Srik * Always called on splimp(). 1063154899Srik */ 1064154899Srikstatic void ce_start (drv_t *d) 1065154899Srik{ 1066154899Srik if (d->running) { 1067154899Srik if (! d->chan->dtr) 1068154899Srik ce_set_dtr (d->chan, 1); 1069154899Srik if (! d->chan->rts) 1070154899Srik ce_set_rts (d->chan, 1); 1071154899Srik ce_send (d); 1072199407Sjhb callout_reset (&d->timeout_handle, hz, ce_watchdog_timer, d); 1073154899Srik } 1074154899Srik} 1075154899Srik 1076154899Srik/* 1077154899Srik * Handle transmit timeouts. 1078154899Srik * Recover after lost transmit interrupts. 1079154899Srik * Always called on splimp(). 1080154899Srik */ 1081154899Srikstatic void ce_watchdog (drv_t *d) 1082154899Srik{ 1083154899Srik CE_DEBUG (d, ("device timeout\n")); 1084154899Srik if (d->running) { 1085154899Srik ce_set_dtr (d->chan, 0); 1086154899Srik ce_set_rts (d->chan, 0); 1087154899Srik/* ce_stop_chan (d->chan);*/ 1088154899Srik/* ce_start_chan (d->chan, 1, 1, 0, 0);*/ 1089154899Srik ce_set_dtr (d->chan, 1); 1090154899Srik ce_set_rts (d->chan, 1); 1091154899Srik ce_start (d); 1092154899Srik } 1093154899Srik} 1094154899Srik 1095199407Sjhbstatic void ce_watchdog_timer (void *arg) 1096199407Sjhb{ 1097199407Sjhb drv_t *d = arg; 1098199407Sjhb bdrv_t *bd = d->board->sys; 1099199407Sjhb 1100199407Sjhb CE_LOCK(bd); 1101199407Sjhb if (d->timeout == 1) 1102199407Sjhb ce_watchdog (d); 1103199407Sjhb if (d->timeout) 1104199407Sjhb d->timeout--; 1105199407Sjhb callout_reset (&d->timeout_handle, hz, ce_watchdog_timer, d); 1106199407Sjhb CE_UNLOCK(bd); 1107199407Sjhb} 1108199407Sjhb 1109154899Srikstatic void ce_transmit (ce_chan_t *c, void *attachment, int len) 1110154899Srik{ 1111154899Srik drv_t *d = c->sys; 1112154899Srik 1113154899Srik d->timeout = 0; 1114199407Sjhb#ifndef NETGRAPH 1115154899Srik ++d->ifp->if_opackets; 1116154899Srik#if __FreeBSD_version >= 600034 1117154899Srik d->ifp->if_flags &= ~IFF_DRV_OACTIVE; 1118154899Srik#else 1119154899Srik d->ifp->if_flags &= ~IFF_OACTIVE; 1120154899Srik#endif 1121154899Srik#endif 1122154899Srik ce_start (d); 1123154899Srik} 1124154899Srik 1125154899Srikstatic void ce_receive (ce_chan_t *c, unsigned char *data, int len) 1126154899Srik{ 1127154899Srik drv_t *d = c->sys; 1128154899Srik struct mbuf *m; 1129154899Srik 1130154899Srik if (! d->running) 1131154899Srik return; 1132154899Srik 1133154899Srik m = makembuf (data, len); 1134154899Srik if (! m) { 1135154899Srik CE_DEBUG (d, ("no memory for packet\n")); 1136154899Srik#ifndef NETGRAPH 1137154899Srik ++d->ifp->if_iqdrops; 1138154899Srik#endif 1139154899Srik return; 1140154899Srik } 1141154899Srik if (c->debug > 1) 1142154899Srik printmbuf (m); 1143154899Srik#ifdef NETGRAPH 1144154899Srik m->m_pkthdr.rcvif = 0; 1145154899Srik IF_ENQUEUE(&d->rqueue, m); 1146154899Srik#else 1147154899Srik ++d->ifp->if_ipackets; 1148154899Srik m->m_pkthdr.rcvif = d->ifp; 1149154899Srik /* Check if there's a BPF listener on this interface. 1150154899Srik * If so, hand off the raw packet to bpf. */ 1151154899Srik#if __FreeBSD_version >= 500000 1152165632Sjhb BPF_TAP (d->ifp, data, len); 1153154899Srik#else 1154165632Sjhb if (d->ifp->if_bpf) 1155154899Srik bpf_tap (d->ifp, data, len); 1156154899Srik#endif 1157154899Srik IF_ENQUEUE(&d->rqueue, m); 1158154899Srik#endif 1159154899Srik} 1160154899Srik 1161154899Srikstatic void ce_error (ce_chan_t *c, int data) 1162154899Srik{ 1163154899Srik drv_t *d = c->sys; 1164154899Srik 1165154899Srik switch (data) { 1166154899Srik case CE_FRAME: 1167154899Srik CE_DEBUG (d, ("frame error\n")); 1168154899Srik#ifndef NETGRAPH 1169154899Srik ++d->ifp->if_ierrors; 1170154899Srik#endif 1171154899Srik break; 1172154899Srik case CE_CRC: 1173154899Srik CE_DEBUG (d, ("crc error\n")); 1174154899Srik#ifndef NETGRAPH 1175154899Srik ++d->ifp->if_ierrors; 1176154899Srik#endif 1177154899Srik break; 1178154899Srik case CE_OVERRUN: 1179154899Srik CE_DEBUG (d, ("overrun error\n")); 1180154899Srik#ifndef NETGRAPH 1181154899Srik ++d->ifp->if_collisions; 1182154899Srik ++d->ifp->if_ierrors; 1183154899Srik#endif 1184154899Srik break; 1185154899Srik case CE_OVERFLOW: 1186154899Srik CE_DEBUG (d, ("overflow error\n")); 1187154899Srik#ifndef NETGRAPH 1188154899Srik ++d->ifp->if_ierrors; 1189154899Srik#endif 1190154899Srik break; 1191154899Srik case CE_UNDERRUN: 1192154899Srik CE_DEBUG (d, ("underrun error\n")); 1193154899Srik d->timeout = 0; 1194199407Sjhb#ifndef NETGRAPH 1195154899Srik ++d->ifp->if_oerrors; 1196154899Srik#if __FreeBSD_version >= 600034 1197154899Srik d->ifp->if_flags &= ~IFF_DRV_OACTIVE; 1198154899Srik#else 1199154899Srik d->ifp->if_flags &= ~IFF_OACTIVE; 1200154899Srik#endif 1201154899Srik#endif 1202154899Srik ce_start (d); 1203154899Srik break; 1204154899Srik default: 1205154899Srik CE_DEBUG (d, ("error #%d\n", data)); 1206154899Srik break; 1207154899Srik } 1208154899Srik} 1209154899Srik 1210154899Srik/* 1211154899Srik * You also need read, write, open, close routines. 1212154899Srik * This should get you started 1213154899Srik */ 1214154899Srik#if __FreeBSD_version < 500000 1215154899Srikstatic int ce_open (dev_t dev, int oflags, int devtype, struct proc *p) 1216154899Srik#else 1217154899Srikstatic int ce_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 1218154899Srik#endif 1219154899Srik{ 1220183397Sed int unit = dev2unit (dev); 1221154899Srik drv_t *d; 1222154899Srik 1223154899Srik if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 1224154899Srik return ENXIO; 1225154899Srik CE_DEBUG2 (d, ("ce_open\n")); 1226154899Srik return 0; 1227154899Srik} 1228154899Srik 1229154899Srik/* 1230154899Srik * Only called on the LAST close. 1231154899Srik */ 1232154899Srik#if __FreeBSD_version < 500000 1233154899Srikstatic int ce_close (dev_t dev, int fflag, int devtype, struct proc *p) 1234154899Srik#else 1235154899Srikstatic int ce_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 1236154899Srik#endif 1237154899Srik{ 1238183397Sed drv_t *d = channel [dev2unit (dev)]; 1239154899Srik 1240154899Srik CE_DEBUG2 (d, ("ce_close\n")); 1241154899Srik return 0; 1242154899Srik} 1243154899Srik 1244154899Srikstatic int ce_modem_status (ce_chan_t *c) 1245154899Srik{ 1246154899Srik drv_t *d = c->sys; 1247154899Srik bdrv_t *bd = d->board->sys; 1248154899Srik int status, s; 1249154899Srik 1250154899Srik status = d->running ? TIOCM_LE : 0; 1251154899Srik s = splimp (); 1252154899Srik CE_LOCK (bd); 1253154899Srik if (ce_get_cd (c)) status |= TIOCM_CD; 1254154899Srik if (ce_get_cts (c)) status |= TIOCM_CTS; 1255154899Srik if (ce_get_dsr (c)) status |= TIOCM_DSR; 1256154899Srik if (c->dtr) status |= TIOCM_DTR; 1257154899Srik if (c->rts) status |= TIOCM_RTS; 1258154899Srik CE_UNLOCK (bd); 1259154899Srik splx (s); 1260154899Srik return status; 1261154899Srik} 1262154899Srik 1263154899Srik#if __FreeBSD_version < 500000 1264154899Srikstatic int ce_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 1265154899Srik#else 1266154899Srikstatic int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1267154899Srik#endif 1268154899Srik{ 1269183397Sed drv_t *d = channel [dev2unit (dev)]; 1270154899Srik bdrv_t *bd = d->board->sys; 1271154899Srik ce_chan_t *c = d->chan; 1272154899Srik struct serial_statistics *st; 1273154899Srik struct e1_statistics *opte1; 1274154899Srik int error, s; 1275154899Srik char mask[16]; 1276154899Srik 1277154899Srik switch (cmd) { 1278154899Srik case SERIAL_GETREGISTERED: 1279154899Srik CE_DEBUG2 (d, ("ioctl: getregistered\n")); 1280154899Srik bzero (mask, sizeof(mask)); 1281154899Srik for (s=0; s<NBRD*NCHAN; ++s) 1282154899Srik if (channel [s]) 1283154899Srik mask [s/8] |= 1 << (s & 7); 1284154899Srik bcopy (mask, data, sizeof (mask)); 1285154899Srik return 0; 1286154899Srik 1287154899Srik#ifndef NETGRAPH 1288154899Srik case SERIAL_GETPROTO: 1289154899Srik CE_DEBUG2 (d, ("ioctl: getproto\n")); 1290154899Srik strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" : 1291154899Srik (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp"); 1292154899Srik return 0; 1293154899Srik 1294154899Srik case SERIAL_SETPROTO: 1295154899Srik CE_DEBUG2 (d, ("ioctl: setproto\n")); 1296154899Srik /* Only for superuser! */ 1297154899Srik#if __FreeBSD_version < 500000 1298154899Srik error = suser (p); 1299180147Sdds#elif __FreeBSD_version < 700000 1300154899Srik error = suser (td); 1301164033Srwatson#else 1302164033Srwatson error = priv_check (td, PRIV_DRIVER); 1303164033Srwatson#endif 1304154899Srik if (error) 1305154899Srik return error; 1306154899Srik#if __FreeBSD_version >= 600034 1307154899Srik if (d->ifp->if_flags & IFF_DRV_RUNNING) 1308154899Srik#else 1309154899Srik if (d->ifp->if_flags & IFF_RUNNING) 1310154899Srik#endif 1311154899Srik return EBUSY; 1312154899Srik if (! strcmp ("cisco", (char*)data)) { 1313154899Srik IFP2SP(d->ifp)->pp_flags &= ~(PP_FR); 1314154899Srik IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1315154899Srik d->ifp->if_flags |= PP_CISCO; 1316228963Sdim#if PP_FR != 0 1317228963Sdim } else if (! strcmp ("fr", (char*)data)) { 1318154899Srik d->ifp->if_flags &= ~(PP_CISCO); 1319154899Srik IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE; 1320228963Sdim#endif 1321154899Srik } else if (! strcmp ("ppp", (char*)data)) { 1322154899Srik IFP2SP(d->ifp)->pp_flags &= ~PP_FR; 1323154899Srik IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1324154899Srik d->ifp->if_flags &= ~(PP_CISCO); 1325154899Srik } else 1326154899Srik return EINVAL; 1327154899Srik return 0; 1328154899Srik 1329154899Srik case SERIAL_GETKEEPALIVE: 1330154899Srik CE_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1331154899Srik if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1332154899Srik (d->ifp->if_flags & PP_CISCO)) 1333154899Srik return EINVAL; 1334154899Srik *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0; 1335154899Srik return 0; 1336154899Srik 1337154899Srik case SERIAL_SETKEEPALIVE: 1338154899Srik CE_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1339154899Srik /* Only for superuser! */ 1340154899Srik#if __FreeBSD_version < 500000 1341154899Srik error = suser (p); 1342180147Sdds#elif __FreeBSD_version < 700000 1343164033Srwatson error = suser (td); 1344154899Srik#else 1345164033Srwatson error = priv_check (td, PRIV_DRIVER); 1346154899Srik#endif 1347154899Srik if (error) 1348154899Srik return error; 1349154899Srik if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1350154899Srik (d->ifp->if_flags & PP_CISCO)) 1351154899Srik return EINVAL; 1352154899Srik s = splimp (); 1353154899Srik CE_LOCK (bd); 1354154899Srik if (*(int*)data) 1355154899Srik IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1356154899Srik else 1357154899Srik IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1358154899Srik CE_UNLOCK (bd); 1359154899Srik splx (s); 1360154899Srik return 0; 1361154899Srik#endif /*NETGRAPH*/ 1362154899Srik 1363154899Srik case SERIAL_GETMODE: 1364154899Srik CE_DEBUG2 (d, ("ioctl: getmode\n")); 1365154899Srik *(int*)data = SERIAL_HDLC; 1366154899Srik return 0; 1367154899Srik 1368154899Srik case SERIAL_SETMODE: 1369154899Srik /* Only for superuser! */ 1370154899Srik#if __FreeBSD_version < 500000 1371154899Srik error = suser (p); 1372180147Sdds#elif __FreeBSD_version < 700000 1373164033Srwatson error = suser (td); 1374154899Srik#else 1375164033Srwatson error = priv_check (td, PRIV_DRIVER); 1376154899Srik#endif 1377154899Srik if (error) 1378154899Srik return error; 1379154899Srik if (*(int*)data != SERIAL_HDLC) 1380154899Srik return EINVAL; 1381154899Srik return 0; 1382154899Srik 1383154899Srik case SERIAL_GETCFG: 1384154899Srik CE_DEBUG2 (d, ("ioctl: getcfg\n")); 1385154899Srik *(char*)data = 'c'; 1386154899Srik return 0; 1387154899Srik 1388154899Srik case SERIAL_SETCFG: 1389154899Srik CE_DEBUG2 (d, ("ioctl: setcfg\n")); 1390154899Srik#if __FreeBSD_version < 500000 1391154899Srik error = suser (p); 1392180147Sdds#elif __FreeBSD_version < 700000 1393164033Srwatson error = suser (td); 1394154899Srik#else 1395164033Srwatson error = priv_check (td, PRIV_DRIVER); 1396154899Srik#endif 1397154899Srik if (error) 1398154899Srik return error; 1399154899Srik if (*((char*)data) != 'c') 1400154899Srik return EINVAL; 1401154899Srik return 0; 1402154899Srik 1403154899Srik case SERIAL_GETSTAT: 1404154899Srik CE_DEBUG2 (d, ("ioctl: getstat\n")); 1405154899Srik st = (struct serial_statistics*) data; 1406154899Srik st->rintr = c->rintr; 1407154899Srik st->tintr = c->tintr; 1408154899Srik st->mintr = 0; 1409154899Srik st->ibytes = c->ibytes; 1410154899Srik st->ipkts = c->ipkts; 1411154899Srik st->obytes = c->obytes; 1412154899Srik st->opkts = c->opkts; 1413154899Srik st->ierrs = c->overrun + c->frame + c->crc; 1414154899Srik st->oerrs = c->underrun; 1415154899Srik return 0; 1416154899Srik 1417154899Srik case SERIAL_GETESTAT: 1418154899Srik CE_DEBUG2 (d, ("ioctl: getestat\n")); 1419154899Srik if (c->type != T_E1) 1420154899Srik return EINVAL; 1421154899Srik opte1 = (struct e1_statistics*) data; 1422154899Srik 1423154899Srik opte1->status = 0; 1424154899Srik if (c->status & ESTS_NOALARM) 1425154899Srik opte1->status |= E1_NOALARM; 1426154899Srik if (c->status & ESTS_LOS) 1427154899Srik opte1->status |= E1_LOS; 1428154899Srik if (c->status & ESTS_LOF) 1429154899Srik opte1->status |= E1_LOF; 1430154899Srik if (c->status & ESTS_AIS) 1431154899Srik opte1->status |= E1_AIS; 1432154899Srik if (c->status & ESTS_LOMF) 1433154899Srik opte1->status |= E1_LOMF; 1434154899Srik if (c->status & ESTS_AIS16) 1435154899Srik opte1->status |= E1_AIS16; 1436154899Srik if (c->status & ESTS_FARLOF) 1437154899Srik opte1->status |= E1_FARLOF; 1438154899Srik if (c->status & ESTS_FARLOMF) 1439154899Srik opte1->status |= E1_FARLOMF; 1440154899Srik if (c->status & ESTS_TSTREQ) 1441154899Srik opte1->status |= E1_TSTREQ; 1442154899Srik if (c->status & ESTS_TSTERR) 1443154899Srik opte1->status |= E1_TSTERR; 1444154899Srik 1445154899Srik opte1->cursec = c->cursec; 1446154899Srik opte1->totsec = c->totsec + c->cursec; 1447154899Srik 1448154899Srik opte1->currnt.bpv = c->currnt.bpv; 1449154899Srik opte1->currnt.fse = c->currnt.fse; 1450154899Srik opte1->currnt.crce = c->currnt.crce; 1451154899Srik opte1->currnt.rcrce = c->currnt.rcrce; 1452154899Srik opte1->currnt.uas = c->currnt.uas; 1453154899Srik opte1->currnt.les = c->currnt.les; 1454154899Srik opte1->currnt.es = c->currnt.es; 1455154899Srik opte1->currnt.bes = c->currnt.bes; 1456154899Srik opte1->currnt.ses = c->currnt.ses; 1457154899Srik opte1->currnt.oofs = c->currnt.oofs; 1458154899Srik opte1->currnt.css = c->currnt.css; 1459154899Srik opte1->currnt.dm = c->currnt.dm; 1460154899Srik 1461154899Srik opte1->total.bpv = c->total.bpv + c->currnt.bpv; 1462154899Srik opte1->total.fse = c->total.fse + c->currnt.fse; 1463154899Srik opte1->total.crce = c->total.crce + c->currnt.crce; 1464154899Srik opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 1465154899Srik opte1->total.uas = c->total.uas + c->currnt.uas; 1466154899Srik opte1->total.les = c->total.les + c->currnt.les; 1467154899Srik opte1->total.es = c->total.es + c->currnt.es; 1468154899Srik opte1->total.bes = c->total.bes + c->currnt.bes; 1469154899Srik opte1->total.ses = c->total.ses + c->currnt.ses; 1470154899Srik opte1->total.oofs = c->total.oofs + c->currnt.oofs; 1471154899Srik opte1->total.css = c->total.css + c->currnt.css; 1472154899Srik opte1->total.dm = c->total.dm + c->currnt.dm; 1473154899Srik for (s=0; s<48; ++s) { 1474154899Srik opte1->interval[s].bpv = c->interval[s].bpv; 1475154899Srik opte1->interval[s].fse = c->interval[s].fse; 1476154899Srik opte1->interval[s].crce = c->interval[s].crce; 1477154899Srik opte1->interval[s].rcrce = c->interval[s].rcrce; 1478154899Srik opte1->interval[s].uas = c->interval[s].uas; 1479154899Srik opte1->interval[s].les = c->interval[s].les; 1480154899Srik opte1->interval[s].es = c->interval[s].es; 1481154899Srik opte1->interval[s].bes = c->interval[s].bes; 1482154899Srik opte1->interval[s].ses = c->interval[s].ses; 1483154899Srik opte1->interval[s].oofs = c->interval[s].oofs; 1484154899Srik opte1->interval[s].css = c->interval[s].css; 1485154899Srik opte1->interval[s].dm = c->interval[s].dm; 1486154899Srik } 1487154899Srik return 0; 1488154899Srik 1489154899Srik case SERIAL_CLRSTAT: 1490154899Srik CE_DEBUG2 (d, ("ioctl: clrstat\n")); 1491154899Srik /* Only for superuser! */ 1492154899Srik#if __FreeBSD_version < 500000 1493154899Srik error = suser (p); 1494180147Sdds#elif __FreeBSD_version < 700000 1495164033Srwatson error = suser (td); 1496154899Srik#else 1497164033Srwatson error = priv_check (td, PRIV_DRIVER); 1498154899Srik#endif 1499154899Srik if (error) 1500154899Srik return error; 1501154899Srik c->rintr = 0; 1502154899Srik c->tintr = 0; 1503154899Srik c->ibytes = 0; 1504154899Srik c->obytes = 0; 1505154899Srik c->ipkts = 0; 1506154899Srik c->opkts = 0; 1507154899Srik c->overrun = 0; 1508154899Srik c->frame = 0; 1509154899Srik c->crc = 0; 1510154899Srik c->underrun = 0; 1511154899Srik bzero (&c->currnt, sizeof (c->currnt)); 1512154899Srik bzero (&c->total, sizeof (c->total)); 1513154899Srik bzero (c->interval, sizeof (c->interval)); 1514154899Srik return 0; 1515154899Srik 1516154899Srik case SERIAL_GETLOOP: 1517154899Srik CE_DEBUG2 (d, ("ioctl: getloop\n")); 1518154899Srik if (c->type != T_E1) 1519154899Srik return EINVAL; 1520154899Srik *(int*)data = c->lloop; 1521154899Srik return 0; 1522154899Srik 1523154899Srik case SERIAL_SETLOOP: 1524154899Srik CE_DEBUG2 (d, ("ioctl: setloop\n")); 1525154899Srik if (c->type != T_E1) 1526154899Srik return EINVAL; 1527154899Srik /* Only for superuser! */ 1528154899Srik#if __FreeBSD_version < 500000 1529154899Srik error = suser (p); 1530180147Sdds#elif __FreeBSD_version < 700000 1531164033Srwatson error = suser (td); 1532154899Srik#else 1533164033Srwatson error = priv_check (td, PRIV_DRIVER); 1534154899Srik#endif 1535154899Srik if (error) 1536154899Srik return error; 1537154899Srik s = splimp (); 1538154899Srik CE_LOCK (bd); 1539154899Srik ce_set_lloop (c, *(int*)data); 1540154899Srik CE_UNLOCK (bd); 1541154899Srik splx (s); 1542154899Srik return 0; 1543154899Srik 1544154899Srik case SERIAL_GETRLOOP: 1545154899Srik CE_DEBUG2 (d, ("ioctl: getrloop\n")); 1546154899Srik if (c->type != T_E1) 1547154899Srik return EINVAL; 1548154899Srik *(int*)data = c->rloop; 1549154899Srik return 0; 1550154899Srik 1551154899Srik case SERIAL_SETRLOOP: 1552154899Srik CE_DEBUG2 (d, ("ioctl: setloop\n")); 1553154899Srik if (c->type != T_E1) 1554154899Srik return EINVAL; 1555154899Srik /* Only for superuser! */ 1556154899Srik#if __FreeBSD_version < 500000 1557154899Srik error = suser (p); 1558180147Sdds#elif __FreeBSD_version < 700000 1559164033Srwatson error = suser (td); 1560154899Srik#else 1561164033Srwatson error = priv_check (td, PRIV_DRIVER); 1562154899Srik#endif 1563154899Srik if (error) 1564154899Srik return error; 1565154899Srik s = splimp (); 1566154899Srik CE_LOCK (bd); 1567154899Srik ce_set_rloop (c, *(int*)data); 1568154899Srik CE_UNLOCK (bd); 1569154899Srik splx (s); 1570154899Srik return 0; 1571154899Srik 1572154899Srik case SERIAL_GETDEBUG: 1573154899Srik CE_DEBUG2 (d, ("ioctl: getdebug\n")); 1574154899Srik *(int*)data = d->chan->debug; 1575154899Srik return 0; 1576154899Srik 1577154899Srik case SERIAL_SETDEBUG: 1578154899Srik CE_DEBUG2 (d, ("ioctl: setdebug\n")); 1579154899Srik /* Only for superuser! */ 1580154899Srik#if __FreeBSD_version < 500000 1581154899Srik error = suser (p); 1582180147Sdds#elif __FreeBSD_version < 700000 1583164033Srwatson error = suser (td); 1584154899Srik#else 1585164033Srwatson error = priv_check (td, PRIV_DRIVER); 1586154899Srik#endif 1587154899Srik if (error) 1588154899Srik return error; 1589180132Srik#ifndef NETGRAPH 1590180132Srik /* 1591180132Srik * The debug_shadow is always greater than zero for logic 1592180132Srik * simplicity. For switching debug off the IFF_DEBUG is 1593180132Srik * responsible. 1594180132Srik */ 1595180132Srik d->chan->debug_shadow = (*(int*)data) ? (*(int*)data) : 1; 1596180132Srik if (d->ifp->if_flags & IFF_DEBUG) 1597180132Srik d->chan->debug = d->chan->debug_shadow; 1598180132Srik#else 1599154899Srik d->chan->debug = *(int*)data; 1600154899Srik#endif 1601154899Srik return 0; 1602154899Srik 1603154899Srik case SERIAL_GETBAUD: 1604154899Srik CE_DEBUG2 (d, ("ioctl: getbaud\n")); 1605154899Srik *(long*)data = c->baud; 1606154899Srik return 0; 1607154899Srik 1608154899Srik case SERIAL_SETBAUD: 1609154899Srik CE_DEBUG2 (d, ("ioctl: setbaud\n")); 1610154899Srik if (c->type != T_E1 || !c->unfram) 1611154899Srik return EINVAL; 1612154899Srik /* Only for superuser! */ 1613154899Srik#if __FreeBSD_version < 500000 1614154899Srik error = suser (p); 1615180147Sdds#elif __FreeBSD_version < 700000 1616164033Srwatson error = suser (td); 1617154899Srik#else 1618164033Srwatson error = priv_check (td, PRIV_DRIVER); 1619154899Srik#endif 1620154899Srik if (error) 1621154899Srik return error; 1622154899Srik s = splimp (); 1623154899Srik CE_LOCK (bd); 1624154899Srik ce_set_baud (c, *(long*)data); 1625154899Srik CE_UNLOCK (bd); 1626154899Srik splx (s); 1627154899Srik return 0; 1628154899Srik 1629154899Srik case SERIAL_GETTIMESLOTS: 1630154899Srik CE_DEBUG2 (d, ("ioctl: gettimeslots\n")); 1631154899Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1632154899Srik return EINVAL; 1633154899Srik *(u_long*)data = c->ts; 1634154899Srik return 0; 1635154899Srik 1636154899Srik case SERIAL_SETTIMESLOTS: 1637154899Srik CE_DEBUG2 (d, ("ioctl: settimeslots\n")); 1638154899Srik /* Only for superuser! */ 1639154899Srik#if __FreeBSD_version < 500000 1640154899Srik error = suser (p); 1641180147Sdds#elif __FreeBSD_version < 700000 1642164033Srwatson error = suser (td); 1643154899Srik#else 1644164033Srwatson error = priv_check (td, PRIV_DRIVER); 1645154899Srik#endif 1646154899Srik if (error) 1647154899Srik return error; 1648154899Srik if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 1649154899Srik return EINVAL; 1650154899Srik s = splimp (); 1651154899Srik CE_LOCK (bd); 1652154899Srik ce_set_ts (c, *(u_long*)data); 1653154899Srik CE_UNLOCK (bd); 1654154899Srik splx (s); 1655154899Srik return 0; 1656154899Srik 1657154899Srik case SERIAL_GETHIGAIN: 1658154899Srik CE_DEBUG2 (d, ("ioctl: gethigain\n")); 1659154899Srik if (c->type != T_E1) 1660154899Srik return EINVAL; 1661154899Srik *(int*)data = c->higain; 1662154899Srik return 0; 1663154899Srik 1664154899Srik case SERIAL_SETHIGAIN: 1665154899Srik CE_DEBUG2 (d, ("ioctl: sethigain\n")); 1666154899Srik if (c->type != T_E1) 1667154899Srik return EINVAL; 1668154899Srik /* Only for superuser! */ 1669154899Srik#if __FreeBSD_version < 500000 1670154899Srik error = suser (p); 1671180147Sdds#elif __FreeBSD_version < 700000 1672164033Srwatson error = suser (td); 1673154899Srik#else 1674164033Srwatson error = priv_check (td, PRIV_DRIVER); 1675154899Srik#endif 1676154899Srik if (error) 1677154899Srik return error; 1678154899Srik s = splimp (); 1679154899Srik CE_LOCK (bd); 1680154899Srik ce_set_higain (c, *(int*)data); 1681154899Srik CE_UNLOCK (bd); 1682154899Srik splx (s); 1683154899Srik return 0; 1684154899Srik 1685154899Srik case SERIAL_GETPHONY: 1686154899Srik CE_DEBUG2 (d, ("ioctl: getphony\n")); 1687154899Srik *(int*)data = c->phony; 1688154899Srik return 0; 1689154899Srik 1690154899Srik case SERIAL_SETPHONY: 1691154899Srik CE_DEBUG2 (d, ("ioctl: setphony\n")); 1692154899Srik /* Only for superuser! */ 1693154899Srik#if __FreeBSD_version < 500000 1694154899Srik error = suser (p); 1695180147Sdds#elif __FreeBSD_version < 700000 1696164033Srwatson error = suser (td); 1697154899Srik#else 1698164033Srwatson error = priv_check (td, PRIV_DRIVER); 1699154899Srik#endif 1700154899Srik if (error) 1701154899Srik return error; 1702154899Srik s = splimp (); 1703154899Srik CE_LOCK (bd); 1704154899Srik ce_set_phony (c, *(int*)data); 1705154899Srik CE_UNLOCK (bd); 1706154899Srik splx (s); 1707154899Srik return 0; 1708154899Srik 1709154899Srik case SERIAL_GETUNFRAM: 1710154899Srik CE_DEBUG2 (d, ("ioctl: getunfram\n")); 1711154899Srik if (c->type != T_E1 || c->num != 0) 1712154899Srik return EINVAL; 1713154899Srik *(int*)data = c->unfram; 1714154899Srik return 0; 1715154899Srik 1716154899Srik case SERIAL_SETUNFRAM: 1717154899Srik CE_DEBUG2 (d, ("ioctl: setunfram\n")); 1718154899Srik if (c->type != T_E1 || c->num != 0) 1719154899Srik return EINVAL; 1720154899Srik /* Only for superuser! */ 1721154899Srik#if __FreeBSD_version < 500000 1722154899Srik error = suser (p); 1723180147Sdds#elif __FreeBSD_version < 700000 1724164033Srwatson error = suser (td); 1725154899Srik#else 1726164033Srwatson error = priv_check (td, PRIV_DRIVER); 1727154899Srik#endif 1728154899Srik if (error) 1729154899Srik return error; 1730154899Srik s = splimp (); 1731154899Srik CE_LOCK (bd); 1732154899Srik ce_set_unfram (c, *(int*)data); 1733154899Srik CE_UNLOCK (bd); 1734154899Srik splx (s); 1735154899Srik return 0; 1736154899Srik 1737154899Srik case SERIAL_GETSCRAMBLER: 1738154899Srik CE_DEBUG2 (d, ("ioctl: getscrambler\n")); 1739154899Srik if (!c->unfram) 1740154899Srik return EINVAL; 1741154899Srik *(int*)data = c->scrambler; 1742154899Srik return 0; 1743154899Srik 1744154899Srik case SERIAL_SETSCRAMBLER: 1745154899Srik CE_DEBUG2 (d, ("ioctl: setscrambler\n")); 1746154899Srik /* Only for superuser! */ 1747154899Srik#if __FreeBSD_version < 500000 1748154899Srik error = suser (p); 1749180147Sdds#elif __FreeBSD_version < 700000 1750164033Srwatson error = suser (td); 1751154899Srik#else 1752164033Srwatson error = priv_check (td, PRIV_DRIVER); 1753154899Srik#endif 1754154899Srik if (error) 1755154899Srik return error; 1756154899Srik if (!c->unfram) 1757154899Srik return EINVAL; 1758154899Srik s = splimp (); 1759154899Srik CE_LOCK (bd); 1760154899Srik ce_set_scrambler (c, *(int*)data); 1761154899Srik CE_UNLOCK (bd); 1762154899Srik splx (s); 1763154899Srik return 0; 1764154899Srik 1765154899Srik case SERIAL_GETMONITOR: 1766154899Srik CE_DEBUG2 (d, ("ioctl: getmonitor\n")); 1767154899Srik if (c->type != T_E1) 1768154899Srik return EINVAL; 1769154899Srik *(int*)data = c->monitor; 1770154899Srik return 0; 1771154899Srik 1772154899Srik case SERIAL_SETMONITOR: 1773154899Srik CE_DEBUG2 (d, ("ioctl: setmonitor\n")); 1774154899Srik /* Only for superuser! */ 1775154899Srik#if __FreeBSD_version < 500000 1776154899Srik error = suser (p); 1777180147Sdds#elif __FreeBSD_version < 700000 1778164033Srwatson error = suser (td); 1779154899Srik#else 1780164033Srwatson error = priv_check (td, PRIV_DRIVER); 1781154899Srik#endif 1782154899Srik if (error) 1783154899Srik return error; 1784154899Srik if (c->type != T_E1) 1785154899Srik return EINVAL; 1786154899Srik s = splimp (); 1787154899Srik CE_LOCK (bd); 1788154899Srik ce_set_monitor (c, *(int*)data); 1789154899Srik CE_UNLOCK (bd); 1790154899Srik splx (s); 1791154899Srik return 0; 1792154899Srik 1793154899Srik case SERIAL_GETUSE16: 1794154899Srik CE_DEBUG2 (d, ("ioctl: getuse16\n")); 1795154899Srik if (c->type != T_E1 || c->unfram) 1796154899Srik return EINVAL; 1797154899Srik *(int*)data = c->use16; 1798154899Srik return 0; 1799154899Srik 1800154899Srik case SERIAL_SETUSE16: 1801154899Srik CE_DEBUG2 (d, ("ioctl: setuse16\n")); 1802154899Srik /* Only for superuser! */ 1803154899Srik#if __FreeBSD_version < 500000 1804154899Srik error = suser (p); 1805180147Sdds#elif __FreeBSD_version < 700000 1806164033Srwatson error = suser (td); 1807154899Srik#else 1808164033Srwatson error = priv_check (td, PRIV_DRIVER); 1809154899Srik#endif 1810154899Srik if (error) 1811154899Srik return error; 1812154899Srik if (c->type != T_E1) 1813154899Srik return EINVAL; 1814154899Srik s = splimp (); 1815154899Srik CE_LOCK (bd); 1816154899Srik ce_set_use16 (c, *(int*)data); 1817154899Srik CE_UNLOCK (bd); 1818154899Srik splx (s); 1819154899Srik return 0; 1820154899Srik 1821154899Srik case SERIAL_GETCRC4: 1822154899Srik CE_DEBUG2 (d, ("ioctl: getcrc4\n")); 1823154899Srik if (c->type != T_E1 || c->unfram) 1824154899Srik return EINVAL; 1825154899Srik *(int*)data = c->crc4; 1826154899Srik return 0; 1827154899Srik 1828154899Srik case SERIAL_SETCRC4: 1829154899Srik CE_DEBUG2 (d, ("ioctl: setcrc4\n")); 1830154899Srik /* Only for superuser! */ 1831154899Srik#if __FreeBSD_version < 500000 1832154899Srik error = suser (p); 1833180147Sdds#elif __FreeBSD_version < 700000 1834164033Srwatson error = suser (td); 1835154899Srik#else 1836164033Srwatson error = priv_check (td, PRIV_DRIVER); 1837154899Srik#endif 1838154899Srik if (error) 1839154899Srik return error; 1840154899Srik if (c->type != T_E1 || c->unfram) 1841154899Srik return EINVAL; 1842154899Srik s = splimp (); 1843154899Srik CE_LOCK (bd); 1844154899Srik ce_set_crc4 (c, *(int*)data); 1845154899Srik CE_UNLOCK (bd); 1846154899Srik splx (s); 1847154899Srik return 0; 1848154899Srik 1849154899Srik case SERIAL_GETCLK: 1850154899Srik CE_DEBUG2 (d, ("ioctl: getclk\n")); 1851154899Srik if (c->type != T_E1) 1852154899Srik return EINVAL; 1853154899Srik switch (c->gsyn) { 1854154899Srik default: *(int*)data = E1CLK_INTERNAL; break; 1855154899Srik case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 1856154899Srik case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 1857154899Srik case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 1858154899Srik } 1859154899Srik return 0; 1860154899Srik 1861154899Srik case SERIAL_SETCLK: 1862154899Srik CE_DEBUG2 (d, ("ioctl: setclk\n")); 1863154899Srik /* Only for superuser! */ 1864154899Srik#if __FreeBSD_version < 500000 1865154899Srik error = suser (p); 1866180147Sdds#elif __FreeBSD_version < 700000 1867164033Srwatson error = suser (td); 1868154899Srik#else 1869164033Srwatson error = priv_check (td, PRIV_DRIVER); 1870154899Srik#endif 1871154899Srik if (error) 1872154899Srik return error; 1873154899Srik if (c->type != T_E1) 1874154899Srik return EINVAL; 1875154899Srik s = splimp (); 1876154899Srik CE_LOCK (bd); 1877154899Srik switch (*(int*)data) { 1878154899Srik default: ce_set_gsyn (c, GSYN_INT); break; 1879154899Srik case E1CLK_RECEIVE: ce_set_gsyn (c, GSYN_RCV); break; 1880154899Srik case E1CLK_RECEIVE_CHAN0: ce_set_gsyn (c, GSYN_RCV0); break; 1881154899Srik case E1CLK_RECEIVE_CHAN1: ce_set_gsyn (c, GSYN_RCV1); break; 1882154899Srik } 1883154899Srik CE_UNLOCK (bd); 1884154899Srik splx (s); 1885154899Srik return 0; 1886154899Srik 1887154899Srik#if 0 1888154899Srik case SERIAL_RESET: 1889154899Srik CE_DEBUG2 (d, ("ioctl: reset\n")); 1890154899Srik /* Only for superuser! */ 1891154899Srik#if __FreeBSD_version < 500000 1892154899Srik error = suser (p); 1893180147Sdds#elif __FreeBSD_version < 700000 1894164033Srwatson error = suser (td); 1895154899Srik#else 1896164033Srwatson error = priv_check (td, PRIV_DRIVER); 1897154899Srik#endif 1898154899Srik if (error) 1899154899Srik return error; 1900154899Srik s = splimp (); 1901154899Srik CE_LOCK (bd); 1902154899Srik/* ce_reset (c->board, 0, 0);*/ 1903154899Srik CE_UNLOCK (bd); 1904154899Srik splx (s); 1905154899Srik return 0; 1906154899Srik 1907154899Srik case SERIAL_HARDRESET: 1908154899Srik CE_DEBUG2 (d, ("ioctl: hardreset\n")); 1909154899Srik /* Only for superuser! */ 1910154899Srik#if __FreeBSD_version < 500000 1911154899Srik error = suser (p); 1912180147Sdds#elif __FreeBSD_version < 700000 1913164033Srwatson error = suser (td); 1914154899Srik#else 1915164033Srwatson error = priv_check (td, PRIV_DRIVER); 1916154899Srik#endif 1917154899Srik if (error) 1918154899Srik return error; 1919154899Srik s = splimp (); 1920154899Srik CE_LOCK (bd); 1921154899Srik /* hard_reset (c->board); */ 1922154899Srik CE_UNLOCK (bd); 1923154899Srik splx (s); 1924154899Srik return 0; 1925154899Srik#endif 1926154899Srik 1927154899Srik case SERIAL_GETCABLE: 1928154899Srik CE_DEBUG2 (d, ("ioctl: getcable\n")); 1929154899Srik if (c->type != T_E1) 1930154899Srik return EINVAL; 1931154899Srik s = splimp (); 1932154899Srik CE_LOCK (bd); 1933154899Srik *(int*)data = CABLE_TP; 1934154899Srik CE_UNLOCK (bd); 1935154899Srik splx (s); 1936154899Srik return 0; 1937154899Srik 1938154899Srik case SERIAL_GETDIR: 1939154899Srik CE_DEBUG2 (d, ("ioctl: getdir\n")); 1940154899Srik if (c->type != T_E1 && c->type != T_DATA) 1941154899Srik return EINVAL; 1942154899Srik *(int*)data = c->dir; 1943154899Srik return 0; 1944154899Srik 1945154899Srik case SERIAL_SETDIR: 1946154899Srik CE_DEBUG2 (d, ("ioctl: setdir\n")); 1947154899Srik /* Only for superuser! */ 1948154899Srik#if __FreeBSD_version < 500000 1949154899Srik error = suser (p); 1950180147Sdds#elif __FreeBSD_version < 700000 1951164033Srwatson error = suser (td); 1952154899Srik#else 1953164033Srwatson error = priv_check (td, PRIV_DRIVER); 1954154899Srik#endif 1955154899Srik if (error) 1956154899Srik return error; 1957154899Srik s = splimp (); 1958154899Srik CE_LOCK (bd); 1959154899Srik ce_set_dir (c, *(int*)data); 1960154899Srik CE_UNLOCK (bd); 1961154899Srik splx (s); 1962154899Srik return 0; 1963154899Srik 1964154899Srik case TIOCSDTR: /* Set DTR */ 1965154899Srik s = splimp (); 1966154899Srik CE_LOCK (bd); 1967154899Srik ce_set_dtr (c, 1); 1968154899Srik CE_UNLOCK (bd); 1969154899Srik splx (s); 1970154899Srik return 0; 1971154899Srik 1972154899Srik case TIOCCDTR: /* Clear DTR */ 1973154899Srik s = splimp (); 1974154899Srik CE_LOCK (bd); 1975154899Srik ce_set_dtr (c, 0); 1976154899Srik CE_UNLOCK (bd); 1977154899Srik splx (s); 1978154899Srik return 0; 1979154899Srik 1980154899Srik case TIOCMSET: /* Set DTR/RTS */ 1981154899Srik s = splimp (); 1982154899Srik CE_LOCK (bd); 1983154899Srik ce_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1984154899Srik ce_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1985154899Srik CE_UNLOCK (bd); 1986154899Srik splx (s); 1987154899Srik return 0; 1988154899Srik 1989154899Srik case TIOCMBIS: /* Add DTR/RTS */ 1990154899Srik s = splimp (); 1991154899Srik CE_LOCK (bd); 1992154899Srik if (*(int*)data & TIOCM_DTR) ce_set_dtr (c, 1); 1993154899Srik if (*(int*)data & TIOCM_RTS) ce_set_rts (c, 1); 1994154899Srik CE_UNLOCK (bd); 1995154899Srik splx (s); 1996154899Srik return 0; 1997154899Srik 1998154899Srik case TIOCMBIC: /* Clear DTR/RTS */ 1999154899Srik s = splimp (); 2000154899Srik CE_LOCK (bd); 2001154899Srik if (*(int*)data & TIOCM_DTR) ce_set_dtr (c, 0); 2002154899Srik if (*(int*)data & TIOCM_RTS) ce_set_rts (c, 0); 2003154899Srik CE_UNLOCK (bd); 2004154899Srik splx (s); 2005154899Srik return 0; 2006154899Srik 2007154899Srik case TIOCMGET: /* Get modem status */ 2008154899Srik *(int*)data = ce_modem_status (c); 2009154899Srik return 0; 2010154899Srik } 2011154899Srik return ENOTTY; 2012154899Srik} 2013154899Srik 2014154899Srik#ifdef NETGRAPH 2015154899Srik#if __FreeBSD_version >= 500000 2016154899Srikstatic int ng_ce_constructor (node_p node) 2017154899Srik{ 2018154899Srik drv_t *d = NG_NODE_PRIVATE (node); 2019154899Srik#else 2020154899Srikstatic int ng_ce_constructor (node_p *node) 2021154899Srik{ 2022154899Srik drv_t *d = (*node)->private; 2023154899Srik#endif 2024154899Srik CE_DEBUG (d, ("Constructor\n")); 2025154899Srik return EINVAL; 2026154899Srik} 2027154899Srik 2028154899Srikstatic int ng_ce_newhook (node_p node, hook_p hook, const char *name) 2029154899Srik{ 2030154899Srik int s; 2031154899Srik#if __FreeBSD_version >= 500000 2032154899Srik drv_t *d = NG_NODE_PRIVATE (node); 2033154899Srik#else 2034154899Srik drv_t *d = node->private; 2035154899Srik#endif 2036154899Srik bdrv_t *bd = d->board->sys; 2037154899Srik 2038154899Srik CE_DEBUG (d, ("Newhook\n")); 2039154899Srik /* Attach debug hook */ 2040154899Srik if (strcmp (name, NG_CE_HOOK_DEBUG) == 0) { 2041154899Srik#if __FreeBSD_version >= 500000 2042154899Srik NG_HOOK_SET_PRIVATE (hook, NULL); 2043154899Srik#else 2044154899Srik hook->private = 0; 2045154899Srik#endif 2046154899Srik d->debug_hook = hook; 2047154899Srik return 0; 2048154899Srik } 2049154899Srik 2050154899Srik /* Check for raw hook */ 2051154899Srik if (strcmp (name, NG_CE_HOOK_RAW) != 0) 2052154899Srik return EINVAL; 2053154899Srik 2054154899Srik#if __FreeBSD_version >= 500000 2055154899Srik NG_HOOK_SET_PRIVATE (hook, d); 2056154899Srik#else 2057154899Srik hook->private = d; 2058154899Srik#endif 2059154899Srik d->hook = hook; 2060154899Srik s = splimp (); 2061154899Srik CE_LOCK (bd); 2062154899Srik ce_up (d); 2063154899Srik CE_UNLOCK (bd); 2064154899Srik splx (s); 2065154899Srik return 0; 2066154899Srik} 2067154899Srik 2068154899Srikstatic char *format_timeslots (u_long s) 2069154899Srik{ 2070154899Srik static char buf [100]; 2071154899Srik char *p = buf; 2072154899Srik int i; 2073154899Srik 2074154899Srik for (i=1; i<32; ++i) 2075154899Srik if ((s >> i) & 1) { 2076154899Srik int prev = (i > 1) & (s >> (i-1)); 2077154899Srik int next = (i < 31) & (s >> (i+1)); 2078154899Srik 2079154899Srik if (prev) { 2080154899Srik if (next) 2081154899Srik continue; 2082154899Srik *p++ = '-'; 2083154899Srik } else if (p > buf) 2084154899Srik *p++ = ','; 2085154899Srik 2086154899Srik if (i >= 10) 2087154899Srik *p++ = '0' + i / 10; 2088154899Srik *p++ = '0' + i % 10; 2089154899Srik } 2090154899Srik *p = 0; 2091154899Srik return buf; 2092154899Srik} 2093154899Srik 2094154899Srikstatic int print_modems (char *s, ce_chan_t *c, int need_header) 2095154899Srik{ 2096154899Srik int status = ce_modem_status (c); 2097154899Srik int length = 0; 2098154899Srik 2099154899Srik if (need_header) 2100154899Srik length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 2101154899Srik length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 2102154899Srik status & TIOCM_LE ? "On" : "-", 2103154899Srik status & TIOCM_DTR ? "On" : "-", 2104154899Srik status & TIOCM_DSR ? "On" : "-", 2105154899Srik status & TIOCM_RTS ? "On" : "-", 2106154899Srik status & TIOCM_CTS ? "On" : "-", 2107154899Srik status & TIOCM_CD ? "On" : "-"); 2108154899Srik return length; 2109154899Srik} 2110154899Srik 2111154899Srikstatic int print_stats (char *s, ce_chan_t *c, int need_header) 2112154899Srik{ 2113154899Srik int length = 0; 2114154899Srik 2115154899Srik if (need_header) 2116154899Srik length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 2117154899Srik length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 2118154899Srik c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 2119154899Srik c->ipkts, c->overrun + c->frame + c->crc, 2120154899Srik (unsigned long) c->obytes, c->opkts, c->underrun); 2121154899Srik return length; 2122154899Srik} 2123154899Srik 2124154899Srikstatic char *format_e1_status (u_char status) 2125154899Srik{ 2126154899Srik static char buf [80]; 2127154899Srik 2128154899Srik if (status & E1_NOALARM) 2129154899Srik return "Ok"; 2130154899Srik buf[0] = 0; 2131154899Srik if (status & E1_LOS) strcat (buf, ",LOS"); 2132154899Srik if (status & E1_AIS) strcat (buf, ",AIS"); 2133154899Srik if (status & E1_LOF) strcat (buf, ",LOF"); 2134154899Srik if (status & E1_LOMF) strcat (buf, ",LOMF"); 2135154899Srik if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 2136154899Srik if (status & E1_AIS16) strcat (buf, ",AIS16"); 2137154899Srik if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 2138154899Srik if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 2139154899Srik if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 2140154899Srik if (buf[0] == ',') 2141154899Srik return buf+1; 2142154899Srik return "Unknown"; 2143154899Srik} 2144154899Srik 2145154899Srikstatic int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 2146154899Srik{ 2147154899Srik int n, length = 0; 2148154899Srik 2149154899Srik if (numerator < 1 || divider < 1) { 2150154899Srik length += sprintf (s+length, leftalign ? "/- " : " -"); 2151154899Srik return length; 2152154899Srik } 2153154899Srik n = (int) (0.5 + 1000.0 * numerator / divider); 2154154899Srik if (n < 1000) { 2155154899Srik length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 2156154899Srik return length; 2157154899Srik } 2158154899Srik *(s + length) = leftalign ? '/' : ' '; 2159154899Srik length ++; 2160154899Srik 2161154899Srik if (n >= 1000000) n = (n+500) / 1000 * 1000; 2162154899Srik else if (n >= 100000) n = (n+50) / 100 * 100; 2163154899Srik else if (n >= 10000) n = (n+5) / 10 * 10; 2164154899Srik 2165154899Srik switch (n) { 2166154899Srik case 1000: length += printf (s+length, ".999"); return length; 2167154899Srik case 10000: n = 9990; break; 2168154899Srik case 100000: n = 99900; break; 2169154899Srik case 1000000: n = 999000; break; 2170154899Srik } 2171154899Srik if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 2172154899Srik else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 2173154899Srik else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 2174154899Srik else length += sprintf (s+length, "%d", n/1000); 2175154899Srik 2176154899Srik return length; 2177154899Srik} 2178154899Srik 2179154899Srikstatic int print_e1_stats (char *s, ce_chan_t *c) 2180154899Srik{ 2181154899Srik struct e1_counters total; 2182154899Srik u_long totsec; 2183154899Srik int length = 0; 2184154899Srik 2185154899Srik totsec = c->totsec + c->cursec; 2186154899Srik total.bpv = c->total.bpv + c->currnt.bpv; 2187154899Srik total.fse = c->total.fse + c->currnt.fse; 2188154899Srik total.crce = c->total.crce + c->currnt.crce; 2189154899Srik total.rcrce = c->total.rcrce + c->currnt.rcrce; 2190154899Srik total.uas = c->total.uas + c->currnt.uas; 2191154899Srik total.les = c->total.les + c->currnt.les; 2192154899Srik total.es = c->total.es + c->currnt.es; 2193154899Srik total.bes = c->total.bes + c->currnt.bes; 2194154899Srik total.ses = c->total.ses + c->currnt.ses; 2195154899Srik total.oofs = c->total.oofs + c->currnt.oofs; 2196154899Srik total.css = c->total.css + c->currnt.css; 2197154899Srik total.dm = c->total.dm + c->currnt.dm; 2198154899Srik 2199154899Srik length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 2200154899Srik 2201154899Srik /* Unavailable seconds, degraded minutes */ 2202154899Srik length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 2203154899Srik length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 2204154899Srik 2205154899Srik /* Bipolar violations, frame sync errors */ 2206154899Srik length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 2207154899Srik length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 2208154899Srik 2209154899Srik /* CRC errors, remote CRC errors (E-bit) */ 2210154899Srik length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 2211154899Srik length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 2212154899Srik 2213154899Srik /* Errored seconds, line errored seconds */ 2214154899Srik length += print_frac (s + length, 0, c->currnt.es, c->cursec); 2215154899Srik length += print_frac (s + length, 1, c->currnt.les, c->cursec); 2216154899Srik 2217154899Srik /* Severely errored seconds, burst errored seconds */ 2218154899Srik length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 2219154899Srik length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 2220154899Srik 2221154899Srik /* Out of frame seconds, controlled slip seconds */ 2222154899Srik length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 2223154899Srik length += print_frac (s + length, 1, c->currnt.css, c->cursec); 2224154899Srik 2225154899Srik length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 2226154899Srik 2227154899Srik /* Print total statistics. */ 2228154899Srik length += print_frac (s + length, 0, total.uas, totsec); 2229154899Srik length += print_frac (s + length, 1, 60 * total.dm, totsec); 2230154899Srik 2231154899Srik length += print_frac (s + length, 0, total.bpv, totsec); 2232154899Srik length += print_frac (s + length, 1, total.fse, totsec); 2233154899Srik 2234154899Srik length += print_frac (s + length, 0, total.crce, totsec); 2235154899Srik length += print_frac (s + length, 1, total.rcrce, totsec); 2236154899Srik 2237154899Srik length += print_frac (s + length, 0, total.es, totsec); 2238154899Srik length += print_frac (s + length, 1, total.les, totsec); 2239154899Srik 2240154899Srik length += print_frac (s + length, 0, total.ses, totsec); 2241154899Srik length += print_frac (s + length, 1, total.bes, totsec); 2242154899Srik 2243154899Srik length += print_frac (s + length, 0, total.oofs, totsec); 2244154899Srik length += print_frac (s + length, 1, total.css, totsec); 2245154899Srik 2246154899Srik length += sprintf (s + length, " -- Total\n"); 2247154899Srik return length; 2248154899Srik} 2249154899Srik 2250154899Srikstatic int print_chan (char *s, ce_chan_t *c) 2251154899Srik{ 2252154899Srik drv_t *d = c->sys; 2253154899Srik int length = 0; 2254154899Srik 2255154899Srik length += sprintf (s + length, "ce%d", c->board->num * NCHAN + c->num); 2256154899Srik if (d->chan->debug) 2257154899Srik length += sprintf (s + length, " debug=%d", d->chan->debug); 2258154899Srik 2259154899Srik if (c->board->mux) { 2260154899Srik length += sprintf (s + length, " cfg=C"); 2261154899Srik } else { 2262154899Srik length += sprintf (s + length, " cfg=A"); 2263154899Srik } 2264154899Srik 2265154899Srik if (c->baud) 2266154899Srik length += sprintf (s + length, " %ld", c->baud); 2267154899Srik else 2268154899Srik length += sprintf (s + length, " extclock"); 2269154899Srik 2270154899Srik if (c->type == T_E1) 2271154899Srik switch (c->gsyn) { 2272154899Srik case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 2273154899Srik case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 2274154899Srik case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 2275154899Srik case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 2276154899Srik } 2277154899Srik if (c->type == T_E1) 2278154899Srik length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 2279154899Srik 2280154899Srik length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 2281154899Srik 2282154899Srik if (c->type == T_E1) 2283154899Srik length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 2284154899Srik length += sprintf (s + length, "\n"); 2285154899Srik return length; 2286154899Srik} 2287154899Srik 2288154899Srik#if __FreeBSD_version >= 500000 2289154899Srikstatic int ng_ce_rcvmsg (node_p node, item_p item, hook_p lasthook) 2290154899Srik{ 2291154899Srik drv_t *d = NG_NODE_PRIVATE (node); 2292154899Srik struct ng_mesg *msg; 2293154899Srik#else 2294154899Srikstatic int ng_ce_rcvmsg (node_p node, struct ng_mesg *msg, 2295154899Srik const char *retaddr, struct ng_mesg **rptr) 2296154899Srik{ 2297154899Srik drv_t *d = node->private; 2298154899Srik#endif 2299154899Srik struct ng_mesg *resp = NULL; 2300154899Srik int error = 0; 2301154899Srik 2302154899Srik CE_DEBUG (d, ("Rcvmsg\n")); 2303154899Srik#if __FreeBSD_version >= 500000 2304154899Srik NGI_GET_MSG (item, msg); 2305154899Srik#endif 2306154899Srik switch (msg->header.typecookie) { 2307154899Srik default: 2308154899Srik error = EINVAL; 2309154899Srik break; 2310154899Srik 2311154899Srik case NGM_CE_COOKIE: 2312154899Srik printf ("Not implemented yet\n"); 2313154899Srik error = EINVAL; 2314154899Srik break; 2315154899Srik 2316154899Srik case NGM_GENERIC_COOKIE: 2317154899Srik switch (msg->header.cmd) { 2318154899Srik default: 2319154899Srik error = EINVAL; 2320154899Srik break; 2321154899Srik 2322154899Srik case NGM_TEXT_STATUS: { 2323154899Srik char *s; 2324154899Srik int l = 0; 2325154899Srik int dl = sizeof (struct ng_mesg) + 730; 2326154899Srik 2327154899Srik#if __FreeBSD_version >= 500000 2328154899Srik NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2329154899Srik if (! resp) { 2330154899Srik error = ENOMEM; 2331154899Srik break; 2332154899Srik } 2333154899Srik#else 2334184205Sdes resp = malloc (M_NETGRAPH, M_NOWAIT); 2335154899Srik if (! resp) { 2336154899Srik error = ENOMEM; 2337154899Srik break; 2338154899Srik } 2339154899Srik bzero (resp, dl); 2340154899Srik#endif 2341154899Srik s = (resp)->data; 2342154899Srik if (d) { 2343154899Srik l += print_chan (s + l, d->chan); 2344154899Srik l += print_stats (s + l, d->chan, 1); 2345154899Srik l += print_modems (s + l, d->chan, 1); 2346154899Srik l += print_e1_stats (s + l, d->chan); 2347154899Srik } else 2348154899Srik l += sprintf (s + l, "Error: node not connect to channel"); 2349154899Srik#if __FreeBSD_version < 500000 2350154899Srik (resp)->header.version = NG_VERSION; 2351154899Srik (resp)->header.arglen = strlen (s) + 1; 2352154899Srik (resp)->header.token = msg->header.token; 2353154899Srik (resp)->header.typecookie = NGM_CE_COOKIE; 2354154899Srik (resp)->header.cmd = msg->header.cmd; 2355154899Srik#endif 2356193813Simp strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRSIZ); 2357154899Srik } 2358154899Srik break; 2359154899Srik } 2360154899Srik break; 2361154899Srik } 2362154899Srik#if __FreeBSD_version >= 500000 2363154899Srik NG_RESPOND_MSG (error, node, item, resp); 2364154899Srik NG_FREE_MSG (msg); 2365154899Srik#else 2366154899Srik *rptr = resp; 2367184205Sdes free (msg, M_NETGRAPH); 2368154899Srik#endif 2369154899Srik return error; 2370154899Srik} 2371154899Srik 2372154899Srik#if __FreeBSD_version >= 500000 2373154899Srikstatic int ng_ce_rcvdata (hook_p hook, item_p item) 2374154899Srik{ 2375154899Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2376154899Srik struct mbuf *m; 2377154899Srik#if __FreeBSD_version < 502120 2378154899Srik meta_p meta; 2379154899Srik#else 2380154899Srik struct ng_tag_prio *ptag; 2381154899Srik#endif 2382154899Srik#else 2383154899Srikstatic int ng_ce_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) 2384154899Srik{ 2385154899Srik drv_t *d = hook->node->private; 2386154899Srik#endif 2387154899Srik bdrv_t *bd = d->board->sys; 2388154899Srik struct ifqueue *q; 2389154899Srik int s; 2390154899Srik 2391154899Srik CE_DEBUG2 (d, ("Rcvdata\n")); 2392154899Srik#if __FreeBSD_version >= 500000 2393154899Srik NGI_GET_M (item, m); 2394154899Srik#if __FreeBSD_version < 502120 2395154899Srik NGI_GET_META (item, meta); 2396154899Srik#endif 2397154899Srik NG_FREE_ITEM (item); 2398154899Srik if (! NG_HOOK_PRIVATE (hook) || ! d) { 2399154899Srik NG_FREE_M (m); 2400154899Srik#if __FreeBSD_version < 502120 2401154899Srik NG_FREE_META (meta); 2402154899Srik#endif 2403154899Srik#else 2404154899Srik if (! hook->private || ! d) { 2405154899Srik NG_FREE_DATA (m,meta); 2406154899Srik#endif 2407154899Srik return ENETDOWN; 2408154899Srik } 2409154899Srik 2410154899Srik#if __FreeBSD_version >= 502120 2411154899Srik /* Check for high priority data */ 2412154899Srik if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2413154899Srik NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2414154899Srik q = &d->hi_queue; 2415154899Srik else 2416154899Srik q = &d->queue; 2417154899Srik#else 2418154899Srik q = (meta && meta->priority > 0) ? &d->hi_queue : &d->queue; 2419154899Srik#endif 2420154899Srik 2421154899Srik s = splimp (); 2422154899Srik CE_LOCK (bd); 2423154899Srik#if __FreeBSD_version >= 500000 2424154899Srik IF_LOCK (q); 2425154899Srik if (_IF_QFULL (q)) { 2426154899Srik _IF_DROP (q); 2427154899Srik IF_UNLOCK (q); 2428154899Srik CE_UNLOCK (bd); 2429154899Srik splx (s); 2430154899Srik NG_FREE_M (m); 2431154899Srik#if __FreeBSD_version < 502120 2432154899Srik NG_FREE_META (meta); 2433154899Srik#endif 2434154899Srik return ENOBUFS; 2435154899Srik } 2436154899Srik _IF_ENQUEUE (q, m); 2437154899Srik IF_UNLOCK (q); 2438154899Srik#else 2439154899Srik if (IF_QFULL (q)) { 2440154899Srik IF_DROP (q); 2441154899Srik CE_UNLOCK (bd); 2442154899Srik splx (s); 2443154899Srik NG_FREE_DATA (m, meta); 2444154899Srik return ENOBUFS; 2445154899Srik } 2446154899Srik IF_ENQUEUE (q, m); 2447154899Srik#endif 2448154899Srik ce_start (d); 2449154899Srik CE_UNLOCK (bd); 2450154899Srik splx (s); 2451154899Srik return 0; 2452154899Srik} 2453154899Srik 2454154899Srikstatic int ng_ce_rmnode (node_p node) 2455154899Srik{ 2456154899Srik#if __FreeBSD_version >= 500000 2457154899Srik drv_t *d = NG_NODE_PRIVATE (node); 2458154899Srik 2459154899Srik CE_DEBUG (d, ("Rmnode\n")); 2460154899Srik if (d && d->running) { 2461154899Srik bdrv_t *bd = d->board->sys; 2462154899Srik int s = splimp (); 2463154899Srik CE_LOCK (bd); 2464154899Srik ce_down (d); 2465154899Srik CE_UNLOCK (bd); 2466154899Srik splx (s); 2467154899Srik } 2468154899Srik#ifdef KLD_MODULE 2469154899Srik#if __FreeBSD_version >= 502120 2470154899Srik if (node->nd_flags & NGF_REALLY_DIE) { 2471154899Srik#else 2472154899Srik if (node->nd_flags & NG_REALLY_DIE) { 2473154899Srik#endif 2474154899Srik NG_NODE_SET_PRIVATE (node, NULL); 2475154899Srik NG_NODE_UNREF (node); 2476154899Srik } 2477154899Srik#if __FreeBSD_version >= 502120 2478154899Srik NG_NODE_REVIVE(node); /* Persistant node */ 2479154899Srik#else 2480154899Srik node->nd_flags &= ~NG_INVALID; 2481154899Srik#endif 2482154899Srik#endif 2483154899Srik#else /* __FreeBSD_version < 500000 */ 2484154899Srik drv_t *d = node->private; 2485154899Srik 2486154899Srik if (d && d->running) { 2487154899Srik bdrv_t *bd = d->board->sys; 2488154899Srik int s = splimp (); 2489154899Srik CE_LOCK (bd); 2490154899Srik ce_down (d); 2491154899Srik CE_UNLOCK (bd); 2492154899Srik splx (s); 2493154899Srik } 2494154899Srik 2495154899Srik node->flags |= NG_INVALID; 2496154899Srik ng_cutlinks (node); 2497154899Srik#ifdef KLD_MODULE 2498154899Srik ng_unname (node); 2499154899Srik ng_unref (node); 2500154899Srik#endif 2501154899Srik#endif 2502154899Srik return 0; 2503154899Srik} 2504154899Srik 2505154899Srikstatic int ng_ce_connect (hook_p hook) 2506154899Srik{ 2507154899Srik#if __FreeBSD_version >= 500000 2508154899Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2509154899Srik#else 2510154899Srik drv_t *d = hook->node->private; 2511154899Srik#endif 2512154899Srik 2513154899Srik if (d) { 2514154899Srik CE_DEBUG (d, ("Connect\n")); 2515199407Sjhb callout_reset (&d->timeout_handle, hz, ce_watchdog_timer, d); 2516154899Srik } 2517154899Srik 2518154899Srik return 0; 2519154899Srik} 2520154899Srik 2521154899Srikstatic int ng_ce_disconnect (hook_p hook) 2522154899Srik{ 2523154899Srik#if __FreeBSD_version >= 500000 2524154899Srik drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2525154899Srik#else 2526154899Srik drv_t *d = hook->node->private; 2527154899Srik#endif 2528154899Srik 2529154899Srik if (d) { 2530154899Srik CE_DEBUG (d, ("Disconnect\n")); 2531154899Srik#if __FreeBSD_version >= 500000 2532154899Srik if (NG_HOOK_PRIVATE (hook)) 2533154899Srik#else 2534154899Srik if (hook->private) 2535154899Srik#endif 2536154899Srik { 2537154899Srik bdrv_t *bd = d->board->sys; 2538154899Srik int s = splimp (); 2539154899Srik CE_LOCK (bd); 2540154899Srik ce_down (d); 2541154899Srik CE_UNLOCK (bd); 2542154899Srik splx (s); 2543154899Srik } 2544154899Srik /* If we were wait it than it reasserted now, just stop it. */ 2545154899Srik if (!callout_drain (&d->timeout_handle)) 2546154899Srik callout_stop (&d->timeout_handle); 2547154899Srik } 2548154899Srik return 0; 2549154899Srik} 2550154899Srik#endif 2551154899Srik 2552154899Srikstatic int ce_modevent (module_t mod, int type, void *unused) 2553154899Srik{ 2554154899Srik#if __FreeBSD_version < 500000 2555154899Srik dev_t dev; 2556154899Srik struct cdevsw *cdsw; 2557154899Srik#endif 2558154899Srik static int load_count = 0; 2559154899Srik 2560154899Srik#if __FreeBSD_version < 500000 2561154899Srik dev = makedev (CDEV_MAJOR, 0); 2562154899Srik#endif 2563154899Srik 2564154899Srik switch (type) { 2565154899Srik case MOD_LOAD: 2566154899Srik#if __FreeBSD_version < 500000 2567154899Srik if (dev != NODEV && 2568154899Srik (cdsw = devsw (dev)) && 2569154899Srik cdsw->d_maj == CDEV_MAJOR) { 2570154899Srik printf ("Tau32-PCI driver is already in system\n"); 2571154899Srik return (ENXIO); 2572154899Srik } 2573154899Srik#endif 2574154899Srik#if __FreeBSD_version >= 500000 && defined NETGRAPH 2575154899Srik if (ng_newtype (&typestruct)) 2576154899Srik printf ("Failed to register ng_ce\n"); 2577154899Srik#endif 2578154899Srik ++load_count; 2579154899Srik#if __FreeBSD_version <= 500000 2580154899Srik cdevsw_add (&ce_cdevsw); 2581154899Srik#endif 2582154899Srik#if __FreeBSD_version >= 500000 2583188663Srwatson callout_init (&timeout_handle, CALLOUT_MPSAFE); 2584154899Srik#else 2585154899Srik callout_init (&timeout_handle); 2586154899Srik#endif 2587154899Srik callout_reset (&timeout_handle, hz*5, ce_timeout, 0); 2588154899Srik break; 2589154899Srik case MOD_UNLOAD: 2590154899Srik if (load_count == 1) { 2591154899Srik printf ("Removing device entry for Tau32-PCI\n"); 2592154899Srik#if __FreeBSD_version <= 500000 2593154899Srik cdevsw_remove (&ce_cdevsw); 2594154899Srik#endif 2595154899Srik#if __FreeBSD_version >= 500000 && defined NETGRAPH 2596154899Srik ng_rmtype (&typestruct); 2597154899Srik#endif 2598154899Srik } 2599154899Srik /* If we were wait it than it reasserted now, just stop it. 2600154899Srik * Actually we shouldn't get this condition. But code could be 2601154899Srik * changed in the future, so just be a litle paranoid. 2602154899Srik */ 2603154899Srik if (!callout_drain (&timeout_handle)) 2604154899Srik callout_stop (&timeout_handle); 2605154899Srik --load_count; 2606154899Srik break; 2607154899Srik case MOD_SHUTDOWN: 2608154899Srik break; 2609154899Srik } 2610154899Srik return 0; 2611154899Srik} 2612154899Srik 2613154899Srik#ifdef NETGRAPH 2614154899Srik#if __FreeBSD_version >= 502100 2615154899Srikstatic struct ng_type typestruct = { 2616154899Srik .version = NG_ABI_VERSION, 2617154899Srik .name = NG_CE_NODE_TYPE, 2618154899Srik .constructor = ng_ce_constructor, 2619154899Srik .rcvmsg = ng_ce_rcvmsg, 2620154899Srik .shutdown = ng_ce_rmnode, 2621154899Srik .newhook = ng_ce_newhook, 2622154899Srik .connect = ng_ce_connect, 2623154899Srik .rcvdata = ng_ce_rcvdata, 2624154899Srik .disconnect = ng_ce_disconnect, 2625154899Srik}; 2626154899Srik#else /* __FreeBSD_version < 502100 */ 2627154899Srikstatic struct ng_type typestruct = { 2628154899Srik#if __FreeBSD_version >= 500000 2629154899Srik NG_ABI_VERSION, 2630154899Srik#else 2631154899Srik NG_VERSION, 2632154899Srik#endif 2633154899Srik NG_CE_NODE_TYPE, 2634154899Srik ce_modevent, 2635154899Srik ng_ce_constructor, 2636154899Srik ng_ce_rcvmsg, 2637154899Srik ng_ce_rmnode, 2638154899Srik ng_ce_newhook, 2639154899Srik NULL, 2640154899Srik ng_ce_connect, 2641154899Srik ng_ce_rcvdata, 2642154899Srik#if __FreeBSD_version < 500000 2643154899Srik NULL, 2644154899Srik#endif 2645154899Srik ng_ce_disconnect, 2646154899Srik NULL 2647154899Srik}; 2648154899Srik#endif /* __FreeBSD_version < 502100 */ 2649154899Srik 2650154899Srik#endif /*NETGRAPH*/ 2651154899Srik 2652154899Srik#if __FreeBSD_version >= 500000 2653154899Srik#ifdef NETGRAPH 2654154899SrikMODULE_DEPEND (ng_ce, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2655154899Srik#else 2656154899SrikMODULE_DEPEND (ce, sppp, 1, 1, 1); 2657154899Srik#endif 2658154899Srik#ifdef KLD_MODULE 2659154899SrikDRIVER_MODULE (cemod, pci, ce_driver, ce_devclass, ce_modevent, NULL); 2660154899Srik#else 2661154899SrikDRIVER_MODULE (ce, pci, ce_driver, ce_devclass, ce_modevent, NULL); 2662154899Srik#endif 2663154899Srik#else /* if __FreeBSD_version < 500000*/ 2664154899Srik#ifdef NETGRAPH 2665154899SrikDRIVER_MODULE (ce, pci, ce_driver, ce_devclass, ng_mod_event, &typestruct); 2666154899Srik#else 2667154899SrikDRIVER_MODULE (ce, pci, ce_driver, ce_devclass, ce_modevent, NULL); 2668154899Srik#endif 2669154899Srik#endif /* __FreeBSD_version < 500000 */ 2670154899Srik#endif /* NPCI */ 2671