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