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