if_cp.c revision 150306
1266986Smarkj/*- 2266986Smarkj * Cronyx-Tau-PCI adapter driver for FreeBSD. 3266986Smarkj * Supports PPP/HDLC, Cisco/HDLC and FrameRelay protocol in synchronous mode, 4266986Smarkj * and asyncronous channels with full modem control. 5266986Smarkj * Keepalive protocol implemented in both Cisco and PPP modes. 6266986Smarkj * 7266986Smarkj * Copyright (C) 1999-2004 Cronyx Engineering. 8266986Smarkj * Author: Kurakin Roman, <rik@cronyx.ru> 9266986Smarkj * 10266986Smarkj * Copyright (C) 1999-2002 Cronyx Engineering. 11266986Smarkj * Author: Serge Vakulenko, <vak@cronyx.ru> 12266986Smarkj * 13266986Smarkj * This software is distributed with NO WARRANTIES, not even the implied 14266986Smarkj * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15266986Smarkj * 16266986Smarkj * Authors grant any other persons or organisations a permission to use, 17266986Smarkj * modify and redistribute this software in source and binary forms, 18266986Smarkj * as long as this message is kept with the software, all derivative 19266986Smarkj * works or modified versions. 20266986Smarkj * 21266986Smarkj * Cronyx Id: if_cp.c,v 1.1.2.41 2004/06/23 17:09:13 rik Exp $ 22266986Smarkj */ 23266986Smarkj 24266986Smarkj#include <sys/cdefs.h> 25266986Smarkj__FBSDID("$FreeBSD: head/sys/dev/cp/if_cp.c 150306 2005-09-19 03:10:21Z imp $"); 26266986Smarkj 27266986Smarkj#include <sys/param.h> 28266986Smarkj#include <sys/ucred.h> 29266986Smarkj#include <sys/proc.h> 30266986Smarkj#include <sys/systm.h> 31266986Smarkj#include <sys/mbuf.h> 32266986Smarkj#include <sys/kernel.h> 33266986Smarkj#include <sys/module.h> 34266986Smarkj#include <sys/conf.h> 35266986Smarkj#include <sys/malloc.h> 36266986Smarkj#include <sys/socket.h> 37266986Smarkj#include <sys/sockio.h> 38266986Smarkj#include <sys/sysctl.h> 39266986Smarkj#include <sys/tty.h> 40266986Smarkj#include <sys/bus.h> 41266986Smarkj#include <vm/vm.h> 42266986Smarkj#include <vm/pmap.h> 43266986Smarkj#include <net/if.h> 44266986Smarkj#include <dev/pci/pcivar.h> 45266986Smarkj#include <dev/pci/pcireg.h> 46266986Smarkj#include <machine/bus.h> 47266986Smarkj#include <sys/rman.h> 48266986Smarkj#include "opt_ng_cronyx.h" 49266986Smarkj#ifdef NETGRAPH_CRONYX 50266986Smarkj# include "opt_netgraph.h" 51266986Smarkj# ifndef NETGRAPH 52266986Smarkj# error #option NETGRAPH missed from configuration 53266986Smarkj# endif 54266986Smarkj# include <netgraph/ng_message.h> 55266986Smarkj# include <netgraph/netgraph.h> 56266986Smarkj# include <dev/cp/ng_cp.h> 57266986Smarkj#else 58266986Smarkj# include <net/if_sppp.h> 59266986Smarkj# include <net/if_types.h> 60266986Smarkj#include <dev/pci/pcivar.h> 61266986Smarkj# define PP_CISCO IFF_LINK2 62266986Smarkj# include <net/bpf.h> 63266986Smarkj#endif 64266986Smarkj#include <dev/cx/machdep.h> 65266986Smarkj#include <dev/cp/cpddk.h> 66266986Smarkj#include <machine/cserial.h> 67266986Smarkj#include <machine/resource.h> 68266986Smarkj#include <machine/pmap.h> 69266986Smarkj 70266986Smarkj/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 71266986Smarkj#ifndef PP_FR 72266986Smarkj#define PP_FR 0 73266986Smarkj#endif 74266986Smarkj 75266986Smarkj#define CP_DEBUG(d,s) ({if (d->chan->debug) {\ 76266986Smarkj printf ("%s: ", d->name); printf s;}}) 77266986Smarkj#define CP_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 78266986Smarkj printf ("%s: ", d->name); printf s;}}) 79266986Smarkj#define CP_LOCK_NAME "cpX" 80266986Smarkj 81266986Smarkjstatic int cp_mpsafenet = 1; 82266986SmarkjTUNABLE_INT("debug.cp.mpsafenet", &cp_mpsafenet); 83266986SmarkjSYSCTL_NODE(_debug, OID_AUTO, cp, CTLFLAG_RD, 0, "Cronyx Tau-PCI Adapters"); 84266986SmarkjSYSCTL_INT(_debug_cp, OID_AUTO, mpsafenet, CTLFLAG_RD, &cp_mpsafenet, 0, 85266986Smarkj "Enable/disable MPSAFE network support for Cronyx Tau-PCI Adapters"); 86266986Smarkj 87266986Smarkj#define CP_LOCK(_bd) do { \ 88266986Smarkj if (cp_mpsafenet) \ 89266986Smarkj mtx_lock (&(_bd)->cp_mtx); \ 90266986Smarkj } while (0) 91266986Smarkj#define CP_UNLOCK(_bd) do { \ 92266986Smarkj if (cp_mpsafenet) \ 93266986Smarkj mtx_unlock (&(_bd)->cp_mtx); \ 94266986Smarkj } while (0) 95266986Smarkj 96266986Smarkj#define CP_LOCK_ASSERT(_bd) do { \ 97266986Smarkj if (cp_mpsafenet) \ 98266986Smarkj mtx_assert (&(_bd)->cp_mtx, MA_OWNED); \ 99266986Smarkj } while (0) 100266986Smarkj 101266986Smarkjstatic int cp_probe __P((device_t)); 102266986Smarkjstatic int cp_attach __P((device_t)); 103266986Smarkjstatic int cp_detach __P((device_t)); 104266986Smarkj 105266986Smarkjstatic device_method_t cp_methods[] = { 106266986Smarkj /* Device interface */ 107266986Smarkj DEVMETHOD(device_probe, cp_probe), 108266986Smarkj DEVMETHOD(device_attach, cp_attach), 109266986Smarkj DEVMETHOD(device_detach, cp_detach), 110266986Smarkj 111266986Smarkj {0, 0} 112266986Smarkj}; 113266986Smarkj 114266986Smarkjtypedef struct _cp_dma_mem_t { 115266986Smarkj unsigned long phys; 116266986Smarkj void *virt; 117266986Smarkj size_t size; 118266986Smarkj bus_dma_tag_t dmat; 119266986Smarkj bus_dmamap_t mapp; 120266986Smarkj} cp_dma_mem_t; 121266986Smarkj 122266986Smarkjtypedef struct _drv_t { 123266986Smarkj char name [8]; 124266986Smarkj int running; 125266986Smarkj cp_chan_t *chan; 126266986Smarkj cp_board_t *board; 127266986Smarkj cp_dma_mem_t dmamem; 128266986Smarkj#ifdef NETGRAPH 129266986Smarkj char nodename [NG_NODELEN+1]; 130266986Smarkj hook_p hook; 131266986Smarkj hook_p debug_hook; 132266986Smarkj node_p node; 133266986Smarkj struct ifqueue queue; 134266986Smarkj struct ifqueue hi_queue; 135266986Smarkj short timeout; 136266986Smarkj struct callout timeout_handle; 137266986Smarkj#else 138266986Smarkj 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 /* Disable the interrupt request. */ 1442 bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); 1443 1444 for (c=b->chan; c<b->chan+NCHAN; ++c) { 1445 drv_t *d = (drv_t*) c->sys; 1446 1447 if (! d || ! d->chan->type) 1448 continue; 1449#ifndef NETGRAPH 1450 /* Detach from the packet filter list of interfaces. */ 1451 bpfdetach (d->ifp); 1452 1453 /* Detach from the sync PPP list. */ 1454 sppp_detach (d->ifp); 1455 1456 /* Detach from the system list of interfaces. */ 1457 if_detach (d->ifp); 1458 if_free (d->ifp); 1459 IF_DRAIN (&d->queue); 1460 mtx_destroy (&d->queue.ifq_mtx); 1461#else 1462 if (d->node) { 1463 ng_rmnode_self (d->node); 1464 NG_NODE_UNREF (d->node); 1465 d->node = NULL; 1466 } 1467 mtx_destroy (&d->queue.ifq_mtx); 1468 mtx_destroy (&d->hi_queue.ifq_mtx); 1469#endif 1470 destroy_dev (d->devt); 1471 } 1472 1473 b->sys = NULL; 1474 CP_UNLOCK (bd); 1475 1476 bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 1477 bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); 1478 bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); 1479 1480 CP_LOCK (bd); 1481 cp_led_off (b); 1482 CP_UNLOCK (bd); 1483 callout_drain (&led_timo[b->num]); 1484 splx (s); 1485 1486 s = splimp (); 1487 for (c = b->chan; c < b->chan + NCHAN; ++c) { 1488 drv_t *d = (drv_t*) c->sys; 1489 1490 if (! d || ! d->chan->type) 1491 continue; 1492 channel [b->num*NCHAN + c->num] = 0; 1493 /* Deallocate buffers. */ 1494 cp_bus_dma_mem_free (&d->dmamem); 1495 } 1496 adapter [b->num] = 0; 1497 cp_bus_dma_mem_free (&bd->dmamem); 1498 free (b, M_DEVBUF); 1499 splx (s); 1500 mtx_destroy (&bd->cp_mtx); 1501 return 0; 1502} 1503 1504#ifndef NETGRAPH 1505static void cp_ifstart (struct ifnet *ifp) 1506{ 1507 drv_t *d = ifp->if_softc; 1508 bdrv_t *bd = d->board->sys; 1509 1510 CP_LOCK (bd); 1511 cp_start (d); 1512 CP_UNLOCK (bd); 1513} 1514 1515static void cp_ifwatchdog (struct ifnet *ifp) 1516{ 1517 drv_t *d = ifp->if_softc; 1518 1519 cp_watchdog (d); 1520} 1521 1522static void cp_tlf (struct sppp *sp) 1523{ 1524 drv_t *d = SP2IFP(sp)->if_softc; 1525 1526 CP_DEBUG2 (d, ("cp_tlf\n")); 1527 /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */ 1528/* cp_set_dtr (d->chan, 0);*/ 1529/* cp_set_rts (d->chan, 0);*/ 1530 if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 1531 sp->pp_down (sp); 1532} 1533 1534static void cp_tls (struct sppp *sp) 1535{ 1536 drv_t *d = SP2IFP(sp)->if_softc; 1537 1538 CP_DEBUG2 (d, ("cp_tls\n")); 1539 if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 1540 sp->pp_up (sp); 1541} 1542 1543/* 1544 * Process an ioctl request. 1545 */ 1546static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 1547{ 1548 drv_t *d = ifp->if_softc; 1549 bdrv_t *bd = d->board->sys; 1550 int error, s, was_up, should_be_up; 1551 1552 was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 1553 error = sppp_ioctl (ifp, cmd, data); 1554 1555 if (error) 1556 return error; 1557 1558 if (! (ifp->if_flags & IFF_DEBUG)) 1559 d->chan->debug = 0; 1560 else if (! d->chan->debug) 1561 d->chan->debug = 1; 1562 1563 switch (cmd) { 1564 default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 1565 case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; 1566 case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; 1567 case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; 1568 case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; 1569 } 1570 1571 /* We get here only in case of SIFFLAGS or SIFADDR. */ 1572 s = splimp (); 1573 CP_LOCK (bd); 1574 should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 1575 if (! was_up && should_be_up) { 1576 /* Interface goes up -- start it. */ 1577 cp_up (d); 1578 cp_start (d); 1579 } else if (was_up && ! should_be_up) { 1580 /* Interface is going down -- stop it. */ 1581/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 1582 cp_down (d); 1583 } 1584 CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); 1585 CP_UNLOCK (bd); 1586 splx (s); 1587 return 0; 1588} 1589 1590/* 1591 * Initialization of interface. 1592 * It seems to be never called by upper level? 1593 */ 1594static void cp_initialize (void *softc) 1595{ 1596 drv_t *d = softc; 1597 1598 CP_DEBUG (d, ("cp_initialize\n")); 1599} 1600#endif /*NETGRAPH*/ 1601 1602/* 1603 * Stop the interface. Called on splimp(). 1604 */ 1605static void cp_down (drv_t *d) 1606{ 1607 CP_DEBUG (d, ("cp_down\n")); 1608 /* Interface is going down -- stop it. */ 1609 cp_set_dtr (d->chan, 0); 1610 cp_set_rts (d->chan, 0); 1611 1612 d->running = 0; 1613} 1614 1615/* 1616 * Start the interface. Called on splimp(). 1617 */ 1618static void cp_up (drv_t *d) 1619{ 1620 CP_DEBUG (d, ("cp_up\n")); 1621 cp_set_dtr (d->chan, 1); 1622 cp_set_rts (d->chan, 1); 1623 d->running = 1; 1624} 1625 1626/* 1627 * Start output on the interface. Get another datagram to send 1628 * off of the interface queue, and copy it to the interface 1629 * before starting the output. 1630 */ 1631static void cp_send (drv_t *d) 1632{ 1633 struct mbuf *m; 1634 u_short len; 1635 1636 CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); 1637 1638 /* No output if the interface is down. */ 1639 if (! d->running) 1640 return; 1641 1642 /* No output if the modem is off. */ 1643 if (! (d->chan->lloop || d->chan->type != T_SERIAL || 1644 cp_get_dsr (d->chan))) 1645 return; 1646 1647 while (cp_transmit_space (d->chan)) { 1648 /* Get the packet to send. */ 1649#ifdef NETGRAPH 1650 IF_DEQUEUE (&d->hi_queue, m); 1651 if (! m) 1652 IF_DEQUEUE (&d->queue, m); 1653#else 1654 m = sppp_dequeue (d->ifp); 1655#endif 1656 if (! m) 1657 return; 1658#ifndef NETGRAPH 1659 if (d->ifp->if_bpf) 1660 BPF_MTAP (d->ifp, m); 1661#endif 1662 len = m_length (m, NULL); 1663 if (len >= BUFSZ) 1664 printf ("%s: too long packet: %d bytes: ", 1665 d->name, len); 1666 else if (! m->m_next) 1667 cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); 1668 else { 1669 u_char *buf = d->chan->tbuf[d->chan->te]; 1670 m_copydata (m, 0, len, buf); 1671 cp_send_packet (d->chan, buf, len, 0); 1672 } 1673 m_freem (m); 1674 /* Set up transmit timeout, if the transmit ring is not empty.*/ 1675#ifdef NETGRAPH 1676 d->timeout = 10; 1677#else 1678 d->ifp->if_timer = 10; 1679#endif 1680 } 1681#ifndef NETGRAPH 1682 d->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1683#endif 1684} 1685 1686/* 1687 * Start output on the interface. 1688 * Always called on splimp(). 1689 */ 1690static void cp_start (drv_t *d) 1691{ 1692 if (d->running) { 1693 if (! d->chan->dtr) 1694 cp_set_dtr (d->chan, 1); 1695 if (! d->chan->rts) 1696 cp_set_rts (d->chan, 1); 1697 cp_send (d); 1698 } 1699} 1700 1701/* 1702 * Handle transmit timeouts. 1703 * Recover after lost transmit interrupts. 1704 * Always called on splimp(). 1705 */ 1706static void cp_watchdog (drv_t *d) 1707{ 1708 bdrv_t *bd = d->board->sys; 1709 CP_DEBUG (d, ("device timeout\n")); 1710 if (d->running) { 1711 int s = splimp (); 1712 1713 CP_LOCK (bd); 1714 cp_stop_chan (d->chan); 1715 cp_stop_e1 (d->chan); 1716 cp_start_e1 (d->chan); 1717 cp_start_chan (d->chan, 1, 1, 0, 0); 1718 cp_set_dtr (d->chan, 1); 1719 cp_set_rts (d->chan, 1); 1720 cp_start (d); 1721 CP_UNLOCK (bd); 1722 splx (s); 1723 } 1724} 1725 1726static void cp_transmit (cp_chan_t *c, void *attachment, int len) 1727{ 1728 drv_t *d = c->sys; 1729 1730#ifdef NETGRAPH 1731 d->timeout = 0; 1732#else 1733 ++d->ifp->if_opackets; 1734 d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1735 d->ifp->if_timer = 0; 1736#endif 1737 cp_start (d); 1738} 1739 1740static void cp_receive (cp_chan_t *c, unsigned char *data, int len) 1741{ 1742 drv_t *d = c->sys; 1743 struct mbuf *m; 1744#ifdef NETGRAPH 1745 int error; 1746#endif 1747 1748 if (! d->running) 1749 return; 1750 1751 m = makembuf (data, len); 1752 if (! m) { 1753 CP_DEBUG (d, ("no memory for packet\n")); 1754#ifndef NETGRAPH 1755 ++d->ifp->if_iqdrops; 1756#endif 1757 return; 1758 } 1759 if (c->debug > 1) 1760 printmbuf (m); 1761#ifdef NETGRAPH 1762 m->m_pkthdr.rcvif = 0; 1763 NG_SEND_DATA_ONLY (error, d->hook, m); 1764#else 1765 ++d->ifp->if_ipackets; 1766 m->m_pkthdr.rcvif = d->ifp; 1767 /* Check if there's a BPF listener on this interface. 1768 * If so, hand off the raw packet to bpf. */ 1769 if (d->ifp->if_bpf) 1770 BPF_TAP (d->ifp, data, len); 1771 IF_ENQUEUE (&d->queue, m); 1772#endif 1773} 1774 1775static void cp_error (cp_chan_t *c, int data) 1776{ 1777 drv_t *d = c->sys; 1778 1779 switch (data) { 1780 case CP_FRAME: 1781 CP_DEBUG (d, ("frame error\n")); 1782#ifndef NETGRAPH 1783 ++d->ifp->if_ierrors; 1784#endif 1785 break; 1786 case CP_CRC: 1787 CP_DEBUG (d, ("crc error\n")); 1788#ifndef NETGRAPH 1789 ++d->ifp->if_ierrors; 1790#endif 1791 break; 1792 case CP_OVERRUN: 1793 CP_DEBUG (d, ("overrun error\n")); 1794#ifndef NETGRAPH 1795 ++d->ifp->if_collisions; 1796 ++d->ifp->if_ierrors; 1797#endif 1798 break; 1799 case CP_OVERFLOW: 1800 CP_DEBUG (d, ("overflow error\n")); 1801#ifndef NETGRAPH 1802 ++d->ifp->if_ierrors; 1803#endif 1804 break; 1805 case CP_UNDERRUN: 1806 CP_DEBUG (d, ("underrun error\n")); 1807#ifdef NETGRAPH 1808 d->timeout = 0; 1809#else 1810 ++d->ifp->if_oerrors; 1811 d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1812 d->ifp->if_timer = 0; 1813#endif 1814 cp_start (d); 1815 break; 1816 default: 1817 CP_DEBUG (d, ("error #%d\n", data)); 1818 break; 1819 } 1820} 1821 1822#ifdef NETGRAPH 1823static int ng_cp_constructor (node_p node) 1824{ 1825 drv_t *d = NG_NODE_PRIVATE (node); 1826 CP_DEBUG (d, ("Constructor\n")); 1827 return EINVAL; 1828} 1829 1830static int ng_cp_newhook (node_p node, hook_p hook, const char *name) 1831{ 1832 int s; 1833 drv_t *d = NG_NODE_PRIVATE (node); 1834 bdrv_t *bd = d->board->sys; 1835 1836 CP_DEBUG (d, ("Newhook\n")); 1837 /* Attach debug hook */ 1838 if (strcmp (name, NG_CP_HOOK_DEBUG) == 0) { 1839 NG_HOOK_SET_PRIVATE (hook, NULL); 1840 d->debug_hook = hook; 1841 return 0; 1842 } 1843 1844 /* Check for raw hook */ 1845 if (strcmp (name, NG_CP_HOOK_RAW) != 0) 1846 return EINVAL; 1847 1848 NG_HOOK_SET_PRIVATE (hook, d); 1849 d->hook = hook; 1850 s = splimp (); 1851 CP_LOCK (bd); 1852 cp_up (d); 1853 CP_UNLOCK (bd); 1854 splx (s); 1855 return 0; 1856} 1857 1858static char *format_timeslots (u_long s) 1859{ 1860 static char buf [100]; 1861 char *p = buf; 1862 int i; 1863 1864 for (i=1; i<32; ++i) 1865 if ((s >> i) & 1) { 1866 int prev = (i > 1) & (s >> (i-1)); 1867 int next = (i < 31) & (s >> (i+1)); 1868 1869 if (prev) { 1870 if (next) 1871 continue; 1872 *p++ = '-'; 1873 } else if (p > buf) 1874 *p++ = ','; 1875 1876 if (i >= 10) 1877 *p++ = '0' + i / 10; 1878 *p++ = '0' + i % 10; 1879 } 1880 *p = 0; 1881 return buf; 1882} 1883 1884static int print_modems (char *s, cp_chan_t *c, int need_header) 1885{ 1886 int status = cp_modem_status (c); 1887 int length = 0; 1888 1889 if (need_header) 1890 length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 1891 length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 1892 status & TIOCM_LE ? "On" : "-", 1893 status & TIOCM_DTR ? "On" : "-", 1894 status & TIOCM_DSR ? "On" : "-", 1895 status & TIOCM_RTS ? "On" : "-", 1896 status & TIOCM_CTS ? "On" : "-", 1897 status & TIOCM_CD ? "On" : "-"); 1898 return length; 1899} 1900 1901static int print_stats (char *s, cp_chan_t *c, int need_header) 1902{ 1903 int length = 0; 1904 1905 if (need_header) 1906 length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 1907 length += sprintf (s + length, "%7ld %7ld %7ld %8lu %7ld %7ld %8lu %7ld %7ld\n", 1908 c->rintr, c->tintr, 0l, (unsigned long) c->ibytes, 1909 c->ipkts, c->overrun + c->frame + c->crc, 1910 (unsigned long) c->obytes, c->opkts, c->underrun); 1911 return length; 1912} 1913 1914static char *format_e1_status (u_char status) 1915{ 1916 static char buf [80]; 1917 1918 if (status & E1_NOALARM) 1919 return "Ok"; 1920 buf[0] = 0; 1921 if (status & E1_LOS) strcat (buf, ",LOS"); 1922 if (status & E1_AIS) strcat (buf, ",AIS"); 1923 if (status & E1_LOF) strcat (buf, ",LOF"); 1924 if (status & E1_LOMF) strcat (buf, ",LOMF"); 1925 if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 1926 if (status & E1_AIS16) strcat (buf, ",AIS16"); 1927 if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 1928 if (status & E1_TSTREQ) strcat (buf, ",TSTREQ"); 1929 if (status & E1_TSTERR) strcat (buf, ",TSTERR"); 1930 if (buf[0] == ',') 1931 return buf+1; 1932 return "Unknown"; 1933} 1934 1935static int print_frac (char *s, int leftalign, u_long numerator, u_long divider) 1936{ 1937 int n, length = 0; 1938 1939 if (numerator < 1 || divider < 1) { 1940 length += sprintf (s+length, leftalign ? "/- " : " -"); 1941 return length; 1942 } 1943 n = (int) (0.5 + 1000.0 * numerator / divider); 1944 if (n < 1000) { 1945 length += sprintf (s+length, leftalign ? "/.%-3d" : " .%03d", n); 1946 return length; 1947 } 1948 *(s + length) = leftalign ? '/' : ' '; 1949 length ++; 1950 1951 if (n >= 1000000) n = (n+500) / 1000 * 1000; 1952 else if (n >= 100000) n = (n+50) / 100 * 100; 1953 else if (n >= 10000) n = (n+5) / 10 * 10; 1954 1955 switch (n) { 1956 case 1000: length += printf (s+length, ".999"); return length; 1957 case 10000: n = 9990; break; 1958 case 100000: n = 99900; break; 1959 case 1000000: n = 999000; break; 1960 } 1961 if (n < 10000) length += sprintf (s+length, "%d.%d", n/1000, n/10%100); 1962 else if (n < 100000) length += sprintf (s+length, "%d.%d", n/1000, n/100%10); 1963 else if (n < 1000000) length += sprintf (s+length, "%d.", n/1000); 1964 else length += sprintf (s+length, "%d", n/1000); 1965 1966 return length; 1967} 1968 1969static int print_e1_stats (char *s, cp_chan_t *c) 1970{ 1971 struct e1_counters total; 1972 u_long totsec; 1973 int length = 0; 1974 1975 totsec = c->totsec + c->cursec; 1976 total.bpv = c->total.bpv + c->currnt.bpv; 1977 total.fse = c->total.fse + c->currnt.fse; 1978 total.crce = c->total.crce + c->currnt.crce; 1979 total.rcrce = c->total.rcrce + c->currnt.rcrce; 1980 total.uas = c->total.uas + c->currnt.uas; 1981 total.les = c->total.les + c->currnt.les; 1982 total.es = c->total.es + c->currnt.es; 1983 total.bes = c->total.bes + c->currnt.bes; 1984 total.ses = c->total.ses + c->currnt.ses; 1985 total.oofs = c->total.oofs + c->currnt.oofs; 1986 total.css = c->total.css + c->currnt.css; 1987 total.dm = c->total.dm + c->currnt.dm; 1988 1989 length += sprintf (s + length, " Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 1990 1991 /* Unavailable seconds, degraded minutes */ 1992 length += print_frac (s + length, 0, c->currnt.uas, c->cursec); 1993 length += print_frac (s + length, 1, 60 * c->currnt.dm, c->cursec); 1994 1995 /* Bipolar violations, frame sync errors */ 1996 length += print_frac (s + length, 0, c->currnt.bpv, c->cursec); 1997 length += print_frac (s + length, 1, c->currnt.fse, c->cursec); 1998 1999 /* CRC errors, remote CRC errors (E-bit) */ 2000 length += print_frac (s + length, 0, c->currnt.crce, c->cursec); 2001 length += print_frac (s + length, 1, c->currnt.rcrce, c->cursec); 2002 2003 /* Errored seconds, line errored seconds */ 2004 length += print_frac (s + length, 0, c->currnt.es, c->cursec); 2005 length += print_frac (s + length, 1, c->currnt.les, c->cursec); 2006 2007 /* Severely errored seconds, burst errored seconds */ 2008 length += print_frac (s + length, 0, c->currnt.ses, c->cursec); 2009 length += print_frac (s + length, 1, c->currnt.bes, c->cursec); 2010 2011 /* Out of frame seconds, controlled slip seconds */ 2012 length += print_frac (s + length, 0, c->currnt.oofs, c->cursec); 2013 length += print_frac (s + length, 1, c->currnt.css, c->cursec); 2014 2015 length += sprintf (s + length, " %s\n", format_e1_status (c->status)); 2016 2017 /* Print total statistics. */ 2018 length += print_frac (s + length, 0, total.uas, totsec); 2019 length += print_frac (s + length, 1, 60 * total.dm, totsec); 2020 2021 length += print_frac (s + length, 0, total.bpv, totsec); 2022 length += print_frac (s + length, 1, total.fse, totsec); 2023 2024 length += print_frac (s + length, 0, total.crce, totsec); 2025 length += print_frac (s + length, 1, total.rcrce, totsec); 2026 2027 length += print_frac (s + length, 0, total.es, totsec); 2028 length += print_frac (s + length, 1, total.les, totsec); 2029 2030 length += print_frac (s + length, 0, total.ses, totsec); 2031 length += print_frac (s + length, 1, total.bes, totsec); 2032 2033 length += print_frac (s + length, 0, total.oofs, totsec); 2034 length += print_frac (s + length, 1, total.css, totsec); 2035 2036 length += sprintf (s + length, " -- Total\n"); 2037 return length; 2038} 2039 2040static int print_chan (char *s, cp_chan_t *c) 2041{ 2042 drv_t *d = c->sys; 2043 bdrv_t *bd = d->board->sys; 2044 int length = 0; 2045 2046 length += sprintf (s + length, "cp%d", c->board->num * NCHAN + c->num); 2047 if (d->chan->debug) 2048 length += sprintf (s + length, " debug=%d", d->chan->debug); 2049 2050 if (c->board->mux) { 2051 length += sprintf (s + length, " cfg=C"); 2052 } else { 2053 length += sprintf (s + length, " cfg=A"); 2054 } 2055 2056 if (c->baud) 2057 length += sprintf (s + length, " %ld", c->baud); 2058 else 2059 length += sprintf (s + length, " extclock"); 2060 2061 if (c->type == T_E1 || c->type == T_G703) 2062 switch (c->gsyn) { 2063 case GSYN_INT : length += sprintf (s + length, " syn=int"); break; 2064 case GSYN_RCV : length += sprintf (s + length, " syn=rcv"); break; 2065 case GSYN_RCV0 : length += sprintf (s + length, " syn=rcv0"); break; 2066 case GSYN_RCV1 : length += sprintf (s + length, " syn=rcv1"); break; 2067 case GSYN_RCV2 : length += sprintf (s + length, " syn=rcv2"); break; 2068 case GSYN_RCV3 : length += sprintf (s + length, " syn=rcv3"); break; 2069 } 2070 if (c->type == T_SERIAL) { 2071 length += sprintf (s + length, " dpll=%s", c->dpll ? "on" : "off"); 2072 length += sprintf (s + length, " nrzi=%s", c->nrzi ? "on" : "off"); 2073 length += sprintf (s + length, " invclk=%s", c->invtxc ? "on" : "off"); 2074 } 2075 if (c->type == T_E1) 2076 length += sprintf (s + length, " higain=%s", c->higain ? "on" : "off"); 2077 2078 length += sprintf (s + length, " loop=%s", c->lloop ? "on" : "off"); 2079 2080 if (c->type == T_E1) 2081 length += sprintf (s + length, " ts=%s", format_timeslots (c->ts)); 2082 if (c->type == T_G703) { 2083 int lq, x; 2084 2085 x = splimp (); 2086 CP_LOCK (bd); 2087 lq = cp_get_lq (c); 2088 CP_UNLOCK (bd); 2089 splx (x); 2090 length += sprintf (s + length, " (level=-%.1fdB)", lq / 10.0); 2091 } 2092 length += sprintf (s + length, "\n"); 2093 return length; 2094} 2095 2096static int ng_cp_rcvmsg (node_p node, item_p item, hook_p lasthook) 2097{ 2098 drv_t *d = NG_NODE_PRIVATE (node); 2099 struct ng_mesg *msg; 2100 struct ng_mesg *resp = NULL; 2101 int error = 0; 2102 2103 CP_DEBUG (d, ("Rcvmsg\n")); 2104 NGI_GET_MSG (item, msg); 2105 switch (msg->header.typecookie) { 2106 default: 2107 error = EINVAL; 2108 break; 2109 2110 case NGM_CP_COOKIE: 2111 printf ("Not implemented yet\n"); 2112 error = EINVAL; 2113 break; 2114 2115 case NGM_GENERIC_COOKIE: 2116 switch (msg->header.cmd) { 2117 default: 2118 error = EINVAL; 2119 break; 2120 2121 case NGM_TEXT_STATUS: { 2122 char *s; 2123 int l = 0; 2124 int dl = sizeof (struct ng_mesg) + 730; 2125 2126 NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2127 if (! resp) { 2128 error = ENOMEM; 2129 break; 2130 } 2131 s = (resp)->data; 2132 if (d) { 2133 l += print_chan (s + l, d->chan); 2134 l += print_stats (s + l, d->chan, 1); 2135 l += print_modems (s + l, d->chan, 1); 2136 l += print_e1_stats (s + l, d->chan); 2137 } else 2138 l += sprintf (s + l, "Error: node not connect to channel"); 2139 strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN); 2140 } 2141 break; 2142 } 2143 break; 2144 } 2145 NG_RESPOND_MSG (error, node, item, resp); 2146 NG_FREE_MSG (msg); 2147 return error; 2148} 2149 2150static int ng_cp_rcvdata (hook_p hook, item_p item) 2151{ 2152 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2153 struct mbuf *m; 2154 struct ng_tag_prio *ptag; 2155 bdrv_t *bd = d->board->sys; 2156 struct ifqueue *q; 2157 int s; 2158 2159 CP_DEBUG2 (d, ("Rcvdata\n")); 2160 NGI_GET_M (item, m); 2161 NG_FREE_ITEM (item); 2162 if (! NG_HOOK_PRIVATE (hook) || ! d) { 2163 NG_FREE_M (m); 2164 return ENETDOWN; 2165 } 2166 2167 /* Check for high priority data */ 2168 if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2169 NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2170 q = &d->hi_queue; 2171 else 2172 q = &d->queue; 2173 2174 s = splimp (); 2175 CP_LOCK (bd); 2176 IF_LOCK (q); 2177 if (_IF_QFULL (q)) { 2178 _IF_DROP (q); 2179 IF_UNLOCK (q); 2180 CP_UNLOCK (bd); 2181 splx (s); 2182 NG_FREE_M (m); 2183 return ENOBUFS; 2184 } 2185 _IF_ENQUEUE (q, m); 2186 IF_UNLOCK (q); 2187 cp_start (d); 2188 CP_UNLOCK (bd); 2189 splx (s); 2190 return 0; 2191} 2192 2193static int ng_cp_rmnode (node_p node) 2194{ 2195 drv_t *d = NG_NODE_PRIVATE (node); 2196 2197 CP_DEBUG (d, ("Rmnode\n")); 2198 if (d && d->running) { 2199 bdrv_t *bd = d->board->sys; 2200 int s = splimp (); 2201 CP_LOCK (bd); 2202 cp_down (d); 2203 CP_UNLOCK (bd); 2204 splx (s); 2205 } 2206#ifdef KLD_MODULE 2207 if (node->nd_flags & NGF_REALLY_DIE) { 2208 NG_NODE_SET_PRIVATE (node, NULL); 2209 NG_NODE_UNREF (node); 2210 } 2211 NG_NODE_REVIVE(node); /* Persistant node */ 2212#endif 2213 return 0; 2214} 2215 2216static void ng_cp_watchdog (void *arg) 2217{ 2218 drv_t *d = arg; 2219 2220 if (d) { 2221 if (d->timeout == 1) 2222 cp_watchdog (d); 2223 if (d->timeout) 2224 d->timeout--; 2225 callout_reset (&d->timeout_handle, hz, ng_cp_watchdog, d); 2226 } 2227} 2228 2229static int ng_cp_connect (hook_p hook) 2230{ 2231 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2232 2233 if (d) { 2234 CP_DEBUG (d, ("Connect\n")); 2235 callout_reset (&d->timeout_handle, hz, ng_cp_watchdog, d); 2236 } 2237 2238 return 0; 2239} 2240 2241static int ng_cp_disconnect (hook_p hook) 2242{ 2243 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2244 2245 if (d) { 2246 CP_DEBUG (d, ("Disconnect\n")); 2247 if (NG_HOOK_PRIVATE (hook)) 2248 { 2249 bdrv_t *bd = d->board->sys; 2250 int s = splimp (); 2251 CP_LOCK (bd); 2252 cp_down (d); 2253 CP_UNLOCK (bd); 2254 splx (s); 2255 } 2256 /* If we were wait it than it reasserted now, just stop it. */ 2257 if (!callout_drain (&d->timeout_handle)) 2258 callout_stop (&d->timeout_handle); 2259 } 2260 return 0; 2261} 2262#endif 2263 2264static int cp_modevent (module_t mod, int type, void *unused) 2265{ 2266 static int load_count = 0; 2267 2268 if (!debug_mpsafenet && cp_mpsafenet) { 2269 printf ("WORNING! Network stack is not MPSAFE. " 2270 "Turning off debug.cp.mpsafenet.\n"); 2271 cp_mpsafenet = 0; 2272 } 2273 if (cp_mpsafenet) 2274 cp_cdevsw.d_flags &= ~D_NEEDGIANT; 2275 2276 switch (type) { 2277 case MOD_LOAD: 2278#ifdef NETGRAPH 2279 if (ng_newtype (&typestruct)) 2280 printf ("Failed to register ng_cp\n"); 2281#endif 2282 ++load_count; 2283 callout_init (&timeout_handle, cp_mpsafenet?CALLOUT_MPSAFE:0); 2284 callout_reset (&timeout_handle, hz*5, cp_timeout, 0); 2285 break; 2286 case MOD_UNLOAD: 2287 if (load_count == 1) { 2288 printf ("Removing device entry for Tau-PCI\n"); 2289#ifdef NETGRAPH 2290 ng_rmtype (&typestruct); 2291#endif 2292 } 2293 /* If we were wait it than it reasserted now, just stop it. 2294 * Actually we shouldn't get this condition. But code could be 2295 * changed in the future, so just be a litle paranoid. 2296 */ 2297 if (!callout_drain (&timeout_handle)) 2298 callout_stop (&timeout_handle); 2299 --load_count; 2300 break; 2301 case MOD_SHUTDOWN: 2302 break; 2303 } 2304 return 0; 2305} 2306 2307#ifdef NETGRAPH 2308static struct ng_type typestruct = { 2309 .version = NG_ABI_VERSION, 2310 .name = NG_CP_NODE_TYPE, 2311 .constructor = ng_cp_constructor, 2312 .rcvmsg = ng_cp_rcvmsg, 2313 .shutdown = ng_cp_rmnode, 2314 .newhook = ng_cp_newhook, 2315 .connect = ng_cp_connect, 2316 .rcvdata = ng_cp_rcvdata, 2317 .disconnect = ng_cp_disconnect, 2318}; 2319#endif /*NETGRAPH*/ 2320 2321#ifdef NETGRAPH 2322MODULE_DEPEND (ng_cp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2323#else 2324MODULE_DEPEND (cp, sppp, 1, 1, 1); 2325#endif 2326DRIVER_MODULE (cp, pci, cp_driver, cp_devclass, cp_modevent, NULL); 2327MODULE_VERSION (cp, 1); 2328