if_cp.c revision 149847
1/*- 2 * Cronyx-Tau-PCI adapter driver for FreeBSD. 3 * Supports PPP/HDLC, Cisco/HDLC and FrameRelay protocol in synchronous mode, 4 * and asyncronous channels with full modem control. 5 * Keepalive protocol implemented in both Cisco and PPP modes. 6 * 7 * Copyright (C) 1999-2004 Cronyx Engineering. 8 * Author: Kurakin Roman, <rik@cronyx.ru> 9 * 10 * Copyright (C) 1999-2002 Cronyx Engineering. 11 * Author: Serge Vakulenko, <vak@cronyx.ru> 12 * 13 * This software is distributed with NO WARRANTIES, not even the implied 14 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15 * 16 * Authors grant any other persons or organisations a permission to use, 17 * modify and redistribute this software in source and binary forms, 18 * as long as this message is kept with the software, all derivative 19 * works or modified versions. 20 * 21 * Cronyx Id: if_cp.c,v 1.1.2.41 2004/06/23 17:09:13 rik Exp $ 22 */ 23 24#include <sys/cdefs.h> 25__FBSDID("$FreeBSD: head/sys/dev/cp/if_cp.c 149847 2005-09-07 09:53:35Z obrien $"); 26 27#include <sys/param.h> 28#include <sys/ucred.h> 29#include <sys/proc.h> 30#include <sys/systm.h> 31#include <sys/mbuf.h> 32#include <sys/kernel.h> 33#include <sys/module.h> 34#include <sys/conf.h> 35#include <sys/malloc.h> 36#include <sys/socket.h> 37#include <sys/sockio.h> 38#include <sys/sysctl.h> 39#include <sys/tty.h> 40#include <sys/bus.h> 41#include <vm/vm.h> 42#include <vm/pmap.h> 43#include <net/if.h> 44#include <dev/pci/pcivar.h> 45#include <dev/pci/pcireg.h> 46#include <machine/bus.h> 47#include <sys/rman.h> 48#include "opt_ng_cronyx.h" 49#ifdef NETGRAPH_CRONYX 50# include "opt_netgraph.h" 51# ifndef NETGRAPH 52# error #option NETGRAPH missed from configuration 53# endif 54# include <netgraph/ng_message.h> 55# include <netgraph/netgraph.h> 56# include <dev/cp/ng_cp.h> 57#else 58# include <net/if_sppp.h> 59# include <net/if_types.h> 60#include <dev/pci/pcivar.h> 61# define PP_CISCO IFF_LINK2 62# include <net/bpf.h> 63#endif 64#include <dev/cx/machdep.h> 65#include <dev/cp/cpddk.h> 66#include <machine/cserial.h> 67#include <machine/resource.h> 68#include <machine/pmap.h> 69 70/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 71#ifndef PP_FR 72#define PP_FR 0 73#endif 74 75#define CP_DEBUG(d,s) ({if (d->chan->debug) {\ 76 printf ("%s: ", d->name); printf s;}}) 77#define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 78 printf ("%s: ", d->name); printf s;}}) 79#define CP_LOCK_NAME "cpX" 80 81static int cp_mpsafenet = 1; 82TUNABLE_INT("debug.cp.mpsafenet", &cp_mpsafenet); 83SYSCTL_NODE(_debug, OID_AUTO, cp, CTLFLAG_RD, 0, "Cronyx Tau-PCI Adapters"); 84SYSCTL_INT(_debug_cp, OID_AUTO, mpsafenet, CTLFLAG_RD, &cp_mpsafenet, 0, 85 "Enable/disable MPSAFE network support for Cronyx Tau-PCI Adapters"); 86 87#define CP_LOCK(_bd) do { \ 88 if (cp_mpsafenet) \ 89 mtx_lock (&(_bd)->cp_mtx); \ 90 } while (0) 91#define CP_UNLOCK(_bd) do { \ 92 if (cp_mpsafenet) \ 93 mtx_unlock (&(_bd)->cp_mtx); \ 94 } while (0) 95 96#define CP_LOCK_ASSERT(_bd) do { \ 97 if (cp_mpsafenet) \ 98 mtx_assert (&(_bd)->cp_mtx, MA_OWNED); \ 99 } while (0) 100 101static int cp_probe __P((device_t)); 102static int cp_attach __P((device_t)); 103static int cp_detach __P((device_t)); 104 105static device_method_t cp_methods[] = { 106 /* Device interface */ 107 DEVMETHOD(device_probe, cp_probe), 108 DEVMETHOD(device_attach, cp_attach), 109 DEVMETHOD(device_detach, cp_detach), 110 111 {0, 0} 112}; 113 114typedef struct _cp_dma_mem_t { 115 unsigned long phys; 116 void *virt; 117 size_t size; 118 bus_dma_tag_t dmat; 119 bus_dmamap_t mapp; 120} cp_dma_mem_t; 121 122typedef struct _drv_t { 123 char name [8]; 124 int running; 125 cp_chan_t *chan; 126 cp_board_t *board; 127 cp_dma_mem_t dmamem; 128#ifdef NETGRAPH 129 char nodename [NG_NODELEN+1]; 130 hook_p hook; 131 hook_p debug_hook; 132 node_p node; 133 struct ifqueue queue; 134 struct ifqueue hi_queue; 135 short timeout; 136 struct callout timeout_handle; 137#else 138 struct ifqueue queue; 139 struct ifnet *ifp; 140#endif 141 struct cdev *devt; 142} drv_t; 143 144typedef struct _bdrv_t { 145 cp_board_t *board; 146 struct resource *cp_res; 147 struct resource *cp_irq; 148 void *cp_intrhand; 149 cp_dma_mem_t dmamem; 150 drv_t channel [NCHAN]; 151 struct mtx cp_mtx; 152} bdrv_t; 153 154static driver_t cp_driver = { 155 "cp", 156 cp_methods, 157 sizeof(bdrv_t), 158}; 159 160static devclass_t cp_devclass; 161 162static void cp_receive (cp_chan_t *c, unsigned char *data, int len); 163static void cp_transmit (cp_chan_t *c, void *attachment, int len); 164static void cp_error (cp_chan_t *c, int data); 165static void cp_up (drv_t *d); 166static void cp_start (drv_t *d); 167static void cp_down (drv_t *d); 168static void cp_watchdog (drv_t *d); 169#ifdef NETGRAPH 170extern struct ng_type typestruct; 171#else 172static void cp_ifstart (struct ifnet *ifp); 173static void cp_tlf (struct sppp *sp); 174static void cp_tls (struct sppp *sp); 175static void cp_ifwatchdog (struct ifnet *ifp); 176static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 177static void cp_initialize (void *softc); 178#endif 179 180static cp_board_t *adapter [NBRD]; 181static drv_t *channel [NBRD*NCHAN]; 182static struct callout led_timo [NBRD]; 183static struct callout timeout_handle; 184 185static int cp_destroy = 0; 186 187/* 188 * You also need read, write, open, close routines. 189 * This should get you started 190 */ 191static int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td) 192{ 193 int unit = minor (dev); 194 drv_t *d; 195 196 if (unit >= NBRD*NCHAN || ! (d = channel[unit])) 197 return ENXIO; 198 CP_DEBUG2 (d, ("cp_open\n")); 199 return 0; 200} 201 202/* 203 * Only called on the LAST close. 204 */ 205static int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td) 206{ 207 drv_t *d = channel [minor (dev)]; 208 209 CP_DEBUG2 (d, ("cp_close\n")); 210 return 0; 211} 212 213static int cp_modem_status (cp_chan_t *c) 214{ 215 drv_t *d = c->sys; 216 bdrv_t *bd = d->board->sys; 217 int status, s; 218 219 status = d->running ? TIOCM_LE : 0; 220 s = splimp (); 221 CP_LOCK (bd); 222 if (cp_get_cd (c)) status |= TIOCM_CD; 223 if (cp_get_cts (c)) status |= TIOCM_CTS; 224 if (cp_get_dsr (c)) status |= TIOCM_DSR; 225 if (c->dtr) status |= TIOCM_DTR; 226 if (c->rts) status |= TIOCM_RTS; 227 CP_UNLOCK (bd); 228 splx (s); 229 return status; 230} 231 232 233static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 234{ 235 drv_t *d = channel [minor (dev)]; 236 bdrv_t *bd = d->board->sys; 237 cp_chan_t *c = d->chan; 238 struct serial_statistics *st; 239 struct e1_statistics *opte1; 240 struct e3_statistics *opte3; 241 int error, s; 242 char mask[16]; 243 244 switch (cmd) { 245 case SERIAL_GETREGISTERED: 246 CP_DEBUG2 (d, ("ioctl: getregistered\n")); 247 bzero (mask, sizeof(mask)); 248 for (s=0; s<NBRD*NCHAN; ++s) 249 if (channel [s]) 250 mask [s/8] |= 1 << (s & 7); 251 bcopy (mask, data, sizeof (mask)); 252 return 0; 253 254#ifndef NETGRAPH 255 case SERIAL_GETPROTO: 256 CP_DEBUG2 (d, ("ioctl: getproto\n")); 257 strcpy ((char*)data, (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" : 258 (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp"); 259 return 0; 260 261 case SERIAL_SETPROTO: 262 CP_DEBUG2 (d, ("ioctl: setproto\n")); 263 /* Only for superuser! */ 264 error = suser (td); 265 if (error) 266 return error; 267 if (d->ifp->if_drv_flags & IFF_DRV_RUNNING) 268 return EBUSY; 269 if (! strcmp ("cisco", (char*)data)) { 270 IFP2SP(d->ifp)->pp_flags &= ~(PP_FR); 271 IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 272 d->ifp->if_flags |= PP_CISCO; 273 } else if (! strcmp ("fr", (char*)data) && PP_FR) { 274 d->ifp->if_flags &= ~(PP_CISCO); 275 IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE; 276 } else if (! strcmp ("ppp", (char*)data)) { 277 IFP2SP(d->ifp)->pp_flags &= ~PP_FR; 278 IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 279 d->ifp->if_flags &= ~(PP_CISCO); 280 } else 281 return EINVAL; 282 return 0; 283 284 case SERIAL_GETKEEPALIVE: 285 CP_DEBUG2 (d, ("ioctl: getkeepalive\n")); 286 if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 287 (d->ifp->if_flags & PP_CISCO)) 288 return EINVAL; 289 *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0; 290 return 0; 291 292 case SERIAL_SETKEEPALIVE: 293 CP_DEBUG2 (d, ("ioctl: setkeepalive\n")); 294 /* Only for superuser! */ 295 error = suser (td); 296 if (error) 297 return error; 298 if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 299 (d->ifp->if_flags & PP_CISCO)) 300 return EINVAL; 301 s = splimp (); 302 CP_LOCK (bd); 303 if (*(int*)data) 304 IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 305 else 306 IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 307 CP_UNLOCK (bd); 308 splx (s); 309 return 0; 310#endif /*NETGRAPH*/ 311 312 case SERIAL_GETMODE: 313 CP_DEBUG2 (d, ("ioctl: getmode\n")); 314 *(int*)data = SERIAL_HDLC; 315 return 0; 316 317 case SERIAL_SETMODE: 318 /* Only for superuser! */ 319 error = suser (td); 320 if (error) 321 return error; 322 if (*(int*)data != SERIAL_HDLC) 323 return EINVAL; 324 return 0; 325 326 case SERIAL_GETCFG: 327 CP_DEBUG2 (d, ("ioctl: getcfg\n")); 328 if (c->type != T_E1 || c->unfram) 329 return EINVAL; 330 *(char*)data = c->board->mux ? 'c' : 'a'; 331 return 0; 332 333 case SERIAL_SETCFG: 334 CP_DEBUG2 (d, ("ioctl: setcfg\n")); 335 error = suser (td); 336 if (error) 337 return error; 338 if (c->type != T_E1) 339 return EINVAL; 340 s = splimp (); 341 CP_LOCK (bd); 342 cp_set_mux (c->board, *((char*)data) == 'c'); 343 CP_UNLOCK (bd); 344 splx (s); 345 return 0; 346 347 case SERIAL_GETSTAT: 348 CP_DEBUG2 (d, ("ioctl: getstat\n")); 349 st = (struct serial_statistics*) data; 350 st->rintr = c->rintr; 351 st->tintr = c->tintr; 352 st->mintr = 0; 353 st->ibytes = c->ibytes; 354 st->ipkts = c->ipkts; 355 st->obytes = c->obytes; 356 st->opkts = c->opkts; 357 st->ierrs = c->overrun + c->frame + c->crc; 358 st->oerrs = c->underrun; 359 return 0; 360 361 case SERIAL_GETESTAT: 362 CP_DEBUG2 (d, ("ioctl: getestat\n")); 363 if (c->type != T_E1 && c->type != T_G703) 364 return EINVAL; 365 opte1 = (struct e1_statistics*) data; 366 opte1->status = c->status; 367 opte1->cursec = c->cursec; 368 opte1->totsec = c->totsec + c->cursec; 369 370 opte1->currnt.bpv = c->currnt.bpv; 371 opte1->currnt.fse = c->currnt.fse; 372 opte1->currnt.crce = c->currnt.crce; 373 opte1->currnt.rcrce = c->currnt.rcrce; 374 opte1->currnt.uas = c->currnt.uas; 375 opte1->currnt.les = c->currnt.les; 376 opte1->currnt.es = c->currnt.es; 377 opte1->currnt.bes = c->currnt.bes; 378 opte1->currnt.ses = c->currnt.ses; 379 opte1->currnt.oofs = c->currnt.oofs; 380 opte1->currnt.css = c->currnt.css; 381 opte1->currnt.dm = c->currnt.dm; 382 383 opte1->total.bpv = c->total.bpv + c->currnt.bpv; 384 opte1->total.fse = c->total.fse + c->currnt.fse; 385 opte1->total.crce = c->total.crce + c->currnt.crce; 386 opte1->total.rcrce = c->total.rcrce + c->currnt.rcrce; 387 opte1->total.uas = c->total.uas + c->currnt.uas; 388 opte1->total.les = c->total.les + c->currnt.les; 389 opte1->total.es = c->total.es + c->currnt.es; 390 opte1->total.bes = c->total.bes + c->currnt.bes; 391 opte1->total.ses = c->total.ses + c->currnt.ses; 392 opte1->total.oofs = c->total.oofs + c->currnt.oofs; 393 opte1->total.css = c->total.css + c->currnt.css; 394 opte1->total.dm = c->total.dm + c->currnt.dm; 395 for (s=0; s<48; ++s) { 396 opte1->interval[s].bpv = c->interval[s].bpv; 397 opte1->interval[s].fse = c->interval[s].fse; 398 opte1->interval[s].crce = c->interval[s].crce; 399 opte1->interval[s].rcrce = c->interval[s].rcrce; 400 opte1->interval[s].uas = c->interval[s].uas; 401 opte1->interval[s].les = c->interval[s].les; 402 opte1->interval[s].es = c->interval[s].es; 403 opte1->interval[s].bes = c->interval[s].bes; 404 opte1->interval[s].ses = c->interval[s].ses; 405 opte1->interval[s].oofs = c->interval[s].oofs; 406 opte1->interval[s].css = c->interval[s].css; 407 opte1->interval[s].dm = c->interval[s].dm; 408 } 409 return 0; 410 411 case SERIAL_GETE3STAT: 412 CP_DEBUG2 (d, ("ioctl: gete3stat\n")); 413 if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 414 return EINVAL; 415 opte3 = (struct e3_statistics*) data; 416 417 opte3->status = c->e3status; 418 opte3->cursec = (c->e3csec_5 * 2 + 1) / 10; 419 opte3->totsec = c->e3tsec + opte3->cursec; 420 421 opte3->ccv = c->e3ccv; 422 opte3->tcv = c->e3tcv + opte3->ccv; 423 424 for (s = 0; s < 48; ++s) { 425 opte3->icv[s] = c->e3icv[s]; 426 } 427 return 0; 428 429 case SERIAL_CLRSTAT: 430 CP_DEBUG2 (d, ("ioctl: clrstat\n")); 431 /* Only for superuser! */ 432 error = suser (td); 433 if (error) 434 return error; 435 c->rintr = 0; 436 c->tintr = 0; 437 c->ibytes = 0; 438 c->obytes = 0; 439 c->ipkts = 0; 440 c->opkts = 0; 441 c->overrun = 0; 442 c->frame = 0; 443 c->crc = 0; 444 c->underrun = 0; 445 bzero (&c->currnt, sizeof (c->currnt)); 446 bzero (&c->total, sizeof (c->total)); 447 bzero (c->interval, sizeof (c->interval)); 448 c->e3ccv = 0; 449 c->e3tcv = 0; 450 bzero (c->e3icv, sizeof (c->e3icv)); 451 return 0; 452 453 case SERIAL_GETBAUD: 454 CP_DEBUG2 (d, ("ioctl: getbaud\n")); 455 *(long*)data = c->baud; 456 return 0; 457 458 case SERIAL_SETBAUD: 459 CP_DEBUG2 (d, ("ioctl: setbaud\n")); 460 /* Only for superuser! */ 461 error = suser (td); 462 if (error) 463 return error; 464 s = splimp (); 465 CP_LOCK (bd); 466 cp_set_baud (c, *(long*)data); 467 CP_UNLOCK (bd); 468 splx (s); 469 return 0; 470 471 case SERIAL_GETLOOP: 472 CP_DEBUG2 (d, ("ioctl: getloop\n")); 473 *(int*)data = c->lloop; 474 return 0; 475 476 case SERIAL_SETLOOP: 477 CP_DEBUG2 (d, ("ioctl: setloop\n")); 478 /* Only for superuser! */ 479 error = suser (td); 480 if (error) 481 return error; 482 s = splimp (); 483 CP_LOCK (bd); 484 cp_set_lloop (c, *(int*)data); 485 CP_UNLOCK (bd); 486 splx (s); 487 return 0; 488 489 case SERIAL_GETDPLL: 490 CP_DEBUG2 (d, ("ioctl: getdpll\n")); 491 if (c->type != T_SERIAL) 492 return EINVAL; 493 *(int*)data = c->dpll; 494 return 0; 495 496 case SERIAL_SETDPLL: 497 CP_DEBUG2 (d, ("ioctl: setdpll\n")); 498 /* Only for superuser! */ 499 error = suser (td); 500 if (error) 501 return error; 502 if (c->type != T_SERIAL) 503 return EINVAL; 504 s = splimp (); 505 CP_LOCK (bd); 506 cp_set_dpll (c, *(int*)data); 507 CP_UNLOCK (bd); 508 splx (s); 509 return 0; 510 511 case SERIAL_GETNRZI: 512 CP_DEBUG2 (d, ("ioctl: getnrzi\n")); 513 if (c->type != T_SERIAL) 514 return EINVAL; 515 *(int*)data = c->nrzi; 516 return 0; 517 518 case SERIAL_SETNRZI: 519 CP_DEBUG2 (d, ("ioctl: setnrzi\n")); 520 /* Only for superuser! */ 521 error = suser (td); 522 if (error) 523 return error; 524 if (c->type != T_SERIAL) 525 return EINVAL; 526 s = splimp (); 527 CP_LOCK (bd); 528 cp_set_nrzi (c, *(int*)data); 529 CP_UNLOCK (bd); 530 splx (s); 531 return 0; 532 533 case SERIAL_GETDEBUG: 534 CP_DEBUG2 (d, ("ioctl: getdebug\n")); 535 *(int*)data = d->chan->debug; 536 return 0; 537 538 case SERIAL_SETDEBUG: 539 CP_DEBUG2 (d, ("ioctl: setdebug\n")); 540 /* Only for superuser! */ 541 error = suser (td); 542 if (error) 543 return error; 544 d->chan->debug = *(int*)data; 545#ifndef NETGRAPH 546 if (d->chan->debug) 547 d->ifp->if_flags |= IFF_DEBUG; 548 else 549 d->ifp->if_flags &= ~IFF_DEBUG; 550#endif 551 return 0; 552 553 case SERIAL_GETHIGAIN: 554 CP_DEBUG2 (d, ("ioctl: gethigain\n")); 555 if (c->type != T_E1) 556 return EINVAL; 557 *(int*)data = c->higain; 558 return 0; 559 560 case SERIAL_SETHIGAIN: 561 CP_DEBUG2 (d, ("ioctl: sethigain\n")); 562 /* Only for superuser! */ 563 error = suser (td); 564 if (error) 565 return error; 566 if (c->type != T_E1) 567 return EINVAL; 568 s = splimp (); 569 CP_LOCK (bd); 570 cp_set_higain (c, *(int*)data); 571 CP_UNLOCK (bd); 572 splx (s); 573 return 0; 574 575 case SERIAL_GETPHONY: 576 CP_DEBUG2 (d, ("ioctl: getphony\n")); 577 if (c->type != T_E1) 578 return EINVAL; 579 *(int*)data = c->phony; 580 return 0; 581 582 case SERIAL_SETPHONY: 583 CP_DEBUG2 (d, ("ioctl: setphony\n")); 584 /* Only for superuser! */ 585 error = suser (td); 586 if (error) 587 return error; 588 if (c->type != T_E1) 589 return EINVAL; 590 s = splimp (); 591 CP_LOCK (bd); 592 cp_set_phony (c, *(int*)data); 593 CP_UNLOCK (bd); 594 splx (s); 595 return 0; 596 597 case SERIAL_GETUNFRAM: 598 CP_DEBUG2 (d, ("ioctl: getunfram\n")); 599 if (c->type != T_E1) 600 return EINVAL; 601 *(int*)data = c->unfram; 602 return 0; 603 604 case SERIAL_SETUNFRAM: 605 CP_DEBUG2 (d, ("ioctl: setunfram\n")); 606 /* Only for superuser! */ 607 error = suser (td); 608 if (error) 609 return error; 610 if (c->type != T_E1) 611 return EINVAL; 612 s = splimp (); 613 CP_LOCK (bd); 614 cp_set_unfram (c, *(int*)data); 615 CP_UNLOCK (bd); 616 splx (s); 617 return 0; 618 619 case SERIAL_GETSCRAMBLER: 620 CP_DEBUG2 (d, ("ioctl: getscrambler\n")); 621 if (c->type != T_G703 && !c->unfram) 622 return EINVAL; 623 *(int*)data = c->scrambler; 624 return 0; 625 626 case SERIAL_SETSCRAMBLER: 627 CP_DEBUG2 (d, ("ioctl: setscrambler\n")); 628 /* Only for superuser! */ 629 error = suser (td); 630 if (error) 631 return error; 632 if (c->type != T_G703 && !c->unfram) 633 return EINVAL; 634 s = splimp (); 635 CP_LOCK (bd); 636 cp_set_scrambler (c, *(int*)data); 637 CP_UNLOCK (bd); 638 splx (s); 639 return 0; 640 641 case SERIAL_GETMONITOR: 642 CP_DEBUG2 (d, ("ioctl: getmonitor\n")); 643 if (c->type != T_E1 && 644 c->type != T_E3 && 645 c->type != T_T3 && 646 c->type != T_STS1) 647 return EINVAL; 648 *(int*)data = c->monitor; 649 return 0; 650 651 case SERIAL_SETMONITOR: 652 CP_DEBUG2 (d, ("ioctl: setmonitor\n")); 653 /* Only for superuser! */ 654 error = suser (td); 655 if (error) 656 return error; 657 if (c->type != T_E1) 658 return EINVAL; 659 s = splimp (); 660 CP_LOCK (bd); 661 cp_set_monitor (c, *(int*)data); 662 CP_UNLOCK (bd); 663 splx (s); 664 return 0; 665 666 case SERIAL_GETUSE16: 667 CP_DEBUG2 (d, ("ioctl: getuse16\n")); 668 if (c->type != T_E1 || c->unfram) 669 return EINVAL; 670 *(int*)data = c->use16; 671 return 0; 672 673 case SERIAL_SETUSE16: 674 CP_DEBUG2 (d, ("ioctl: setuse16\n")); 675 /* Only for superuser! */ 676 error = suser (td); 677 if (error) 678 return error; 679 if (c->type != T_E1) 680 return EINVAL; 681 s = splimp (); 682 CP_LOCK (bd); 683 cp_set_use16 (c, *(int*)data); 684 CP_UNLOCK (bd); 685 splx (s); 686 return 0; 687 688 case SERIAL_GETCRC4: 689 CP_DEBUG2 (d, ("ioctl: getcrc4\n")); 690 if (c->type != T_E1 || c->unfram) 691 return EINVAL; 692 *(int*)data = c->crc4; 693 return 0; 694 695 case SERIAL_SETCRC4: 696 CP_DEBUG2 (d, ("ioctl: setcrc4\n")); 697 /* Only for superuser! */ 698 error = suser (td); 699 if (error) 700 return error; 701 if (c->type != T_E1) 702 return EINVAL; 703 s = splimp (); 704 CP_LOCK (bd); 705 cp_set_crc4 (c, *(int*)data); 706 CP_UNLOCK (bd); 707 splx (s); 708 return 0; 709 710 case SERIAL_GETCLK: 711 CP_DEBUG2 (d, ("ioctl: getclk\n")); 712 if (c->type != T_E1 && 713 c->type != T_G703 && 714 c->type != T_E3 && 715 c->type != T_T3 && 716 c->type != T_STS1) 717 return EINVAL; 718 switch (c->gsyn) { 719 default: *(int*)data = E1CLK_INTERNAL; break; 720 case GSYN_RCV: *(int*)data = E1CLK_RECEIVE; break; 721 case GSYN_RCV0: *(int*)data = E1CLK_RECEIVE_CHAN0; break; 722 case GSYN_RCV1: *(int*)data = E1CLK_RECEIVE_CHAN1; break; 723 case GSYN_RCV2: *(int*)data = E1CLK_RECEIVE_CHAN2; break; 724 case GSYN_RCV3: *(int*)data = E1CLK_RECEIVE_CHAN3; break; 725 } 726 return 0; 727 728 case SERIAL_SETCLK: 729 CP_DEBUG2 (d, ("ioctl: setclk\n")); 730 /* Only for superuser! */ 731 error = suser (td); 732 if (error) 733 return error; 734 if (c->type != T_E1 && 735 c->type != T_G703 && 736 c->type != T_E3 && 737 c->type != T_T3 && 738 c->type != T_STS1) 739 return EINVAL; 740 s = splimp (); 741 CP_LOCK (bd); 742 switch (*(int*)data) { 743 default: cp_set_gsyn (c, GSYN_INT); break; 744 case E1CLK_RECEIVE: cp_set_gsyn (c, GSYN_RCV); break; 745 case E1CLK_RECEIVE_CHAN0: cp_set_gsyn (c, GSYN_RCV0); break; 746 case E1CLK_RECEIVE_CHAN1: cp_set_gsyn (c, GSYN_RCV1); break; 747 case E1CLK_RECEIVE_CHAN2: cp_set_gsyn (c, GSYN_RCV2); break; 748 case E1CLK_RECEIVE_CHAN3: cp_set_gsyn (c, GSYN_RCV3); break; 749 } 750 CP_UNLOCK (bd); 751 splx (s); 752 return 0; 753 754 case SERIAL_GETTIMESLOTS: 755 CP_DEBUG2 (d, ("ioctl: gettimeslots\n")); 756 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 757 return EINVAL; 758 *(u_long*)data = c->ts; 759 return 0; 760 761 case SERIAL_SETTIMESLOTS: 762 CP_DEBUG2 (d, ("ioctl: settimeslots\n")); 763 /* Only for superuser! */ 764 error = suser (td); 765 if (error) 766 return error; 767 if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) 768 return EINVAL; 769 s = splimp (); 770 CP_LOCK (bd); 771 cp_set_ts (c, *(u_long*)data); 772 CP_UNLOCK (bd); 773 splx (s); 774 return 0; 775 776 case SERIAL_GETINVCLK: 777 CP_DEBUG2 (d, ("ioctl: getinvclk\n")); 778#if 1 779 return EINVAL; 780#else 781 if (c->type != T_SERIAL) 782 return EINVAL; 783 *(int*)data = c->invtxc; 784 return 0; 785#endif 786 787 case SERIAL_SETINVCLK: 788 CP_DEBUG2 (d, ("ioctl: setinvclk\n")); 789 /* Only for superuser! */ 790 error = suser (td); 791 if (error) 792 return error; 793 if (c->type != T_SERIAL) 794 return EINVAL; 795 s = splimp (); 796 CP_LOCK (bd); 797 cp_set_invtxc (c, *(int*)data); 798 cp_set_invrxc (c, *(int*)data); 799 CP_UNLOCK (bd); 800 splx (s); 801 return 0; 802 803 case SERIAL_GETINVTCLK: 804 CP_DEBUG2 (d, ("ioctl: getinvtclk\n")); 805 if (c->type != T_SERIAL) 806 return EINVAL; 807 *(int*)data = c->invtxc; 808 return 0; 809 810 case SERIAL_SETINVTCLK: 811 CP_DEBUG2 (d, ("ioctl: setinvtclk\n")); 812 /* Only for superuser! */ 813 error = suser (td); 814 if (error) 815 return error; 816 if (c->type != T_SERIAL) 817 return EINVAL; 818 s = splimp (); 819 CP_LOCK (bd); 820 cp_set_invtxc (c, *(int*)data); 821 CP_UNLOCK (bd); 822 splx (s); 823 return 0; 824 825 case SERIAL_GETINVRCLK: 826 CP_DEBUG2 (d, ("ioctl: getinvrclk\n")); 827 if (c->type != T_SERIAL) 828 return EINVAL; 829 *(int*)data = c->invrxc; 830 return 0; 831 832 case SERIAL_SETINVRCLK: 833 CP_DEBUG2 (d, ("ioctl: setinvrclk\n")); 834 /* Only for superuser! */ 835 error = suser (td); 836 if (error) 837 return error; 838 if (c->type != T_SERIAL) 839 return EINVAL; 840 s = splimp (); 841 CP_LOCK (bd); 842 cp_set_invrxc (c, *(int*)data); 843 CP_UNLOCK (bd); 844 splx (s); 845 return 0; 846 847 case SERIAL_GETLEVEL: 848 CP_DEBUG2 (d, ("ioctl: getlevel\n")); 849 if (c->type != T_G703) 850 return EINVAL; 851 s = splimp (); 852 CP_LOCK (bd); 853 *(int*)data = cp_get_lq (c); 854 CP_UNLOCK (bd); 855 splx (s); 856 return 0; 857 858#if 0 859 case SERIAL_RESET: 860 CP_DEBUG2 (d, ("ioctl: reset\n")); 861 /* Only for superuser! */ 862 error = suser (td); 863 if (error) 864 return error; 865 s = splimp (); 866 CP_LOCK (bd); 867 cp_reset (c->board, 0, 0); 868 CP_UNLOCK (bd); 869 splx (s); 870 return 0; 871 872 case SERIAL_HARDRESET: 873 CP_DEBUG2 (d, ("ioctl: hardreset\n")); 874 /* Only for superuser! */ 875 error = suser (td); 876 if (error) 877 return error; 878 s = splimp (); 879 CP_LOCK (bd); 880 /* hard_reset (c->board); */ 881 CP_UNLOCK (bd); 882 splx (s); 883 return 0; 884#endif 885 886 case SERIAL_GETCABLE: 887 CP_DEBUG2 (d, ("ioctl: getcable\n")); 888 if (c->type != T_SERIAL) 889 return EINVAL; 890 s = splimp (); 891 CP_LOCK (bd); 892 *(int*)data = cp_get_cable (c); 893 CP_UNLOCK (bd); 894 splx (s); 895 return 0; 896 897 case SERIAL_GETDIR: 898 CP_DEBUG2 (d, ("ioctl: getdir\n")); 899 if (c->type != T_E1 && c->type != T_DATA) 900 return EINVAL; 901 *(int*)data = c->dir; 902 return 0; 903 904 case SERIAL_SETDIR: 905 CP_DEBUG2 (d, ("ioctl: setdir\n")); 906 /* Only for superuser! */ 907 error = suser (td); 908 if (error) 909 return error; 910 s = splimp (); 911 CP_LOCK (bd); 912 cp_set_dir (c, *(int*)data); 913 CP_UNLOCK (bd); 914 splx (s); 915 return 0; 916 917 case SERIAL_GETRLOOP: 918 CP_DEBUG2 (d, ("ioctl: getrloop\n")); 919 if (c->type != T_G703 && 920 c->type != T_E3 && 921 c->type != T_T3 && 922 c->type != T_STS1) 923 return EINVAL; 924 *(int*)data = cp_get_rloop (c); 925 return 0; 926 927 case SERIAL_SETRLOOP: 928 CP_DEBUG2 (d, ("ioctl: setloop\n")); 929 if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) 930 return EINVAL; 931 /* Only for superuser! */ 932 error = suser (td); 933 if (error) 934 return error; 935 s = splimp (); 936 CP_LOCK (bd); 937 cp_set_rloop (c, *(int*)data); 938 CP_UNLOCK (bd); 939 splx (s); 940 return 0; 941 942 case SERIAL_GETCABLEN: 943 CP_DEBUG2 (d, ("ioctl: getcablen\n")); 944 if (c->type != T_T3 && c->type != T_STS1) 945 return EINVAL; 946 *(int*)data = c->cablen; 947 return 0; 948 949 case SERIAL_SETCABLEN: 950 CP_DEBUG2 (d, ("ioctl: setloop\n")); 951 if (c->type != T_T3 && c->type != T_STS1) 952 return EINVAL; 953 /* Only for superuser! */ 954 error = suser (td); 955 if (error) 956 return error; 957 s = splimp (); 958 CP_LOCK (bd); 959 cp_set_cablen (c, *(int*)data); 960 CP_UNLOCK (bd); 961 splx (s); 962 return 0; 963 964 case TIOCSDTR: /* Set DTR */ 965 s = splimp (); 966 CP_LOCK (bd); 967 cp_set_dtr (c, 1); 968 CP_UNLOCK (bd); 969 splx (s); 970 return 0; 971 972 case TIOCCDTR: /* Clear DTR */ 973 s = splimp (); 974 CP_LOCK (bd); 975 cp_set_dtr (c, 0); 976 CP_UNLOCK (bd); 977 splx (s); 978 return 0; 979 980 case TIOCMSET: /* Set DTR/RTS */ 981 s = splimp (); 982 CP_LOCK (bd); 983 cp_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 984 cp_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 985 CP_UNLOCK (bd); 986 splx (s); 987 return 0; 988 989 case TIOCMBIS: /* Add DTR/RTS */ 990 s = splimp (); 991 CP_LOCK (bd); 992 if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 1); 993 if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 1); 994 CP_UNLOCK (bd); 995 splx (s); 996 return 0; 997 998 case TIOCMBIC: /* Clear DTR/RTS */ 999 s = splimp (); 1000 CP_LOCK (bd); 1001 if (*(int*)data & TIOCM_DTR) cp_set_dtr (c, 0); 1002 if (*(int*)data & TIOCM_RTS) cp_set_rts (c, 0); 1003 CP_UNLOCK (bd); 1004 splx (s); 1005 return 0; 1006 1007 case TIOCMGET: /* Get modem status */ 1008 *(int*)data = cp_modem_status (c); 1009 return 0; 1010 } 1011 return ENOTTY; 1012} 1013 1014static struct cdevsw cp_cdevsw = { 1015 .d_version = D_VERSION, 1016 .d_open = cp_open, 1017 .d_close = cp_close, 1018 .d_ioctl = cp_ioctl, 1019 .d_name = "cp", 1020 .d_flags = D_NEEDGIANT, 1021}; 1022 1023/* 1024 * Print the mbuf chain, for debug purposes only. 1025 */ 1026static void printmbuf (struct mbuf *m) 1027{ 1028 printf ("mbuf:"); 1029 for (; m; m=m->m_next) { 1030 if (m->m_flags & M_PKTHDR) 1031 printf (" HDR %d:", m->m_pkthdr.len); 1032 if (m->m_flags & M_EXT) 1033 printf (" EXT:"); 1034 printf (" %d", m->m_len); 1035 } 1036 printf ("\n"); 1037} 1038 1039/* 1040 * Make an mbuf from data. 1041 */ 1042static struct mbuf *makembuf (void *buf, unsigned len) 1043{ 1044 struct mbuf *m; 1045 1046 MGETHDR (m, M_DONTWAIT, MT_DATA); 1047 if (! m) 1048 return 0; 1049 MCLGET (m, M_DONTWAIT); 1050 if (! (m->m_flags & M_EXT)) { 1051 m_freem (m); 1052 return 0; 1053 } 1054 m->m_pkthdr.len = m->m_len = len; 1055 bcopy (buf, mtod (m, caddr_t), len); 1056 return m; 1057} 1058 1059static int cp_probe (device_t dev) 1060{ 1061 if ((pci_get_vendor (dev) == cp_vendor_id) && 1062 (pci_get_device (dev) == cp_device_id)) { 1063 device_set_desc (dev, "Cronyx-Tau-PCI serial adapter"); 1064 return BUS_PROBE_DEFAULT; 1065 } 1066 return ENXIO; 1067} 1068 1069static void cp_timeout (void *arg) 1070{ 1071 drv_t *d; 1072 int s, i, k; 1073 1074 for (i = 0; i < NBRD; ++i) { 1075 if (adapter[i] == NULL) 1076 continue; 1077 for (k = 0; k < NCHAN; ++k) { 1078 s = splimp (); 1079 if (cp_destroy) { 1080 splx (s); 1081 return; 1082 } 1083 d = channel[i * NCHAN + k]; 1084 if (!d) { 1085 splx (s); 1086 continue; 1087 } 1088 CP_LOCK ((bdrv_t *)d->board->sys); 1089 switch (d->chan->type) { 1090 case T_G703: 1091 cp_g703_timer (d->chan); 1092 break; 1093 case T_E1: 1094 cp_e1_timer (d->chan); 1095 break; 1096 case T_E3: 1097 case T_T3: 1098 case T_STS1: 1099 cp_e3_timer (d->chan); 1100 break; 1101 default: 1102 break; 1103 } 1104 CP_UNLOCK ((bdrv_t *)d->board->sys); 1105 splx (s); 1106 } 1107 } 1108 s = splimp (); 1109 if (!cp_destroy) 1110 callout_reset (&timeout_handle, hz, cp_timeout, 0); 1111 splx (s); 1112} 1113 1114static void cp_led_off (void *arg) 1115{ 1116 cp_board_t *b = arg; 1117 bdrv_t *bd = (bdrv_t *) b->sys; 1118 int s; 1119 s = splimp (); 1120 if (cp_destroy) { 1121 splx (s); 1122 return; 1123 } 1124 CP_LOCK (bd); 1125 cp_led (b, 0); 1126 CP_UNLOCK (bd); 1127 splx (s); 1128} 1129 1130static void cp_intr (void *arg) 1131{ 1132 bdrv_t *bd = arg; 1133 cp_board_t *b = bd->board; 1134#ifndef NETGRAPH 1135 int i; 1136#endif 1137 int s = splimp (); 1138 if (cp_destroy) { 1139 splx (s); 1140 return; 1141 } 1142 CP_LOCK (bd); 1143 /* Check if we are ready */ 1144 if (b->sys == NULL) { 1145 /* Not we are not, just cleanup. */ 1146 cp_interrupt_poll (b, 1); 1147 CP_UNLOCK (bd); 1148 return; 1149 } 1150 /* Turn LED on. */ 1151 cp_led (b, 1); 1152 1153 cp_interrupt (b); 1154 1155 /* Turn LED off 50 msec later. */ 1156 callout_reset (&led_timo[b->num], hz/20, cp_led_off, b); 1157 CP_UNLOCK (bd); 1158 splx (s); 1159 1160#ifndef NETGRAPH 1161 /* Pass packets in a lock-free state */ 1162 for (i = 0; i < NCHAN && b->chan[i].type; i++) { 1163 drv_t *d = b->chan[i].sys; 1164 struct mbuf *m; 1165 if (!d || !d->running) 1166 continue; 1167 while (_IF_QLEN(&d->queue)) { 1168 IF_DEQUEUE (&d->queue,m); 1169 if (!m) 1170 continue; 1171 sppp_input (d->ifp, m); 1172 } 1173 } 1174#endif 1175} 1176 1177static void 1178cp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 1179{ 1180 unsigned long *addr; 1181 1182 if (error) 1183 return; 1184 1185 KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 1186 addr = arg; 1187 *addr = segs->ds_addr; 1188} 1189 1190static int 1191cp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem) 1192{ 1193 int error; 1194 1195 error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 1196 BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 1197 dmem->size, 0, NULL, NULL, &dmem->dmat); 1198 if (error) { 1199 if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 1200 else printf ("cp%d: ", bnum); 1201 printf ("couldn't allocate tag for dma memory\n"); 1202 return 0; 1203 } 1204 error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 1205 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 1206 if (error) { 1207 if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 1208 else printf ("cp%d: ", bnum); 1209 printf ("couldn't allocate mem for dma memory\n"); 1210 bus_dma_tag_destroy (dmem->dmat); 1211 return 0; 1212 } 1213 error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 1214 dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0); 1215 if (error) { 1216 if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); 1217 else printf ("cp%d: ", bnum); 1218 printf ("couldn't load mem map for dma memory\n"); 1219 bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 1220 bus_dma_tag_destroy (dmem->dmat); 1221 return 0; 1222 } 1223 return 1; 1224} 1225 1226static void 1227cp_bus_dma_mem_free (cp_dma_mem_t *dmem) 1228{ 1229 bus_dmamap_unload (dmem->dmat, dmem->mapp); 1230 bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 1231 bus_dma_tag_destroy (dmem->dmat); 1232} 1233 1234/* 1235 * Called if the probe succeeded. 1236 */ 1237static int cp_attach (device_t dev) 1238{ 1239 bdrv_t *bd = device_get_softc (dev); 1240 int unit = device_get_unit (dev); 1241 char *cp_ln = CP_LOCK_NAME; 1242 unsigned short res; 1243 vm_offset_t vbase; 1244 int rid, error; 1245 cp_board_t *b; 1246 cp_chan_t *c; 1247 drv_t *d; 1248 int s = splimp (); 1249 1250 b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK); 1251 if (!b) { 1252 printf ("cp%d: couldn't allocate memory\n", unit); 1253 splx (s); 1254 return (ENXIO); 1255 } 1256 bzero (b, sizeof(cp_board_t)); 1257 1258 bd->board = b; 1259 rid = PCIR_BAR(0); 1260 bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, 1261 0, ~0, 1, RF_ACTIVE); 1262 if (! bd->cp_res) { 1263 printf ("cp%d: cannot map memory\n", unit); 1264 free (b, M_DEVBUF); 1265 splx (s); 1266 return (ENXIO); 1267 } 1268 vbase = (vm_offset_t) rman_get_virtual (bd->cp_res); 1269 1270 cp_ln[2] = '0' + unit; 1271 mtx_init (&bd->cp_mtx, cp_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); 1272 res = cp_init (b, unit, (u_char*) vbase); 1273 if (res) { 1274 printf ("cp%d: can't init, error code:%x\n", unit, res); 1275 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 1276 free (b, M_DEVBUF); 1277 splx (s); 1278 return (ENXIO); 1279 } 1280 1281 bd->dmamem.size = sizeof(cp_qbuf_t); 1282 if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { 1283 free (b, M_DEVBUF); 1284 splx (s); 1285 return (ENXIO); 1286 } 1287 CP_LOCK (bd); 1288 cp_reset (b, bd->dmamem.virt, bd->dmamem.phys); 1289 CP_UNLOCK (bd); 1290 1291 rid = 0; 1292 bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 1293 RF_SHAREABLE | RF_ACTIVE); 1294 if (! bd->cp_irq) { 1295 cp_destroy = 1; 1296 printf ("cp%d: cannot map interrupt\n", unit); 1297 bus_release_resource (dev, SYS_RES_MEMORY, 1298 PCIR_BAR(0), bd->cp_res); 1299 mtx_destroy (&bd->cp_mtx); 1300 free (b, M_DEVBUF); 1301 splx (s); 1302 return (ENXIO); 1303 } 1304 callout_init (&led_timo[unit], cp_mpsafenet ? CALLOUT_MPSAFE : 0); 1305 error = bus_setup_intr (dev, bd->cp_irq, 1306 INTR_TYPE_NET|(cp_mpsafenet?INTR_MPSAFE:0), 1307 cp_intr, bd, &bd->cp_intrhand); 1308 if (error) { 1309 cp_destroy = 1; 1310 printf ("cp%d: cannot set up irq\n", unit); 1311 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 1312 bus_release_resource (dev, SYS_RES_MEMORY, 1313 PCIR_BAR(0), bd->cp_res); 1314 mtx_destroy (&bd->cp_mtx); 1315 free (b, M_DEVBUF); 1316 splx (s); 1317 return (ENXIO); 1318 } 1319 printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000); 1320 1321 for (c = b->chan; c < b->chan + NCHAN; ++c) { 1322 if (! c->type) 1323 continue; 1324 d = &bd->channel[c->num]; 1325 d->dmamem.size = sizeof(cp_buf_t); 1326 if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 1327 continue; 1328 channel [b->num*NCHAN + c->num] = d; 1329 sprintf (d->name, "cp%d.%d", b->num, c->num); 1330 d->board = b; 1331 d->chan = c; 1332 c->sys = d; 1333#ifdef NETGRAPH 1334 if (ng_make_node_common (&typestruct, &d->node) != 0) { 1335 printf ("%s: cannot make common node\n", d->name); 1336 d->node = NULL; 1337 continue; 1338 } 1339 NG_NODE_SET_PRIVATE (d->node, d); 1340 sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE, 1341 c->board->num*NCHAN + c->num); 1342 if (ng_name_node (d->node, d->nodename)) { 1343 printf ("%s: cannot name node\n", d->nodename); 1344 NG_NODE_UNREF (d->node); 1345 continue; 1346 } 1347 d->queue.ifq_maxlen = IFQ_MAXLEN; 1348 d->hi_queue.ifq_maxlen = IFQ_MAXLEN; 1349 mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 1350 mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); 1351 callout_init (&d->timeout_handle, 1352 cp_mpsafenet ? CALLOUT_MPSAFE : 0); 1353#else /*NETGRAPH*/ 1354 d->ifp = if_alloc(IFT_PPP); 1355 if (d->ifp == NULL) { 1356 printf ("%s: cannot if_alloc() interface\n", d->name); 1357 continue; 1358 } 1359 d->ifp->if_softc = d; 1360 if_initname (d->ifp, "cp", b->num * NCHAN + c->num); 1361 d->ifp->if_mtu = PP_MTU; 1362 d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 1363 if (!cp_mpsafenet) 1364 d->ifp->if_flags |= IFF_NEEDSGIANT; 1365 d->ifp->if_ioctl = cp_sioctl; 1366 d->ifp->if_start = cp_ifstart; 1367 d->ifp->if_watchdog = cp_ifwatchdog; 1368 d->ifp->if_init = cp_initialize; 1369 d->queue.ifq_maxlen = NRBUF; 1370 mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); 1371 sppp_attach (d->ifp); 1372 if_attach (d->ifp); 1373 IFP2SP(d->ifp)->pp_tlf = cp_tlf; 1374 IFP2SP(d->ifp)->pp_tls = cp_tls; 1375 /* If BPF is in the kernel, call the attach for it. 1376 * The header size of PPP or Cisco/HDLC is 4 bytes. */ 1377 bpfattach (d->ifp, DLT_PPP, 4); 1378#endif /*NETGRAPH*/ 1379 cp_start_e1 (c); 1380 cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); 1381 1382 /* Register callback functions. */ 1383 cp_register_transmit (c, &cp_transmit); 1384 cp_register_receive (c, &cp_receive); 1385 cp_register_error (c, &cp_error); 1386 d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT, 1387 GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num); 1388 } 1389 CP_LOCK (bd); 1390 b->sys = bd; 1391 adapter[unit] = b; 1392 CP_UNLOCK (bd); 1393 splx (s); 1394 return 0; 1395} 1396 1397static int cp_detach (device_t dev) 1398{ 1399 bdrv_t *bd = device_get_softc (dev); 1400 cp_board_t *b = bd->board; 1401 cp_chan_t *c; 1402 int s; 1403 1404 KASSERT (mtx_initialized (&bd->cp_mtx), ("cp mutex not initialized")); 1405 s = splimp (); 1406 CP_LOCK (bd); 1407 /* Check if the device is busy (open). */ 1408 for (c = b->chan; c < b->chan + NCHAN; ++c) { 1409 drv_t *d = (drv_t*) c->sys; 1410 1411 if (! d || ! d->chan->type) 1412 continue; 1413 if (d->running) { 1414 CP_UNLOCK (bd); 1415 splx (s); 1416 return EBUSY; 1417 } 1418 } 1419 1420 /* Ok, we can unload driver */ 1421 /* At first we should stop all channels */ 1422 for (c = b->chan; c < b->chan + NCHAN; ++c) { 1423 drv_t *d = (drv_t*) c->sys; 1424 1425 if (! d || ! d->chan->type) 1426 continue; 1427 1428 cp_stop_chan (c); 1429 cp_stop_e1 (c); 1430 cp_set_dtr (d->chan, 0); 1431 cp_set_rts (d->chan, 0); 1432 } 1433 1434 /* Reset the adapter. */ 1435 cp_destroy = 1; 1436 cp_interrupt_poll (b, 1); 1437 cp_led_off (b); 1438 cp_reset (b, 0 ,0); 1439 callout_stop (&led_timo[b->num]); 1440 1441 for (c=b->chan; c<b->chan+NCHAN; ++c) { 1442 drv_t *d = (drv_t*) c->sys; 1443 1444 if (! d || ! d->chan->type) 1445 continue; 1446#ifndef NETGRAPH 1447 /* Detach from the packet filter list of interfaces. */ 1448 bpfdetach (d->ifp); 1449 1450 /* Detach from the sync PPP list. */ 1451 sppp_detach (d->ifp); 1452 1453 /* Detach from the system list of interfaces. */ 1454 if_detach (d->ifp); 1455 if_free (d->ifp); 1456 IF_DRAIN (&d->queue); 1457 mtx_destroy (&d->queue.ifq_mtx); 1458#else 1459 if (d->node) { 1460 ng_rmnode_self (d->node); 1461 NG_NODE_UNREF (d->node); 1462 d->node = NULL; 1463 } 1464 mtx_destroy (&d->queue.ifq_mtx); 1465 mtx_destroy (&d->hi_queue.ifq_mtx); 1466#endif 1467 destroy_dev (d->devt); 1468 } 1469 1470 b->sys = NULL; 1471 CP_UNLOCK (bd); 1472 1473 /* Disable the interrupt request. */ 1474 bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); 1475 bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 1476 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 1477 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 1478 1479 CP_LOCK (bd); 1480 cp_led_off (b); 1481 CP_UNLOCK (bd); 1482 callout_drain (&led_timo[b->num]); 1483 splx (s); 1484 1485 s = splimp (); 1486 for (c = b->chan; c < b->chan + NCHAN; ++c) { 1487 drv_t *d = (drv_t*) c->sys; 1488 1489 if (! d || ! d->chan->type) 1490 continue; 1491 channel [b->num*NCHAN + c->num] = 0; 1492 /* Deallocate buffers. */ 1493 cp_bus_dma_mem_free (&d->dmamem); 1494 } 1495 adapter [b->num] = 0; 1496 cp_bus_dma_mem_free (&bd->dmamem); 1497 free (b, M_DEVBUF); 1498 splx (s); 1499 mtx_destroy (&bd->cp_mtx); 1500 return 0; 1501} 1502 1503#ifndef NETGRAPH 1504static void cp_ifstart (struct ifnet *ifp) 1505{ 1506 drv_t *d = ifp->if_softc; 1507 bdrv_t *bd = d->board->sys; 1508 1509 CP_LOCK (bd); 1510 cp_start (d); 1511 CP_UNLOCK (bd); 1512} 1513 1514static void cp_ifwatchdog (struct ifnet *ifp) 1515{ 1516 drv_t *d = ifp->if_softc; 1517 1518 cp_watchdog (d); 1519} 1520 1521static void cp_tlf (struct sppp *sp) 1522{ 1523 drv_t *d = SP2IFP(sp)->if_softc; 1524 1525 CP_DEBUG2 (d, ("cp_tlf\n")); 1526 /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */ 1527/* cp_set_dtr (d->chan, 0);*/ 1528/* cp_set_rts (d->chan, 0);*/ 1529 if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 1530 sp->pp_down (sp); 1531} 1532 1533static void cp_tls (struct sppp *sp) 1534{ 1535 drv_t *d = SP2IFP(sp)->if_softc; 1536 1537 CP_DEBUG2 (d, ("cp_tls\n")); 1538 if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 1539 sp->pp_up (sp); 1540} 1541 1542/* 1543 * Process an ioctl request. 1544 */ 1545static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 1546{ 1547 drv_t *d = ifp->if_softc; 1548 bdrv_t *bd = d->board->sys; 1549 int error, s, was_up, should_be_up; 1550 1551 was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 1552 error = sppp_ioctl (ifp, cmd, data); 1553 1554 if (error) 1555 return error; 1556 1557 if (! (ifp->if_flags & IFF_DEBUG)) 1558 d->chan->debug = 0; 1559 else if (! d->chan->debug) 1560 d->chan->debug = 1; 1561 1562 switch (cmd) { 1563 default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 1564 case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 1565 case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 1566 case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 1567 case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 1568 } 1569 1570 /* We get here only in case of SIFFLAGS or SIFADDR. */ 1571 s = splimp (); 1572 CP_LOCK (bd); 1573 should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 1574 if (! was_up && should_be_up) { 1575 /* Interface goes up -- start it. */ 1576 cp_up (d); 1577 cp_start (d); 1578 } else if (was_up && ! should_be_up) { 1579 /* Interface is going down -- stop it. */ 1580/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 1581 cp_down (d); 1582 } 1583 CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 1584 CP_UNLOCK (bd); 1585 splx (s); 1586 return 0; 1587} 1588 1589/* 1590 * Initialization of interface. 1591 * It seems to be never called by upper level? 1592 */ 1593static void cp_initialize (void *softc) 1594{ 1595 drv_t *d = softc; 1596 1597 CP_DEBUG (d, ("cp_initialize\n")); 1598} 1599#endif /*NETGRAPH*/ 1600 1601/* 1602 * Stop the interface. Called on splimp(). 1603 */ 1604static void cp_down (drv_t *d) 1605{ 1606 CP_DEBUG (d, ("cp_down\n")); 1607 /* Interface is going down -- stop it. */ 1608 cp_set_dtr (d->chan, 0); 1609 cp_set_rts (d->chan, 0); 1610 1611 d->running = 0; 1612} 1613 1614/* 1615 * Start the interface. Called on splimp(). 1616 */ 1617static void cp_up (drv_t *d) 1618{ 1619 CP_DEBUG (d, ("cp_up\n")); 1620 cp_set_dtr (d->chan, 1); 1621 cp_set_rts (d->chan, 1); 1622 d->running = 1; 1623} 1624 1625/* 1626 * Start output on the interface. Get another datagram to send 1627 * off of the interface queue, and copy it to the interface 1628 * before starting the output. 1629 */ 1630static void cp_send (drv_t *d) 1631{ 1632 struct mbuf *m; 1633 u_short len; 1634 1635 CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); 1636 1637 /* No output if the interface is down. */ 1638 if (! d->running) 1639 return; 1640 1641 /* No output if the modem is off. */ 1642 if (! (d->chan->lloop || d->chan->type != T_SERIAL || 1643 cp_get_dsr (d->chan))) 1644 return; 1645 1646 while (cp_transmit_space (d->chan)) { 1647 /* Get the packet to send. */ 1648#ifdef NETGRAPH 1649 IF_DEQUEUE (&d->hi_queue, m); 1650 if (! m) 1651 IF_DEQUEUE (&d->queue, m); 1652#else 1653 m = sppp_dequeue (d->ifp); 1654#endif 1655 if (! m) 1656 return; 1657#ifndef NETGRAPH 1658 if (d->ifp->if_bpf) 1659 BPF_MTAP (d->ifp, m); 1660#endif 1661 len = m_length (m, NULL); 1662 if (len >= BUFSZ) 1663 printf ("%s: too long packet: %d bytes: ", 1664 d->name, len); 1665 else if (! m->m_next) 1666 cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 1667 else { 1668 u_char *buf = d->chan->tbuf[d->chan->te]; 1669 m_copydata (m, 0, len, buf); 1670 cp_send_packet (d->chan, buf, len, 0); 1671 } 1672 m_freem (m); 1673 /* Set up transmit timeout, if the transmit ring is not empty.*/ 1674#ifdef NETGRAPH 1675 d->timeout = 10; 1676#else 1677 d->ifp->if_timer = 10; 1678#endif 1679 } 1680#ifndef NETGRAPH 1681 d->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1682#endif 1683} 1684 1685/* 1686 * Start output on the interface. 1687 * Always called on splimp(). 1688 */ 1689static void cp_start (drv_t *d) 1690{ 1691 if (d->running) { 1692 if (! d->chan->dtr) 1693 cp_set_dtr (d->chan, 1); 1694 if (! d->chan->rts) 1695 cp_set_rts (d->chan, 1); 1696 cp_send (d); 1697 } 1698} 1699 1700/* 1701 * Handle transmit timeouts. 1702 * Recover after lost transmit interrupts. 1703 * Always called on splimp(). 1704 */ 1705static void cp_watchdog (drv_t *d) 1706{ 1707 bdrv_t *bd = d->board->sys; 1708 CP_DEBUG (d, ("device timeout\n")); 1709 if (d->running) { 1710 int s = splimp (); 1711 1712 CP_LOCK (bd); 1713 cp_stop_chan (d->chan); 1714 cp_stop_e1 (d->chan); 1715 cp_start_e1 (d->chan); 1716 cp_start_chan (d->chan, 1, 1, 0, 0); 1717 cp_set_dtr (d->chan, 1); 1718 cp_set_rts (d->chan, 1); 1719 cp_start (d); 1720 CP_UNLOCK (bd); 1721 splx (s); 1722 } 1723} 1724 1725static void cp_transmit (cp_chan_t *c, void *attachment, int len) 1726{ 1727 drv_t *d = c->sys; 1728 1729#ifdef NETGRAPH 1730 d->timeout = 0; 1731#else 1732 ++d->ifp->if_opackets; 1733 d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1734 d->ifp->if_timer = 0; 1735#endif 1736 cp_start (d); 1737} 1738 1739static void cp_receive (cp_chan_t *c, unsigned char *data, int len) 1740{ 1741 drv_t *d = c->sys; 1742 struct mbuf *m; 1743#ifdef NETGRAPH 1744 int error; 1745#endif 1746 1747 if (! d->running) 1748 return; 1749 1750 m = makembuf (data, len); 1751 if (! m) { 1752 CP_DEBUG (d, ("no memory for packet\n")); 1753#ifndef NETGRAPH 1754 ++d->ifp->if_iqdrops; 1755#endif 1756 return; 1757 } 1758 if (c->debug > 1) 1759 printmbuf (m); 1760#ifdef NETGRAPH 1761 m->m_pkthdr.rcvif = 0; 1762 NG_SEND_DATA_ONLY (error, d->hook, m); 1763#else 1764 ++d->ifp->if_ipackets; 1765 m->m_pkthdr.rcvif = d->ifp; 1766 /* Check if there's a BPF listener on this interface. 1767 * If so, hand off the raw packet to bpf. */ 1768 if (d->ifp->if_bpf) 1769 BPF_TAP (d->ifp, data, len); 1770 IF_ENQUEUE (&d->queue, m); 1771#endif 1772} 1773 1774static void cp_error (cp_chan_t *c, int data) 1775{ 1776 drv_t *d = c->sys; 1777 1778 switch (data) { 1779 case CP_FRAME: 1780 CP_DEBUG (d, ("frame error\n")); 1781#ifndef NETGRAPH 1782 ++d->ifp->if_ierrors; 1783#endif 1784 break; 1785 case CP_CRC: 1786 CP_DEBUG (d, ("crc error\n")); 1787#ifndef NETGRAPH 1788 ++d->ifp->if_ierrors; 1789#endif 1790 break; 1791 case CP_OVERRUN: 1792 CP_DEBUG (d, ("overrun error\n")); 1793#ifndef NETGRAPH 1794 ++d->ifp->if_collisions; 1795 ++d->ifp->if_ierrors; 1796#endif 1797 break; 1798 case CP_OVERFLOW: 1799 CP_DEBUG (d, ("overflow error\n")); 1800#ifndef NETGRAPH 1801 ++d->ifp->if_ierrors; 1802#endif 1803 break; 1804 case CP_UNDERRUN: 1805 CP_DEBUG (d, ("underrun error\n")); 1806#ifdef NETGRAPH 1807 d->timeout = 0; 1808#else 1809 ++d->ifp->if_oerrors; 1810 d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1811 d->ifp->if_timer = 0; 1812#endif 1813 cp_start (d); 1814 break; 1815 default: 1816 CP_DEBUG (d, ("error #%d\n", data)); 1817 break; 1818 } 1819} 1820 1821#ifdef NETGRAPH 1822static int ng_cp_constructor (node_p node) 1823{ 1824 drv_t *d = NG_NODE_PRIVATE (node); 1825 CP_DEBUG (d, ("Constructor\n")); 1826 return EINVAL; 1827} 1828 1829static int ng_cp_newhook (node_p node, hook_p hook, const char *name) 1830{ 1831 int s; 1832 drv_t *d = NG_NODE_PRIVATE (node); 1833 bdrv_t *bd = d->board->sys; 1834 1835 CP_DEBUG (d, ("Newhook\n")); 1836 /* Attach debug hook */ 1837 if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) { 1838 NG_HOOK_SET_PRIVATE (hook, NULL); 1839 d->debug_hook = hook; 1840 return 0; 1841 } 1842 1843 /* Check for raw hook */ 1844 if (strcmp (name, NG_CP_HOOK_RAW) != 0) 1845 return EINVAL; 1846 1847 NG_HOOK_SET_PRIVATE (hook, d); 1848 d->hook = hook; 1849 s = splimp (); 1850 CP_LOCK (bd); 1851 cp_up (d); 1852 CP_UNLOCK (bd); 1853 splx (s); 1854 return 0; 1855} 1856 1857static char *format_timeslots (u_long s) 1858{ 1859 static char buf [100]; 1860 char *p = buf; 1861 int i; 1862 1863 for (i=1; i<32; ++i) 1864 if ((s >> i) & 1) { 1865 int prev = (i > 1) & (s >> (i-1)); 1866 int next = (i < 31) & (s >> (i+1)); 1867 1868 if (prev) { 1869 if (next) 1870 continue; 1871 *p++ = '-'; 1872 } else if (p > buf) 1873 *p++ = ','; 1874 1875 if (i >= 10) 1876 *p++ = '0' + i / 10; 1877 *p++ = '0' + i % 10; 1878 } 1879 *p = 0; 1880 return buf; 1881} 1882 1883static int print_modems (char *s, cp_chan_t *c, int need_header) 1884{ 1885 int status = cp_modem_status (c); 1886 int length = 0; 1887 1888 if (need_header) 1889 length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1890 length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1891 status & TIOCM_LE ? "On" : "-", 1892 status & TIOCM_DTR ? "On" : "-", 1893 status & TIOCM_DSR ? "On" : "-", 1894 status & TIOCM_RTS ? "On" : "-", 1895 status & TIOCM_CTS ? "On" : "-", 1896 status & TIOCM_CD ? "On" : "-"); 1897 return length; 1898} 1899 1900static int print_stats (char *s, cp_chan_t *c, int need_header) 1901{ 1902 int length = 0; 1903 1904 if (need_header) 1905 length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1906 length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 1907 c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 1908 c->ipkts, c->overrun + c->frame + c->crc, 1909 (unsigned long) c->obytes, c->opkts, c->underrun); 1910 return length; 1911} 1912 1913static char *format_e1_status (u_char status) 1914{ 1915 static char buf [80]; 1916 1917 if (status & E1_NOALARM) 1918 return "Ok"; 1919 buf[0] = 0; 1920 if (status & E1_LOS) strcat (buf, ",LOS"); 1921 if (status & E1_AIS) strcat (buf, ",AIS"); 1922 if (status & E1_LOF) strcat (buf, ",LOF"); 1923 if (status & E1_LOMF) strcat (buf, ",LOMF"); 1924 if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1925 if (status & E1_AIS16) strcat (buf, ",AIS16"); 1926 if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1927 if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1928 if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1929 if (buf[0] == ',') 1930 return buf+1; 1931 return "Unknown"; 1932} 1933 1934static int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1935{ 1936 int n, length = 0; 1937 1938 if (numerator < 1 || divider < 1) { 1939 length += sprintf (s+length, leftalign ? "/- " : " -"); 1940 return length; 1941 } 1942 n = (int) (0.5 + 1000.0 * numerator / divider); 1943 if (n < 1000) { 1944 length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1945 return length; 1946 } 1947 *(s + length) = leftalign ? '/' : ' '; 1948 length ++; 1949 1950 if (n >= 1000000) n = (n+500) / 1000 * 1000; 1951 else if (n >= 100000) n = (n+50) / 100 * 100; 1952 else if (n >= 10000) n = (n+5) / 10 * 10; 1953 1954 switch (n) { 1955 case 1000: length += printf (s+length, ".999"); return length; 1956 case 10000: n = 9990; break; 1957 case 100000: n = 99900; break; 1958 case 1000000: n = 999000; break; 1959 } 1960 if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1961 else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1962 else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1963 else length += sprintf (s+length, "%d", n/1000); 1964 1965 return length; 1966} 1967 1968static int print_e1_stats (char *s, cp_chan_t *c) 1969{ 1970 struct e1_counters total; 1971 u_long totsec; 1972 int length = 0; 1973 1974 totsec = c->totsec + c->cursec; 1975 total.bpv = c->total.bpv + c->currnt.bpv; 1976 total.fse = c->total.fse + c->currnt.fse; 1977 total.crce = c->total.crce + c->currnt.crce; 1978 total.rcrce = c->total.rcrce + c->currnt.rcrce; 1979 total.uas = c->total.uas + c->currnt.uas; 1980 total.les = c->total.les + c->currnt.les; 1981 total.es = c->total.es + c->currnt.es; 1982 total.bes = c->total.bes + c->currnt.bes; 1983 total.ses = c->total.ses + c->currnt.ses; 1984 total.oofs = c->total.oofs + c->currnt.oofs; 1985 total.css = c->total.css + c->currnt.css; 1986 total.dm = c->total.dm + c->currnt.dm; 1987 1988 length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1989 1990 /* Unavailable seconds, degraded minutes */ 1991 length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1992 length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1993 1994 /* Bipolar violations, frame sync errors */ 1995 length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 1996 length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 1997 1998 /* CRC errors, remote CRC errors (E-bit) */ 1999 length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 2000 length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 2001 2002 /* Errored seconds, line errored seconds */ 2003 length += print_frac (s + length, 0, c->currnt.es, c->cursec); 2004 length += print_frac (s + length, 1, c->currnt.les, c->cursec); 2005 2006 /* Severely errored seconds, burst errored seconds */ 2007 length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 2008 length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 2009 2010 /* Out of frame seconds, controlled slip seconds */ 2011 length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 2012 length += print_frac (s + length, 1, c->currnt.css, c->cursec); 2013 2014 length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 2015 2016 /* Print total statistics. */ 2017 length += print_frac (s + length, 0, total.uas, totsec); 2018 length += print_frac (s + length, 1, 60 * total.dm, totsec); 2019 2020 length += print_frac (s + length, 0, total.bpv, totsec); 2021 length += print_frac (s + length, 1, total.fse, totsec); 2022 2023 length += print_frac (s + length, 0, total.crce, totsec); 2024 length += print_frac (s + length, 1, total.rcrce, totsec); 2025 2026 length += print_frac (s + length, 0, total.es, totsec); 2027 length += print_frac (s + length, 1, total.les, totsec); 2028 2029 length += print_frac (s + length, 0, total.ses, totsec); 2030 length += print_frac (s + length, 1, total.bes, totsec); 2031 2032 length += print_frac (s + length, 0, total.oofs, totsec); 2033 length += print_frac (s + length, 1, total.css, totsec); 2034 2035 length += sprintf (s + length, " -- Total\n"); 2036 return length; 2037} 2038 2039static int print_chan (char *s, cp_chan_t *c) 2040{ 2041 drv_t *d = c->sys; 2042 bdrv_t *bd = d->board->sys; 2043 int length = 0; 2044 2045 length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num); 2046 if (d->chan->debug) 2047 length += sprintf (s + length, " debug=%d", d->chan->debug); 2048 2049 if (c->board->mux) { 2050 length += sprintf (s + length, " cfg=C"); 2051 } else { 2052 length += sprintf (s + length, " cfg=A"); 2053 } 2054 2055 if (c->baud) 2056 length += sprintf (s + length, " %ld", c->baud); 2057 else 2058 length += sprintf (s + length, " extclock"); 2059 2060 if (c->type == T_E1 || c->type == T_G703) 2061 switch (c->gsyn) { 2062 case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 2063 case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 2064 case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 2065 case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 2066 case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break; 2067 case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break; 2068 } 2069 if (c->type == T_SERIAL) { 2070 length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off"); 2071 length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off"); 2072 length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off"); 2073 } 2074 if (c->type == T_E1) 2075 length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 2076 2077 length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 2078 2079 if (c->type == T_E1) 2080 length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 2081 if (c->type == T_G703) { 2082 int lq, x; 2083 2084 x = splimp (); 2085 CP_LOCK (bd); 2086 lq = cp_get_lq (c); 2087 CP_UNLOCK (bd); 2088 splx (x); 2089 length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2090 } 2091 length += sprintf (s + length, "\n"); 2092 return length; 2093} 2094 2095static int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook) 2096{ 2097 drv_t *d = NG_NODE_PRIVATE (node); 2098 struct ng_mesg *msg; 2099 struct ng_mesg *resp = NULL; 2100 int error = 0; 2101 2102 CP_DEBUG (d, ("Rcvmsg\n")); 2103 NGI_GET_MSG (item, msg); 2104 switch (msg->header.typecookie) { 2105 default: 2106 error = EINVAL; 2107 break; 2108 2109 case NGM_CP_COOKIE: 2110 printf ("Not implemented yet\n"); 2111 error = EINVAL; 2112 break; 2113 2114 case NGM_GENERIC_COOKIE: 2115 switch (msg->header.cmd) { 2116 default: 2117 error = EINVAL; 2118 break; 2119 2120 case NGM_TEXT_STATUS: { 2121 char *s; 2122 int l = 0; 2123 int dl = sizeof (struct ng_mesg) + 730; 2124 2125 NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2126 if (! resp) { 2127 error = ENOMEM; 2128 break; 2129 } 2130 s = (resp)->data; 2131 if (d) { 2132 l += print_chan (s + l, d->chan); 2133 l += print_stats (s + l, d->chan, 1); 2134 l += print_modems (s + l, d->chan, 1); 2135 l += print_e1_stats (s + l, d->chan); 2136 } else 2137 l += sprintf (s + l, "Error: node not connect to channel"); 2138 strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN); 2139 } 2140 break; 2141 } 2142 break; 2143 } 2144 NG_RESPOND_MSG (error, node, item, resp); 2145 NG_FREE_MSG (msg); 2146 return error; 2147} 2148 2149static int ng_cp_rcvdata (hook_p hook, item_p item) 2150{ 2151 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2152 struct mbuf *m; 2153 struct ng_tag_prio *ptag; 2154 bdrv_t *bd = d->board->sys; 2155 struct ifqueue *q; 2156 int s; 2157 2158 CP_DEBUG2 (d, ("Rcvdata\n")); 2159 NGI_GET_M (item, m); 2160 NG_FREE_ITEM (item); 2161 if (! NG_HOOK_PRIVATE (hook) || ! d) { 2162 NG_FREE_M (m); 2163 return ENETDOWN; 2164 } 2165 2166 /* Check for high priority data */ 2167 if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2168 NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2169 q = &d->hi_queue; 2170 else 2171 q = &d->queue; 2172 2173 s = splimp (); 2174 CP_LOCK (bd); 2175 IF_LOCK (q); 2176 if (_IF_QFULL (q)) { 2177 _IF_DROP (q); 2178 IF_UNLOCK (q); 2179 CP_UNLOCK (bd); 2180 splx (s); 2181 NG_FREE_M (m); 2182 return ENOBUFS; 2183 } 2184 _IF_ENQUEUE (q, m); 2185 IF_UNLOCK (q); 2186 cp_start (d); 2187 CP_UNLOCK (bd); 2188 splx (s); 2189 return 0; 2190} 2191 2192static int ng_cp_rmnode (node_p node) 2193{ 2194 drv_t *d = NG_NODE_PRIVATE (node); 2195 2196 CP_DEBUG (d, ("Rmnode\n")); 2197 if (d && d->running) { 2198 bdrv_t *bd = d->board->sys; 2199 int s = splimp (); 2200 CP_LOCK (bd); 2201 cp_down (d); 2202 CP_UNLOCK (bd); 2203 splx (s); 2204 } 2205#ifdef KLD_MODULE 2206 if (node->nd_flags & NGF_REALLY_DIE) { 2207 NG_NODE_SET_PRIVATE (node, NULL); 2208 NG_NODE_UNREF (node); 2209 } 2210 NG_NODE_REVIVE(node); /* Persistant node */ 2211#endif 2212 return 0; 2213} 2214 2215static void ng_cp_watchdog (void *arg) 2216{ 2217 drv_t *d = arg; 2218 2219 if (d) { 2220 if (d->timeout == 1) 2221 cp_watchdog (d); 2222 if (d->timeout) 2223 d->timeout--; 2224 callout_reset (&d->timeout_handle, hz, ng_cp_watchdog, d); 2225 } 2226} 2227 2228static int ng_cp_connect (hook_p hook) 2229{ 2230 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2231 2232 if (d) { 2233 CP_DEBUG (d, ("Connect\n")); 2234 callout_reset (&d->timeout_handle, hz, ng_cp_watchdog, d); 2235 } 2236 2237 return 0; 2238} 2239 2240static int ng_cp_disconnect (hook_p hook) 2241{ 2242 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2243 2244 if (d) { 2245 CP_DEBUG (d, ("Disconnect\n")); 2246 if (NG_HOOK_PRIVATE (hook)) 2247 { 2248 bdrv_t *bd = d->board->sys; 2249 int s = splimp (); 2250 CP_LOCK (bd); 2251 cp_down (d); 2252 CP_UNLOCK (bd); 2253 splx (s); 2254 } 2255 /* If we were wait it than it reasserted now, just stop it. */ 2256 if (!callout_drain (&d->timeout_handle)) 2257 callout_stop (&d->timeout_handle); 2258 } 2259 return 0; 2260} 2261#endif 2262 2263static int cp_modevent (module_t mod, int type, void *unused) 2264{ 2265 static int load_count = 0; 2266 2267 if (!debug_mpsafenet && cp_mpsafenet) { 2268 printf ("WORNING! Network stack is not MPSAFE. " 2269 "Turning off debug.cp.mpsafenet.\n"); 2270 cp_mpsafenet = 0; 2271 } 2272 if (cp_mpsafenet) 2273 cp_cdevsw.d_flags &= ~D_NEEDGIANT; 2274 2275 switch (type) { 2276 case MOD_LOAD: 2277#ifdef NETGRAPH 2278 if (ng_newtype (&typestruct)) 2279 printf ("Failed to register ng_cp\n"); 2280#endif 2281 ++load_count; 2282 callout_init (&timeout_handle, cp_mpsafenet?CALLOUT_MPSAFE:0); 2283 callout_reset (&timeout_handle, hz*5, cp_timeout, 0); 2284 break; 2285 case MOD_UNLOAD: 2286 if (load_count == 1) { 2287 printf ("Removing device entry for Tau-PCI\n"); 2288#ifdef NETGRAPH 2289 ng_rmtype (&typestruct); 2290#endif 2291 } 2292 /* If we were wait it than it reasserted now, just stop it. 2293 * Actually we shouldn't get this condition. But code could be 2294 * changed in the future, so just be a litle paranoid. 2295 */ 2296 if (!callout_drain (&timeout_handle)) 2297 callout_stop (&timeout_handle); 2298 --load_count; 2299 break; 2300 case MOD_SHUTDOWN: 2301 break; 2302 } 2303 return 0; 2304} 2305 2306#ifdef NETGRAPH 2307static struct ng_type typestruct = { 2308 .version = NG_ABI_VERSION, 2309 .name = NG_CP_NODE_TYPE, 2310 .constructor = ng_cp_constructor, 2311 .rcvmsg = ng_cp_rcvmsg, 2312 .shutdown = ng_cp_rmnode, 2313 .newhook = ng_cp_newhook, 2314 .connect = ng_cp_connect, 2315 .rcvdata = ng_cp_rcvdata, 2316 .disconnect = ng_cp_disconnect, 2317}; 2318#endif /*NETGRAPH*/ 2319 2320#ifdef NETGRAPH 2321MODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2322#else 2323MODULE_DEPEND (cp, sppp, 1, 1, 1); 2324#endif 2325DRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2326MODULE_VERSION (cp, 1); 2327