27 28#include <sys/param.h> 29 30#include <sys/systm.h> 31#include <sys/kernel.h> 32#include <sys/module.h> 33#include <sys/priv.h> 34#include <sys/proc.h> 35#include <sys/mbuf.h> 36#include <sys/sockio.h> 37#include <sys/malloc.h> 38#include <sys/socket.h> 39#include <sys/sysctl.h> 40#include <sys/conf.h> 41#include <sys/errno.h> 42#include <sys/serial.h> 43#include <sys/tty.h> 44#include <sys/bus.h> 45#include <machine/bus.h> 46#include <sys/rman.h> 47#include <isa/isavar.h> 48#include <sys/fcntl.h> 49#include <sys/interrupt.h> 50#include <vm/vm.h> 51#include <vm/pmap.h> 52#include <net/if.h> 53#include <machine/cpufunc.h> 54#include <machine/cserial.h> 55#include <machine/resource.h> 56#include <dev/cx/machdep.h> 57#include <dev/cx/cxddk.h> 58#include <dev/cx/cronyxfw.h> 59#include "opt_ng_cronyx.h" 60#ifdef NETGRAPH_CRONYX 61# include "opt_netgraph.h" 62# include <netgraph/ng_message.h> 63# include <netgraph/netgraph.h> 64# include <dev/cx/ng_cx.h> 65#else 66# include <net/if_types.h> 67# include <net/if_sppp.h> 68# define PP_CISCO IFF_LINK2 69# include <net/bpf.h> 70#endif 71 72#define NCX 1 73 74/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 75#ifndef PP_FR 76#define PP_FR 0 77#endif 78 79#define CX_DEBUG(d,s) ({if (d->chan->debug) {\ 80 printf ("%s: ", d->name); printf s;}}) 81#define CX_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 82 printf ("%s: ", d->name); printf s;}}) 83 84#define CX_LOCK_NAME "cxX" 85 86#define CX_LOCK(_bd) mtx_lock (&(_bd)->cx_mtx) 87#define CX_UNLOCK(_bd) mtx_unlock (&(_bd)->cx_mtx) 88#define CX_LOCK_ASSERT(_bd) mtx_assert (&(_bd)->cx_mtx, MA_OWNED) 89 90typedef struct _async_q { 91 int beg; 92 int end; 93 #define BF_SZ 14400 94 int buf[BF_SZ+1]; 95} async_q; 96 97#define AQ_GSZ(q) ((BF_SZ + (q)->end - (q)->beg)%BF_SZ) 98#define AQ_PUSH(q,c) {*((q)->buf + (q)->end) = c;\ 99 (q)->end = ((q)->end + 1)%BF_SZ;} 100#define AQ_POP(q,c) {c = *((q)->buf + (q)->beg);\ 101 (q)->beg = ((q)->beg + 1)%BF_SZ;} 102 103static void cx_identify __P((driver_t *, device_t)); 104static int cx_probe __P((device_t)); 105static int cx_attach __P((device_t)); 106static int cx_detach __P((device_t)); 107static t_open_t cx_topen; 108static t_modem_t cx_tmodem; 109static t_close_t cx_tclose; 110 111static device_method_t cx_isa_methods [] = { 112 DEVMETHOD(device_identify, cx_identify), 113 DEVMETHOD(device_probe, cx_probe), 114 DEVMETHOD(device_attach, cx_attach), 115 DEVMETHOD(device_detach, cx_detach), 116 117 DEVMETHOD_END 118}; 119 120typedef struct _cx_dma_mem_t { 121 unsigned long phys; 122 void *virt; 123 size_t size; 124 bus_dma_tag_t dmat; 125 bus_dmamap_t mapp; 126} cx_dma_mem_t; 127 128typedef struct _drv_t { 129 char name [8]; 130 cx_chan_t *chan; 131 cx_board_t *board; 132 cx_dma_mem_t dmamem; 133 struct tty *tty; 134 struct callout dcd_timeout_handle; 135 unsigned callout; 136 unsigned lock; 137 int open_dev; 138 int cd; 139 int running; 140#ifdef NETGRAPH 141 char nodename [NG_NODESIZ]; 142 hook_p hook; 143 hook_p debug_hook; 144 node_p node; 145 struct ifqueue lo_queue; 146 struct ifqueue hi_queue; 147#else 148 struct ifqueue queue; 149 struct ifnet *ifp; 150#endif 151 short timeout; 152 struct callout timeout_handle; 153 struct cdev *devt; 154 async_q aqueue; 155#define CX_READ 1 156#define CX_WRITE 2 157 int intr_action; 158 short atimeout; 159} drv_t; 160 161typedef struct _bdrv_t { 162 cx_board_t *board; 163 struct resource *base_res; 164 struct resource *drq_res; 165 struct resource *irq_res; 166 int base_rid; 167 int drq_rid; 168 int irq_rid; 169 void *intrhand; 170 drv_t channel [NCHAN]; 171 struct mtx cx_mtx; 172} bdrv_t; 173 174static driver_t cx_isa_driver = { 175 "cx", 176 cx_isa_methods, 177 sizeof (bdrv_t), 178}; 179 180static devclass_t cx_devclass; 181 182extern long csigma_fw_len; 183extern const char *csigma_fw_version; 184extern const char *csigma_fw_date; 185extern const char *csigma_fw_copyright; 186extern const cr_dat_tst_t csigma_fw_tvec[]; 187extern const u_char csigma_fw_data[]; 188static void cx_oproc (struct tty *tp); 189static int cx_param (struct tty *tp, struct termios *t); 190static void cx_stop (struct tty *tp, int flag); 191static void cx_receive (cx_chan_t *c, char *data, int len); 192static void cx_transmit (cx_chan_t *c, void *attachment, int len); 193static void cx_error (cx_chan_t *c, int data); 194static void cx_modem (cx_chan_t *c); 195static void cx_up (drv_t *d); 196static void cx_start (drv_t *d); 197static void cx_softintr (void *); 198static void *cx_fast_ih; 199static void cx_down (drv_t *d); 200static void cx_watchdog (drv_t *d); 201static void cx_watchdog_timer (void *arg); 202static void cx_carrier (void *arg); 203 204#ifdef NETGRAPH 205extern struct ng_type typestruct; 206#else 207static void cx_ifstart (struct ifnet *ifp); 208static void cx_tlf (struct sppp *sp); 209static void cx_tls (struct sppp *sp); 210static int cx_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 211static void cx_initialize (void *softc); 212#endif 213 214static cx_board_t *adapter [NCX]; 215static drv_t *channel [NCX*NCHAN]; 216static struct callout led_timo [NCX]; 217static struct callout timeout_handle; 218 219static int cx_open (struct cdev *dev, int flag, int mode, struct thread *td); 220static int cx_close (struct cdev *dev, int flag, int mode, struct thread *td); 221static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td); 222static struct cdevsw cx_cdevsw = { 223 .d_version = D_VERSION, 224 .d_open = cx_open, 225 .d_close = cx_close, 226 .d_ioctl = cx_ioctl, 227 .d_name = "cx", 228 .d_flags = D_TTY, 229}; 230 231static int MY_SOFT_INTR; 232 233/* 234 * Print the mbuf chain, for debug purposes only. 235 */ 236static void printmbuf (struct mbuf *m) 237{ 238 printf ("mbuf:"); 239 for (; m; m=m->m_next) { 240 if (m->m_flags & M_PKTHDR) 241 printf (" HDR %d:", m->m_pkthdr.len); 242 if (m->m_flags & M_EXT) 243 printf (" EXT:"); 244 printf (" %d", m->m_len); 245 } 246 printf ("\n"); 247} 248 249/* 250 * Make an mbuf from data. 251 */ 252static struct mbuf *makembuf (void *buf, u_int len) 253{ 254 struct mbuf *m, *o, *p; 255 256 MGETHDR (m, M_NOWAIT, MT_DATA); 257 258 if (! m) 259 return 0; 260 261 if (len >= MINCLSIZE) 262 MCLGET (m, M_NOWAIT); 263 264 m->m_pkthdr.len = len; 265 m->m_len = 0; 266 267 p = m; 268 while (len) { 269 u_int n = M_TRAILINGSPACE (p); 270 if (n > len) 271 n = len; 272 if (! n) { 273 /* Allocate new mbuf. */ 274 o = p; 275 MGET (p, M_NOWAIT, MT_DATA); 276 if (! p) { 277 m_freem (m); 278 return 0; 279 } 280 if (len >= MINCLSIZE) 281 MCLGET (p, M_NOWAIT); 282 p->m_len = 0; 283 o->m_next = p; 284 285 n = M_TRAILINGSPACE (p); 286 if (n > len) 287 n = len; 288 } 289 bcopy (buf, mtod (p, caddr_t) + p->m_len, n); 290 291 p->m_len += n; 292 buf = n + (char*) buf; 293 len -= n; 294 } 295 return m; 296} 297 298/* 299 * Recover after lost transmit interrupts. 300 */ 301static void cx_timeout (void *arg) 302{ 303 drv_t *d; 304 int s, i, k; 305 306 for (i = 0; i < NCX; i++) { 307 if (adapter[i] == NULL) 308 continue; 309 for (k = 0; k < NCHAN; ++k) { 310 d = channel[i * NCHAN + k]; 311 if (! d) 312 continue; 313 s = splhigh (); 314 CX_LOCK ((bdrv_t *)d->board->sys); 315 if (d->atimeout == 1 && d->tty && d->tty->t_state & TS_BUSY) { 316 d->tty->t_state &= ~TS_BUSY; 317 if (d->tty->t_dev) { 318 d->intr_action |= CX_WRITE; 319 MY_SOFT_INTR = 1; 320 swi_sched (cx_fast_ih, 0); 321 } 322 CX_DEBUG (d, ("cx_timeout\n")); 323 } 324 if (d->atimeout) 325 d->atimeout--; 326 CX_UNLOCK ((bdrv_t *)d->board->sys); 327 splx (s); 328 } 329 } 330 callout_reset (&timeout_handle, hz*5, cx_timeout, 0); 331} 332 333static void cx_led_off (void *arg) 334{ 335 cx_board_t *b = arg; 336 bdrv_t *bd = b->sys; 337 int s; 338 339 s = splhigh (); 340 CX_LOCK (bd); 341 cx_led (b, 0); 342 CX_UNLOCK (bd); 343 splx (s); 344} 345 346/* 347 * Activate interrupt handler from DDK. 348 */ 349static void cx_intr (void *arg) 350{ 351 bdrv_t *bd = arg; 352 cx_board_t *b = bd->board; 353#ifndef NETGRAPH 354 int i; 355#endif 356 int s = splhigh (); 357 358 CX_LOCK (bd); 359 /* Turn LED on. */ 360 cx_led (b, 1); 361 362 cx_int_handler (b); 363 364 /* Turn LED off 50 msec later. */ 365 callout_reset (&led_timo[b->num], hz/20, cx_led_off, b); 366 CX_UNLOCK (bd); 367 splx (s); 368 369#ifndef NETGRAPH 370 /* Pass packets in a lock-free state */ 371 for (i = 0; i < NCHAN && b->chan[i].type; i++) { 372 drv_t *d = b->chan[i].sys; 373 struct mbuf *m; 374 if (!d || !d->running) 375 continue; 376 while (_IF_QLEN(&d->queue)) { 377 IF_DEQUEUE (&d->queue,m); 378 if (!m) 379 continue; 380 sppp_input (d->ifp, m); 381 } 382 } 383#endif 384} 385 386static int probe_irq (cx_board_t *b, int irq) 387{ 388 int mask, busy, cnt; 389 390 /* Clear pending irq, if any. */ 391 cx_probe_irq (b, -irq); 392 DELAY (100); 393 for (cnt=0; cnt<5; ++cnt) { 394 /* Get the mask of pending irqs, assuming they are busy. 395 * Activate the adapter on given irq. */ 396 busy = cx_probe_irq (b, irq); 397 DELAY (100); 398 399 /* Get the mask of active irqs. 400 * Deactivate our irq. */ 401 mask = cx_probe_irq (b, -irq); 402 DELAY (100); 403 if ((mask & ~busy) == 1 << irq) { 404 cx_probe_irq (b, 0); 405 /* printf ("cx%d: irq %d ok, mask=0x%04x, busy=0x%04x\n", 406 b->num, irq, mask, busy); */ 407 return 1; 408 } 409 } 410 /* printf ("cx%d: irq %d not functional, mask=0x%04x, busy=0x%04x\n", 411 b->num, irq, mask, busy); */ 412 cx_probe_irq (b, 0); 413 return 0; 414} 415 416static short porttab [] = { 417 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 418 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 419}; 420static char dmatab [] = { 7, 6, 5, 0 }; 421static char irqtab [] = { 5, 10, 11, 7, 3, 15, 12, 0 }; 422 423static int cx_is_free_res (device_t dev, int rid, int type, u_long start, 424 u_long end, u_long count) 425{ 426 struct resource *res; 427 428 if (!(res = bus_alloc_resource (dev, type, &rid, start, end, count, 429 RF_ALLOCATED))) 430 return 0; 431 432 bus_release_resource (dev, type, rid, res); 433 434 return 1; 435} 436 437static void cx_identify (driver_t *driver, device_t dev) 438{ 439 u_long iobase, rescount; 440 int devcount; 441 device_t *devices; 442 device_t child; 443 devclass_t my_devclass; 444 int i, k; 445 446 if ((my_devclass = devclass_find ("cx")) == NULL) 447 return; 448 449 devclass_get_devices (my_devclass, &devices, &devcount); 450 451 if (devcount == 0) { 452 /* We should find all devices by our self. We could alter other 453 * devices, but we don't have a choise 454 */ 455 for (i = 0; (iobase = porttab [i]) != 0; i++) { 456 if (!cx_is_free_res (dev, 0, SYS_RES_IOPORT, 457 iobase, iobase + NPORT, NPORT)) 458 continue; 459 if (cx_probe_board (iobase, -1, -1) == 0) 460 continue; 461 462 devcount++; 463 464 child = BUS_ADD_CHILD (dev, ISA_ORDER_SPECULATIVE, "cx", 465 -1); 466 467 if (child == NULL) 468 return; 469 470 device_set_desc_copy (child, "Cronyx Sigma"); 471 device_set_driver (child, driver); 472 bus_set_resource (child, SYS_RES_IOPORT, 0, 473 iobase, NPORT); 474 475 if (devcount >= NCX) 476 break; 477 } 478 } else { 479 static short porttab [] = { 480 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 481 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 482 }; 483 /* Lets check user choise. 484 */ 485 for (k = 0; k < devcount; k++) { 486 if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0, 487 &iobase, &rescount) != 0) 488 continue; 489 490 for (i = 0; porttab [i] != 0; i++) { 491 if (porttab [i] != iobase) 492 continue; 493 if (!cx_is_free_res (devices[k], 0, SYS_RES_IOPORT, 494 iobase, iobase + NPORT, NPORT)) 495 continue; 496 if (cx_probe_board (iobase, -1, -1) == 0) 497 continue; 498 porttab [i] = -1; 499 device_set_desc_copy (devices[k], "Cronyx Sigma"); 500 break; 501 } 502 503 if (porttab [i] == 0) { 504 device_delete_child ( 505 device_get_parent (devices[k]), 506 devices [k]); 507 devices[k] = 0; 508 continue; 509 } 510 } 511 for (k = 0; k < devcount; k++) { 512 if (devices[k] == 0) 513 continue; 514 if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0, 515 &iobase, &rescount) == 0) 516 continue; 517 for (i = 0; (iobase = porttab [i]) != 0; i++) { 518 if (porttab [i] == -1) { 519 continue; 520 } 521 if (!cx_is_free_res (devices[k], 0, SYS_RES_IOPORT, 522 iobase, iobase + NPORT, NPORT)) 523 continue; 524 if (cx_probe_board (iobase, -1, -1) == 0) 525 continue; 526 527 bus_set_resource (devices[k], SYS_RES_IOPORT, 0, 528 iobase, NPORT); 529 porttab [i] = -1; 530 device_set_desc_copy (devices[k], "Cronyx Sigma"); 531 break; 532 } 533 if (porttab [i] == 0) { 534 device_delete_child ( 535 device_get_parent (devices[k]), 536 devices [k]); 537 } 538 } 539 free (devices, M_TEMP); 540 } 541 542 return; 543} 544 545static int cx_probe (device_t dev) 546{ 547 int unit = device_get_unit (dev); 548 int i; 549 u_long iobase, rescount; 550 551 if (!device_get_desc (dev) || 552 strcmp (device_get_desc (dev), "Cronyx Sigma")) 553 return ENXIO; 554 555 if (bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount) != 0) { 556 printf ("cx%d: Couldn't get IOPORT\n", unit); 557 return ENXIO; 558 } 559 560 if (!cx_is_free_res (dev, 0, SYS_RES_IOPORT, 561 iobase, iobase + NPORT, NPORT)) { 562 printf ("cx%d: Resource IOPORT isn't free %lx\n", unit, iobase); 563 return ENXIO; 564 } 565 566 for (i = 0; porttab [i] != 0; i++) { 567 if (porttab [i] == iobase) { 568 porttab [i] = -1; 569 break; 570 } 571 } 572 573 if (porttab [i] == 0) { 574 return ENXIO; 575 } 576 577 if (!cx_probe_board (iobase, -1, -1)) { 578 printf ("cx%d: probing for Sigma at %lx faild\n", unit, iobase); 579 return ENXIO; 580 } 581 582 return 0; 583} 584 585static void 586cx_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) 587{ 588 unsigned long *addr; 589 590 if (error) 591 return; 592 593 KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 594 addr = arg; 595 *addr = segs->ds_addr; 596} 597 598static int 599cx_bus_dma_mem_alloc (int bnum, int cnum, cx_dma_mem_t *dmem) 600{ 601 int error; 602 603 error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_24BIT, 604 BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, 605 dmem->size, 0, NULL, NULL, &dmem->dmat); 606 if (error) { 607 if (cnum >= 0) printf ("cx%d-%d: ", bnum, cnum); 608 else printf ("cx%d: ", bnum); 609 printf ("couldn't allocate tag for dma memory\n"); 610 return 0; 611 } 612 error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, 613 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); 614 if (error) { 615 if (cnum >= 0) printf ("cx%d-%d: ", bnum, cnum); 616 else printf ("cx%d: ", bnum); 617 printf ("couldn't allocate mem for dma memory\n"); 618 bus_dma_tag_destroy (dmem->dmat); 619 return 0; 620 } 621 error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, 622 dmem->size, cx_bus_dmamap_addr, &dmem->phys, 0); 623 if (error) { 624 if (cnum >= 0) printf ("cx%d-%d: ", bnum, cnum); 625 else printf ("cx%d: ", bnum); 626 printf ("couldn't load mem map for dma memory\n"); 627 bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 628 bus_dma_tag_destroy (dmem->dmat); 629 return 0; 630 } 631 return 1; 632} 633 634static void 635cx_bus_dma_mem_free (cx_dma_mem_t *dmem) 636{ 637 bus_dmamap_unload (dmem->dmat, dmem->mapp); 638 bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); 639 bus_dma_tag_destroy (dmem->dmat); 640} 641 642/* 643 * The adapter is present, initialize the driver structures. 644 */ 645static int cx_attach (device_t dev) 646{ 647 bdrv_t *bd = device_get_softc (dev); 648 u_long iobase, drq, irq, rescount; 649 int unit = device_get_unit (dev); 650 char *cx_ln = CX_LOCK_NAME; 651 cx_board_t *b; 652 cx_chan_t *c; 653 drv_t *d; 654 int i; 655 int s; 656 657 KASSERT ((bd != NULL), ("cx%d: NULL device softc\n", unit)); 658 659 bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount); 660 bd->base_rid = 0; 661 bd->base_res = bus_alloc_resource (dev, SYS_RES_IOPORT, &bd->base_rid, 662 iobase, iobase + NPORT, NPORT, RF_ACTIVE); 663 if (! bd->base_res) { 664 printf ("cx%d: cannot allocate base address\n", unit); 665 return ENXIO; 666 } 667 668 if (bus_get_resource (dev, SYS_RES_DRQ, 0, &drq, &rescount) != 0) { 669 for (i = 0; (drq = dmatab [i]) != 0; i++) { 670 if (!cx_is_free_res (dev, 0, SYS_RES_DRQ, 671 drq, drq + 1, 1)) 672 continue; 673 bus_set_resource (dev, SYS_RES_DRQ, 0, drq, 1); 674 break; 675 } 676 677 if (dmatab[i] == 0) { 678 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 679 bd->base_res); 680 printf ("cx%d: Couldn't get DRQ\n", unit); 681 return ENXIO; 682 } 683 } 684 685 bd->drq_rid = 0; 686 bd->drq_res = bus_alloc_resource (dev, SYS_RES_DRQ, &bd->drq_rid, 687 drq, drq + 1, 1, RF_ACTIVE); 688 if (! bd->drq_res) { 689 printf ("cx%d: cannot allocate drq\n", unit); 690 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 691 bd->base_res); 692 return ENXIO; 693 } 694 695 if (bus_get_resource (dev, SYS_RES_IRQ, 0, &irq, &rescount) != 0) { 696 for (i = 0; (irq = irqtab [i]) != 0; i++) { 697 if (!cx_is_free_res (dev, 0, SYS_RES_IRQ, 698 irq, irq + 1, 1)) 699 continue; 700 bus_set_resource (dev, SYS_RES_IRQ, 0, irq, 1); 701 break; 702 } 703 704 if (irqtab[i] == 0) { 705 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 706 bd->drq_res); 707 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 708 bd->base_res); 709 printf ("cx%d: Couldn't get IRQ\n", unit); 710 return ENXIO; 711 } 712 } 713 714 bd->irq_rid = 0; 715 bd->irq_res = bus_alloc_resource (dev, SYS_RES_IRQ, &bd->irq_rid, 716 irq, irq + 1, 1, RF_ACTIVE); 717 if (! bd->irq_res) { 718 printf ("cx%d: Couldn't allocate irq\n", unit); 719 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 720 bd->drq_res); 721 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 722 bd->base_res); 723 return ENXIO; 724 } 725 726 b = malloc (sizeof (cx_board_t), M_DEVBUF, M_WAITOK); 727 if (!b) { 728 printf ("cx:%d: Couldn't allocate memory\n", unit); 729 return (ENXIO); 730 } 731 adapter[unit] = b; 732 bzero (b, sizeof(cx_board_t)); 733 734 if (! cx_open_board (b, unit, iobase, irq, drq)) { 735 printf ("cx%d: error loading firmware\n", unit); 736 free (b, M_DEVBUF); 737 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 738 bd->irq_res); 739 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 740 bd->drq_res); 741 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 742 bd->base_res); 743 return ENXIO; 744 } 745 746 bd->board = b; 747 748 cx_ln[2] = '0' + unit; 749 mtx_init (&bd->cx_mtx, cx_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); 750 if (! probe_irq (b, irq)) { 751 printf ("cx%d: irq %ld not functional\n", unit, irq); 752 bd->board = 0; 753 adapter [unit] = 0; 754 mtx_destroy (&bd->cx_mtx); 755 free (b, M_DEVBUF); 756 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 757 bd->irq_res); 758 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 759 bd->drq_res); 760 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 761 bd->base_res); 762 return ENXIO; 763 } 764 b->sys = bd; 765 callout_init (&led_timo[b->num], CALLOUT_MPSAFE); 766 s = splhigh (); 767 if (bus_setup_intr (dev, bd->irq_res, 768 INTR_TYPE_NET|INTR_MPSAFE, 769 NULL, cx_intr, bd, &bd->intrhand)) { 770 printf ("cx%d: Can't setup irq %ld\n", unit, irq); 771 bd->board = 0; 772 b->sys = 0; 773 adapter [unit] = 0; 774 mtx_destroy (&bd->cx_mtx); 775 free (b, M_DEVBUF); 776 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 777 bd->irq_res); 778 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 779 bd->drq_res); 780 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 781 bd->base_res); 782 splx (s); 783 return ENXIO; 784 } 785 786 CX_LOCK (bd); 787 cx_init (b, b->num, b->port, irq, drq); 788 cx_setup_board (b, 0, 0, 0); 789 CX_UNLOCK (bd); 790 791 printf ("cx%d: <Cronyx-Sigma-%s>\n", b->num, b->name); 792 793 for (c=b->chan; c<b->chan+NCHAN; ++c) { 794 if (c->type == T_NONE) 795 continue; 796 d = &bd->channel[c->num]; 797 d->dmamem.size = sizeof(cx_buf_t); 798 if (! cx_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) 799 continue; 800 d->board = b; 801 d->chan = c; 802 d->open_dev = 0; 803 c->sys = d; 804 channel [b->num*NCHAN + c->num] = d; 805 sprintf (d->name, "cx%d.%d", b->num, c->num); 806 807 switch (c->type) { 808 case T_SYNC_RS232: 809 case T_SYNC_V35: 810 case T_SYNC_RS449: 811 case T_UNIV: 812 case T_UNIV_RS232: 813 case T_UNIV_RS449: 814 case T_UNIV_V35: 815 callout_init (&d->timeout_handle, CALLOUT_MPSAFE); 816#ifdef NETGRAPH 817 if (ng_make_node_common (&typestruct, &d->node) != 0) { 818 printf ("%s: cannot make common node\n", d->name); 819 channel [b->num*NCHAN + c->num] = 0; 820 c->sys = 0; 821 cx_bus_dma_mem_free (&d->dmamem); 822 continue; 823 } 824 NG_NODE_SET_PRIVATE (d->node, d); 825 sprintf (d->nodename, "%s%d", NG_CX_NODE_TYPE, 826 c->board->num*NCHAN + c->num); 827 if (ng_name_node (d->node, d->nodename)) { 828 printf ("%s: cannot name node\n", d->nodename); 829 NG_NODE_UNREF (d->node); 830 channel [b->num*NCHAN + c->num] = 0; 831 c->sys = 0; 832 cx_bus_dma_mem_free (&d->dmamem); 833 continue; 834 } 835 d->lo_queue.ifq_maxlen = ifqmaxlen; 836 d->hi_queue.ifq_maxlen = ifqmaxlen; 837 mtx_init (&d->lo_queue.ifq_mtx, "cx_queue_lo", NULL, MTX_DEF); 838 mtx_init (&d->hi_queue.ifq_mtx, "cx_queue_hi", NULL, MTX_DEF); 839#else /*NETGRAPH*/ 840 d->ifp = if_alloc(IFT_PPP); 841 if (d->ifp == NULL) { 842 printf ("%s: cannot if_alloc() common interface\n", 843 d->name); 844 channel [b->num*NCHAN + c->num] = 0; 845 c->sys = 0; 846 cx_bus_dma_mem_free (&d->dmamem); 847 continue; 848 } 849 d->ifp->if_softc = d; 850 if_initname (d->ifp, "cx", b->num * NCHAN + c->num); 851 d->ifp->if_mtu = PP_MTU; 852 d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 853 d->ifp->if_ioctl = cx_sioctl; 854 d->ifp->if_start = cx_ifstart; 855 d->ifp->if_init = cx_initialize; 856 d->queue.ifq_maxlen = 2; 857 mtx_init (&d->queue.ifq_mtx, "cx_queue", NULL, MTX_DEF); 858 sppp_attach (d->ifp); 859 if_attach (d->ifp); 860 IFP2SP(d->ifp)->pp_tlf = cx_tlf; 861 IFP2SP(d->ifp)->pp_tls = cx_tls; 862 /* If BPF is in the kernel, call the attach for it. 863 * Size of PPP header is 4 bytes. */ 864 bpfattach (d->ifp, DLT_PPP, 4); 865#endif /*NETGRAPH*/ 866 } 867 d->tty = ttyalloc (); 868 d->tty->t_open = cx_topen; 869 d->tty->t_close = cx_tclose; 870 d->tty->t_param = cx_param; 871 d->tty->t_stop = cx_stop; 872 d->tty->t_modem = cx_tmodem; 873 d->tty->t_oproc = cx_oproc; 874 d->tty->t_sc = d; 875 CX_LOCK (bd); 876 cx_start_chan (c, d->dmamem.virt, d->dmamem.phys); 877 cx_register_receive (c, &cx_receive); 878 cx_register_transmit (c, &cx_transmit); 879 cx_register_error (c, &cx_error); 880 cx_register_modem (c, &cx_modem); 881 CX_UNLOCK (bd); 882 883 ttycreate(d->tty, TS_CALLOUT, "x%r%r", b->num, c->num); 884 d->devt = make_dev (&cx_cdevsw, b->num*NCHAN + c->num + 64, UID_ROOT, GID_WHEEL, 0600, "cx%d", b->num*NCHAN + c->num); 885 d->devt->si_drv1 = d; 886 callout_init (&d->dcd_timeout_handle, CALLOUT_MPSAFE); 887 } 888 splx (s); 889 890 return 0; 891} 892 893static int cx_detach (device_t dev) 894{ 895 bdrv_t *bd = device_get_softc (dev); 896 cx_board_t *b = bd->board; 897 cx_chan_t *c; 898 int s; 899 900 KASSERT (mtx_initialized (&bd->cx_mtx), ("cx mutex not initialized")); 901 902 s = splhigh (); 903 CX_LOCK (bd); 904 /* Check if the device is busy (open). */ 905 for (c = b->chan; c < b->chan + NCHAN; ++c) { 906 drv_t *d = (drv_t*) c->sys; 907 908 if (!d || d->chan->type == T_NONE) 909 continue; 910 if (d->lock) { 911 CX_UNLOCK (bd); 912 splx (s); 913 return EBUSY; 914 } 915 if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) && 916 (d->open_dev|0x2)) { 917 CX_UNLOCK (bd); 918 splx (s); 919 return EBUSY; 920 } 921 if (d->running) { 922 CX_UNLOCK (bd); 923 splx (s); 924 return EBUSY; 925 } 926 } 927 928 /* Deactivate the timeout routine. And soft interrupt*/ 929 callout_stop (&led_timo[b->num]); 930 931 for (c = b->chan; c < b->chan + NCHAN; ++c) { 932 drv_t *d = c->sys; 933 934 if (!d || d->chan->type == T_NONE) 935 continue; 936 937 callout_stop (&d->dcd_timeout_handle); 938 } 939 CX_UNLOCK (bd); 940 bus_teardown_intr (dev, bd->irq_res, bd->intrhand); 941 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, bd->irq_res); 942 943 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, bd->drq_res); 944 945 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, bd->base_res); 946 947 CX_LOCK (bd); 948 cx_close_board (b); 949 950 /* Detach the interfaces, free buffer memory. */ 951 for (c = b->chan; c < b->chan + NCHAN; ++c) { 952 drv_t *d = (drv_t*) c->sys; 953 954 if (!d || d->chan->type == T_NONE) 955 continue; 956 957 if (d->tty) { 958 ttyfree (d->tty); 959 d->tty = NULL; 960 } 961 962 callout_stop (&d->timeout_handle); 963#ifdef NETGRAPH 964 if (d->node) { 965 ng_rmnode_self (d->node); 966 NG_NODE_UNREF (d->node); 967 d->node = NULL; 968 } 969 mtx_destroy (&d->lo_queue.ifq_mtx); 970 mtx_destroy (&d->hi_queue.ifq_mtx); 971#else 972 /* Detach from the packet filter list of interfaces. */ 973 bpfdetach (d->ifp); 974 /* Detach from the sync PPP list. */ 975 sppp_detach (d->ifp); 976 977 if_detach (d->ifp); 978 if_free(d->ifp); 979 /* XXXRIK: check interconnection with irq handler */ 980 IF_DRAIN (&d->queue); 981 mtx_destroy (&d->queue.ifq_mtx); 982#endif 983 destroy_dev (d->devt); 984 } 985 986 cx_led_off (b); 987 CX_UNLOCK (bd); 988 callout_drain (&led_timo[b->num]); 989 for (c = b->chan; c < b->chan + NCHAN; ++c) { 990 drv_t *d = c->sys; 991 992 if (!d || d->chan->type == T_NONE) 993 continue; 994 995 callout_drain (&d->dcd_timeout_handle); 996 callout_drain (&d->timeout_handle); 997 } 998 splx (s); 999 1000 s = splhigh (); 1001 for (c = b->chan; c < b->chan + NCHAN; ++c) { 1002 drv_t *d = (drv_t*) c->sys; 1003 1004 if (!d || d->chan->type == T_NONE) 1005 continue; 1006 1007 /* Deallocate buffers. */ 1008 cx_bus_dma_mem_free (&d->dmamem); 1009 } 1010 bd->board = 0; 1011 adapter [b->num] = 0; 1012 free (b, M_DEVBUF); 1013 splx (s); 1014 1015 mtx_destroy (&bd->cx_mtx); 1016 1017 return 0; 1018} 1019 1020#ifndef NETGRAPH 1021static void cx_ifstart (struct ifnet *ifp) 1022{ 1023 drv_t *d = ifp->if_softc; 1024 bdrv_t *bd = d->board->sys; 1025 1026 CX_LOCK (bd); 1027 cx_start (d); 1028 CX_UNLOCK (bd); 1029} 1030 1031static void cx_tlf (struct sppp *sp) 1032{ 1033 drv_t *d = SP2IFP(sp)->if_softc; 1034 1035 CX_DEBUG (d, ("cx_tlf\n")); 1036/* cx_set_dtr (d->chan, 0);*/ 1037/* cx_set_rts (d->chan, 0);*/ 1038 if (!(IFP2SP(d->ifp)->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 1039 sp->pp_down (sp); 1040} 1041 1042static void cx_tls (struct sppp *sp) 1043{ 1044 drv_t *d = SP2IFP(sp)->if_softc; 1045 1046 CX_DEBUG (d, ("cx_tls\n")); 1047 if (!(IFP2SP(d->ifp)->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) 1048 sp->pp_up (sp); 1049} 1050 1051/* 1052 * Initialization of interface. 1053 * It seems to be never called by upper level. 1054 */ 1055static void cx_initialize (void *softc) 1056{ 1057 drv_t *d = softc; 1058 1059 CX_DEBUG (d, ("cx_initialize\n")); 1060} 1061 1062/* 1063 * Process an ioctl request. 1064 */ 1065static int cx_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 1066{ 1067 drv_t *d = ifp->if_softc; 1068 bdrv_t *bd = d->board->sys; 1069 int error, s, was_up, should_be_up; 1070 1071 /* No socket ioctls while the channel is in async mode. */ 1072 if (d->chan->type == T_NONE || d->chan->mode == M_ASYNC) 1073 return EBUSY; 1074 1075 /* Socket ioctls on slave subchannels are not allowed. */ 1076 was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 1077 error = sppp_ioctl (ifp, cmd, data); 1078 if (error) 1079 return error; 1080 1081 s = splhigh (); 1082 CX_LOCK (bd); 1083 if (! (ifp->if_flags & IFF_DEBUG)) 1084 d->chan->debug = 0; 1085 else 1086 d->chan->debug = d->chan->debug_shadow; 1087 CX_UNLOCK (bd); 1088 splx (s); 1089 1090 switch (cmd) { 1091 default: CX_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 1092 case SIOCADDMULTI: CX_DEBUG2 (d, ("SIOCADDMULTI\n")); return 0; 1093 case SIOCDELMULTI: CX_DEBUG2 (d, ("SIOCDELMULTI\n")); return 0; 1094 case SIOCSIFFLAGS: CX_DEBUG2 (d, ("SIOCSIFFLAGS\n")); break; 1095 case SIOCSIFADDR: CX_DEBUG2 (d, ("SIOCSIFADDR\n")); break; 1096 } 1097 1098 /* We get here only in case of SIFFLAGS or SIFADDR. */ 1099 s = splhigh (); 1100 CX_LOCK (bd); 1101 should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; 1102 if (!was_up && should_be_up) { 1103 /* Interface goes up -- start it. */ 1104 cx_up (d); 1105 cx_start (d); 1106 } else if (was_up && !should_be_up) { 1107 /* Interface is going down -- stop it. */ 1108 /* if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 1109 cx_down (d); 1110 } 1111 CX_UNLOCK (bd); 1112 splx (s); 1113 return 0; 1114} 1115#endif /*NETGRAPH*/ 1116 1117/* 1118 * Stop the interface. Called on splimp(). 1119 */ 1120static void cx_down (drv_t *d) 1121{ 1122 int s = splhigh (); 1123 CX_DEBUG (d, ("cx_down\n")); 1124 cx_set_dtr (d->chan, 0); 1125 cx_set_rts (d->chan, 0); 1126 d->running = 0; 1127 callout_stop (&d->timeout_handle); 1128 splx (s); 1129} 1130 1131/* 1132 * Start the interface. Called on splimp(). 1133 */ 1134static void cx_up (drv_t *d) 1135{ 1136 int s = splhigh (); 1137 CX_DEBUG (d, ("cx_up\n")); 1138 cx_set_dtr (d->chan, 1); 1139 cx_set_rts (d->chan, 1); 1140 d->running = 1; 1141 splx (s); 1142} 1143 1144/* 1145 * Start output on the (slave) interface. Get another datagram to send 1146 * off of the interface queue, and copy it to the interface 1147 * before starting the output. 1148 */ 1149static void cx_send (drv_t *d) 1150{ 1151 struct mbuf *m; 1152 u_short len; 1153 1154 CX_DEBUG2 (d, ("cx_send\n")); 1155 1156 /* No output if the interface is down. */ 1157 if (! d->running) 1158 return; 1159 1160 /* No output if the modem is off. */ 1161 if (! cx_get_dsr (d->chan) && ! cx_get_loop(d->chan)) 1162 return; 1163 1164 if (cx_buf_free (d->chan)) { 1165 /* Get the packet to send. */ 1166#ifdef NETGRAPH 1167 IF_DEQUEUE (&d->hi_queue, m); 1168 if (! m) 1169 IF_DEQUEUE (&d->lo_queue, m); 1170#else 1171 m = sppp_dequeue (d->ifp); 1172#endif 1173 if (! m) 1174 return; 1175#ifndef NETGRAPH 1176 BPF_MTAP (d->ifp, m); 1177#endif 1178 len = m_length (m, NULL); 1179 if (! m->m_next) 1180 cx_send_packet (d->chan, (u_char*)mtod (m, caddr_t), 1181 len, 0); 1182 else { 1183 u_char buf [DMABUFSZ]; 1184 m_copydata (m, 0, len, buf); 1185 cx_send_packet (d->chan, buf, len, 0); 1186 } 1187 m_freem (m); 1188 1189 /* Set up transmit timeout, 10 seconds. */ 1190 d->timeout = 10; 1191 } 1192#ifndef NETGRAPH 1193 d->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1194#endif 1195} 1196 1197/* 1198 * Start output on the interface. 1199 * Always called on splimp(). 1200 */ 1201static void cx_start (drv_t *d) 1202{ 1203 int s = splhigh (); 1204 if (d->running) { 1205 if (! d->chan->dtr) 1206 cx_set_dtr (d->chan, 1); 1207 if (! d->chan->rts) 1208 cx_set_rts (d->chan, 1); 1209 cx_send (d); 1210 callout_reset (&d->timeout_handle, hz, cx_watchdog_timer, d); 1211 } 1212 splx (s); 1213} 1214 1215/* 1216 * Handle transmit timeouts. 1217 * Recover after lost transmit interrupts. 1218 * Always called on splimp(). 1219 */ 1220static void cx_watchdog (drv_t *d) 1221{ 1222 1223 CX_DEBUG (d, ("device timeout\n")); 1224 if (d->running) { 1225 cx_setup_chan (d->chan); 1226 cx_start_chan (d->chan, 0, 0); 1227 cx_set_dtr (d->chan, 1); 1228 cx_set_rts (d->chan, 1); 1229 cx_start (d); 1230 } 1231} 1232 1233static void cx_watchdog_timer (void *arg) 1234{ 1235 drv_t *d = arg; 1236 bdrv_t *bd = d->board->sys; 1237 1238 CX_LOCK (bd); 1239 if (d->timeout == 1) 1240 cx_watchdog (d); 1241 if (d->timeout) 1242 d->timeout--; 1243 callout_reset (&d->timeout_handle, hz, cx_watchdog_timer, d); 1244 CX_UNLOCK (bd); 1245} 1246 1247/* 1248 * Transmit callback function. 1249 */ 1250static void cx_transmit (cx_chan_t *c, void *attachment, int len) 1251{ 1252 drv_t *d = c->sys; 1253 1254 if (!d) 1255 return; 1256 1257 if (c->mode == M_ASYNC && d->tty) { 1258 d->tty->t_state &= ~(TS_BUSY | TS_FLUSH); 1259 d->atimeout = 0; 1260 if (d->tty->t_dev) { 1261 d->intr_action |= CX_WRITE; 1262 MY_SOFT_INTR = 1; 1263 swi_sched (cx_fast_ih, 0); 1264 } 1265 return; 1266 } 1267 d->timeout = 0; 1268#ifndef NETGRAPH 1269 ++d->ifp->if_opackets; 1270 d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1271#endif 1272 cx_start (d); 1273} 1274 1275/* 1276 * Process the received packet. 1277 */ 1278static void cx_receive (cx_chan_t *c, char *data, int len) 1279{ 1280 drv_t *d = c->sys; 1281 struct mbuf *m; 1282 char *cc = data; 1283#ifdef NETGRAPH 1284 int error; 1285#endif 1286 1287 if (!d) 1288 return; 1289 1290 if (c->mode == M_ASYNC && d->tty) { 1291 if (d->tty->t_state & TS_ISOPEN) { 1292 async_q *q = &d->aqueue; 1293 int size = BF_SZ - 1 - AQ_GSZ (q); 1294 1295 if (len <= 0 && !size) 1296 return; 1297 1298 if (len > size) { 1299 c->ierrs++; 1300 cx_error (c, CX_OVERRUN); 1301 len = size - 1; 1302 } 1303 1304 while (len--) { 1305 AQ_PUSH (q, *(unsigned char *)cc); 1306 cc++; 1307 } 1308 1309 d->intr_action |= CX_READ; 1310 MY_SOFT_INTR = 1; 1311 swi_sched (cx_fast_ih, 0); 1312 } 1313 return; 1314 } 1315 if (! d->running) 1316 return; 1317 1318 m = makembuf (data, len); 1319 if (! m) { 1320 CX_DEBUG (d, ("no memory for packet\n")); 1321#ifndef NETGRAPH 1322 ++d->ifp->if_iqdrops; 1323#endif 1324 return; 1325 } 1326 if (c->debug > 1) 1327 printmbuf (m); 1328#ifdef NETGRAPH 1329 m->m_pkthdr.rcvif = 0; 1330 NG_SEND_DATA_ONLY (error, d->hook, m); 1331#else 1332 ++d->ifp->if_ipackets; 1333 m->m_pkthdr.rcvif = d->ifp; 1334 /* Check if there's a BPF listener on this interface. 1335 * If so, hand off the raw packet to bpf. */ 1336 BPF_TAP (d->ifp, data, len); 1337 IF_ENQUEUE (&d->queue, m); 1338#endif 1339} 1340 1341#define CONDITION(t,tp) (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))\ 1342 && (!(tp->t_iflag & BRKINT) || (tp->t_iflag & IGNBRK))\ 1343 && (!(tp->t_iflag & PARMRK)\ 1344 || (tp->t_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))\ 1345 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))\ 1346 && linesw[tp->t_line]->l_rint == ttyinput) 1347 1348/* 1349 * Error callback function. 1350 */ 1351static void cx_error (cx_chan_t *c, int data) 1352{ 1353 drv_t *d = c->sys; 1354 async_q *q; 1355 1356 if (!d) 1357 return; 1358 1359 q = &(d->aqueue); 1360 1361 switch (data) { 1362 case CX_FRAME: 1363 CX_DEBUG (d, ("frame error\n")); 1364 if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) 1365 && (AQ_GSZ (q) < BF_SZ - 1) 1366 && (!CONDITION((&d->tty->t_termios), (d->tty)) 1367 || !(d->tty->t_iflag & (IGNPAR | PARMRK)))) { 1368 AQ_PUSH (q, TTY_FE); 1369 d->intr_action |= CX_READ; 1370 MY_SOFT_INTR = 1; 1371 swi_sched (cx_fast_ih, 0); 1372 } 1373#ifndef NETGRAPH 1374 else 1375 ++d->ifp->if_ierrors; 1376#endif 1377 break; 1378 case CX_CRC: 1379 CX_DEBUG (d, ("crc error\n")); 1380 if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) 1381 && (AQ_GSZ (q) < BF_SZ - 1) 1382 && (!CONDITION((&d->tty->t_termios), (d->tty)) 1383 || !(d->tty->t_iflag & INPCK) 1384 || !(d->tty->t_iflag & (IGNPAR | PARMRK)))) { 1385 AQ_PUSH (q, TTY_PE); 1386 d->intr_action |= CX_READ; 1387 MY_SOFT_INTR = 1; 1388 swi_sched (cx_fast_ih, 0); 1389 } 1390#ifndef NETGRAPH 1391 else 1392 ++d->ifp->if_ierrors; 1393#endif 1394 break; 1395 case CX_OVERRUN: 1396 CX_DEBUG (d, ("overrun error\n")); 1397#ifdef TTY_OE 1398 if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) 1399 && (AQ_GSZ (q) < BF_SZ - 1) 1400 && (!CONDITION((&d->tty->t_termios), (d->tty)))) { 1401 AQ_PUSH (q, TTY_OE); 1402 d->intr_action |= CX_READ; 1403 MY_SOFT_INTR = 1; 1404 swi_sched (cx_fast_ih, 0); 1405 } 1406#endif 1407#ifndef NETGRAPH 1408 else { 1409 ++d->ifp->if_collisions; 1410 ++d->ifp->if_ierrors; 1411 } 1412#endif 1413 break; 1414 case CX_OVERFLOW: 1415 CX_DEBUG (d, ("overflow error\n")); 1416#ifndef NETGRAPH 1417 if (c->mode != M_ASYNC) 1418 ++d->ifp->if_ierrors; 1419#endif 1420 break; 1421 case CX_UNDERRUN: 1422 CX_DEBUG (d, ("underrun error\n")); 1423 if (c->mode != M_ASYNC) { 1424 d->timeout = 0; 1425#ifndef NETGRAPH 1426 ++d->ifp->if_oerrors; 1427 d->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1428#endif 1429 cx_start (d); 1430 } 1431 break; 1432 case CX_BREAK: 1433 CX_DEBUG (d, ("break error\n")); 1434 if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) 1435 && (AQ_GSZ (q) < BF_SZ - 1) 1436 && (!CONDITION((&d->tty->t_termios), (d->tty)) 1437 || !(d->tty->t_iflag & (IGNBRK | BRKINT | PARMRK)))) { 1438 AQ_PUSH (q, TTY_BI); 1439 d->intr_action |= CX_READ; 1440 MY_SOFT_INTR = 1; 1441 swi_sched (cx_fast_ih, 0); 1442 } 1443#ifndef NETGRAPH 1444 else 1445 ++d->ifp->if_ierrors; 1446#endif 1447 break; 1448 default: 1449 CX_DEBUG (d, ("error #%d\n", data)); 1450 } 1451} 1452 1453static int cx_topen (struct tty *tp, struct cdev *dev) 1454{ 1455 bdrv_t *bd; 1456 drv_t *d; 1457 1458 d = tp->t_sc; 1459 CX_DEBUG2 (d, ("cx_open (serial)\n")); 1460 1461 bd = d->board->sys; 1462 1463 if (d->chan->mode != M_ASYNC) 1464 return (EBUSY); 1465 1466 d->open_dev |= 0x2; 1467 CX_LOCK (bd); 1468 cx_start_chan (d->chan, 0, 0); 1469 cx_set_dtr (d->chan, 1); 1470 cx_set_rts (d->chan, 1); 1471 d->cd = cx_get_cd (d->chan); 1472 CX_UNLOCK (bd); 1473 1474 CX_DEBUG2 (d, ("cx_open done\n")); 1475 1476 return 0; 1477} 1478 1479static void cx_tclose (struct tty *tp) 1480{ 1481 drv_t *d; 1482 bdrv_t *bd; 1483 1484 d = tp->t_sc; 1485 CX_DEBUG2 (d, ("cx_close\n")); 1486 bd = d->board->sys; 1487 CX_LOCK (bd); 1488 /* Disable receiver. 1489 * Transmitter continues sending the queued data. */ 1490 cx_enable_receive (d->chan, 0); 1491 CX_UNLOCK (bd); 1492 d->open_dev &= ~0x2; 1493} 1494 1495static int cx_tmodem (struct tty *tp, int sigon, int sigoff) 1496{ 1497 drv_t *d; 1498 bdrv_t *bd; 1499 1500 d = tp->t_sc; 1501 bd = d->board->sys; 1502 1503 CX_LOCK (bd); 1504 if (!sigon && !sigoff) { 1505 if (cx_get_dsr (d->chan)) sigon |= SER_DSR; 1506 if (cx_get_cd (d->chan)) sigon |= SER_DCD; 1507 if (cx_get_cts (d->chan)) sigon |= SER_CTS; 1508 if (d->chan->dtr) sigon |= SER_DTR; 1509 if (d->chan->rts) sigon |= SER_RTS; 1510 CX_UNLOCK (bd); 1511 return sigon; 1512 } 1513 1514 if (sigon & SER_DTR) 1515 cx_set_dtr (d->chan, 1); 1516 if (sigoff & SER_DTR) 1517 cx_set_dtr (d->chan, 0); 1518 if (sigon & SER_RTS) 1519 cx_set_rts (d->chan, 1); 1520 if (sigoff & SER_RTS) 1521 cx_set_rts (d->chan, 0); 1522 CX_UNLOCK (bd); 1523 1524 return (0); 1525} 1526 1527static int cx_open (struct cdev *dev, int flag, int mode, struct thread *td) 1528{ 1529 int unit; 1530 drv_t *d; 1531 1532 d = dev->si_drv1; 1533 unit = d->chan->num; 1534 1535 CX_DEBUG2 (d, ("cx_open unit=%d, flag=0x%x, mode=0x%x\n", 1536 unit, flag, mode)); 1537 1538 d->open_dev |= 0x1; 1539 1540 CX_DEBUG2 (d, ("cx_open done\n")); 1541 1542 return 0; 1543} 1544 1545static int cx_close (struct cdev *dev, int flag, int mode, struct thread *td) 1546{ 1547 drv_t *d; 1548 1549 d = dev->si_drv1; 1550 CX_DEBUG2 (d, ("cx_close\n")); 1551 d->open_dev &= ~0x1; 1552 return 0; 1553} 1554 1555static int cx_modem_status (drv_t *d) 1556{ 1557 bdrv_t *bd = d->board->sys; 1558 int status = 0, s = splhigh (); 1559 CX_LOCK (bd); 1560 /* Already opened by someone or network interface is up? */ 1561 if ((d->chan->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) && 1562 (d->open_dev|0x2)) || (d->chan->mode != M_ASYNC && d->running)) 1563 status = TIOCM_LE; /* always enabled while open */ 1564 1565 if (cx_get_dsr (d->chan)) status |= TIOCM_DSR; 1566 if (cx_get_cd (d->chan)) status |= TIOCM_CD; 1567 if (cx_get_cts (d->chan)) status |= TIOCM_CTS; 1568 if (d->chan->dtr) status |= TIOCM_DTR; 1569 if (d->chan->rts) status |= TIOCM_RTS; 1570 CX_UNLOCK (bd); 1571 splx (s); 1572 return status; 1573} 1574 1575static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1576{ 1577 drv_t *d; 1578 bdrv_t *bd; 1579 cx_chan_t *c; 1580 struct serial_statistics *st; 1581 int error, s; 1582 char mask[16]; 1583 1584 d = dev->si_drv1; 1585 c = d->chan; 1586 1587 bd = d->board->sys; 1588 1589 switch (cmd) { 1590 case SERIAL_GETREGISTERED: 1591 CX_DEBUG2 (d, ("ioctl: getregistered\n")); 1592 bzero (mask, sizeof(mask)); 1593 for (s=0; s<NCX*NCHAN; ++s) 1594 if (channel [s]) 1595 mask [s/8] |= 1 << (s & 7); 1596 bcopy (mask, data, sizeof (mask)); 1597 return 0; 1598 1599 case SERIAL_GETPORT: 1600 CX_DEBUG2 (d, ("ioctl: getport\n")); 1601 s = splhigh (); 1602 CX_LOCK (bd); 1603 *(int *)data = cx_get_port (c); 1604 CX_UNLOCK (bd); 1605 splx (s); 1606 if (*(int *)data<0) 1607 return (EINVAL); 1608 else 1609 return 0; 1610 1611 case SERIAL_SETPORT: 1612 CX_DEBUG2 (d, ("ioctl: setproto\n")); 1613 /* Only for superuser! */ 1614 error = priv_check (td, PRIV_DRIVER); 1615 if (error) 1616 return error; 1617 1618 s = splhigh (); 1619 CX_LOCK (bd); 1620 cx_set_port (c, *(int *)data); 1621 CX_UNLOCK (bd); 1622 splx (s); 1623 return 0; 1624 1625#ifndef NETGRAPH 1626 case SERIAL_GETPROTO: 1627 CX_DEBUG2 (d, ("ioctl: getproto\n")); 1628 s = splhigh (); 1629 CX_LOCK (bd); 1630 strcpy ((char*)data, (c->mode == M_ASYNC) ? "async" : 1631 (IFP2SP(d->ifp)->pp_flags & PP_FR) ? "fr" : 1632 (d->ifp->if_flags & PP_CISCO) ? "cisco" : "ppp"); 1633 CX_UNLOCK (bd); 1634 splx (s); 1635 return 0; 1636 1637 case SERIAL_SETPROTO: 1638 CX_DEBUG2 (d, ("ioctl: setproto\n")); 1639 /* Only for superuser! */ 1640 error = priv_check (td, PRIV_DRIVER); 1641 if (error) 1642 return error; 1643 if (c->mode == M_ASYNC) 1644 return EBUSY; 1645 if (d->ifp->if_drv_flags & IFF_DRV_RUNNING) 1646 return EBUSY; 1647 if (! strcmp ("cisco", (char*)data)) { 1648 IFP2SP(d->ifp)->pp_flags &= ~(PP_FR); 1649 IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1650 d->ifp->if_flags |= PP_CISCO; 1651 } else if (! strcmp ("fr", (char*)data)) { 1652 d->ifp->if_flags &= ~(PP_CISCO); 1653 IFP2SP(d->ifp)->pp_flags |= PP_FR | PP_KEEPALIVE; 1654 } else if (! strcmp ("ppp", (char*)data)) { 1655 IFP2SP(d->ifp)->pp_flags &= ~(PP_FR | PP_KEEPALIVE); 1656 d->ifp->if_flags &= ~(PP_CISCO); 1657 } else 1658 return EINVAL; 1659 return 0; 1660 1661 case SERIAL_GETKEEPALIVE: 1662 CX_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1663 if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1664 (d->ifp->if_flags & PP_CISCO) || 1665 (c->mode == M_ASYNC)) 1666 return EINVAL; 1667 s = splhigh (); 1668 CX_LOCK (bd); 1669 *(int*)data = (IFP2SP(d->ifp)->pp_flags & PP_KEEPALIVE) ? 1 : 0; 1670 CX_UNLOCK (bd); 1671 splx (s); 1672 return 0; 1673 1674 case SERIAL_SETKEEPALIVE: 1675 CX_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1676 /* Only for superuser! */ 1677 error = priv_check (td, PRIV_DRIVER); 1678 if (error) 1679 return error; 1680 if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || 1681 (d->ifp->if_flags & PP_CISCO)) 1682 return EINVAL; 1683 s = splhigh (); 1684 CX_LOCK (bd); 1685 if (*(int*)data) 1686 IFP2SP(d->ifp)->pp_flags |= PP_KEEPALIVE; 1687 else 1688 IFP2SP(d->ifp)->pp_flags &= ~PP_KEEPALIVE; 1689 CX_UNLOCK (bd); 1690 splx (s); 1691 return 0; 1692#endif /*NETGRAPH*/ 1693 1694 case SERIAL_GETMODE: 1695 CX_DEBUG2 (d, ("ioctl: getmode\n")); 1696 s = splhigh (); 1697 CX_LOCK (bd); 1698 *(int*)data = (c->mode == M_ASYNC) ? 1699 SERIAL_ASYNC : SERIAL_HDLC; 1700 CX_UNLOCK (bd); 1701 splx (s); 1702 return 0; 1703 1704 case SERIAL_SETMODE: 1705 CX_DEBUG2 (d, ("ioctl: setmode\n")); 1706 /* Only for superuser! */ 1707 error = priv_check (td, PRIV_DRIVER); 1708 if (error) 1709 return error; 1710 1711 /* Somebody is waiting for carrier? */ 1712 if (d->lock) 1713 return EBUSY; 1714 /* /dev/ttyXX is already opened by someone? */ 1715 if (c->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) && 1716 (d->open_dev|0x2)) 1717 return EBUSY; 1718 /* Network interface is up? 1719 * Cannot change to async mode. */ 1720 if (c->mode != M_ASYNC && d->running && 1721 (*(int*)data == SERIAL_ASYNC)) 1722 return EBUSY; 1723 1724 s = splhigh (); 1725 CX_LOCK (bd); 1726 if (c->mode == M_HDLC && *(int*)data == SERIAL_ASYNC) { 1727 cx_set_mode (c, M_ASYNC); 1728 cx_enable_receive (c, 0); 1729 cx_enable_transmit (c, 0); 1730 } else if (c->mode == M_ASYNC && *(int*)data == SERIAL_HDLC) { 1731 if (d->ifp->if_flags & IFF_DEBUG) 1732 c->debug = c->debug_shadow; 1733 cx_set_mode (c, M_HDLC); 1734 cx_enable_receive (c, 1); 1735 cx_enable_transmit (c, 1); 1736 } 1737 CX_UNLOCK (bd); 1738 splx (s); 1739 return 0; 1740 1741 case SERIAL_GETSTAT: 1742 CX_DEBUG2 (d, ("ioctl: getestat\n")); 1743 st = (struct serial_statistics*) data; 1744 s = splhigh (); 1745 CX_LOCK (bd); 1746 st->rintr = c->rintr; 1747 st->tintr = c->tintr; 1748 st->mintr = c->mintr; 1749 st->ibytes = c->ibytes; 1750 st->ipkts = c->ipkts; 1751 st->ierrs = c->ierrs; 1752 st->obytes = c->obytes; 1753 st->opkts = c->opkts; 1754 st->oerrs = c->oerrs; 1755 CX_UNLOCK (bd); 1756 splx (s); 1757 return 0; 1758 1759 case SERIAL_CLRSTAT: 1760 CX_DEBUG2 (d, ("ioctl: clrstat\n")); 1761 /* Only for superuser! */ 1762 error = priv_check (td, PRIV_DRIVER); 1763 if (error) 1764 return error; 1765 s = splhigh (); 1766 CX_LOCK (bd); 1767 c->rintr = 0; 1768 c->tintr = 0; 1769 c->mintr = 0; 1770 c->ibytes = 0; 1771 c->ipkts = 0; 1772 c->ierrs = 0; 1773 c->obytes = 0; 1774 c->opkts = 0; 1775 c->oerrs = 0; 1776 CX_UNLOCK (bd); 1777 splx (s); 1778 return 0; 1779 1780 case SERIAL_GETBAUD: 1781 CX_DEBUG2 (d, ("ioctl: getbaud\n")); 1782 if (c->mode == M_ASYNC) 1783 return EINVAL; 1784 s = splhigh (); 1785 CX_LOCK (bd); 1786 *(long*)data = cx_get_baud(c); 1787 CX_UNLOCK (bd); 1788 splx (s); 1789 return 0; 1790 1791 case SERIAL_SETBAUD: 1792 CX_DEBUG2 (d, ("ioctl: setbaud\n")); 1793 /* Only for superuser! */ 1794 error = priv_check (td, PRIV_DRIVER); 1795 if (error) 1796 return error; 1797 if (c->mode == M_ASYNC) 1798 return EINVAL; 1799 s = splhigh (); 1800 CX_LOCK (bd); 1801 cx_set_baud (c, *(long*)data); 1802 CX_UNLOCK (bd); 1803 splx (s); 1804 return 0; 1805 1806 case SERIAL_GETLOOP: 1807 CX_DEBUG2 (d, ("ioctl: getloop\n")); 1808 if (c->mode == M_ASYNC) 1809 return EINVAL; 1810 s = splhigh (); 1811 CX_LOCK (bd); 1812 *(int*)data = cx_get_loop (c); 1813 CX_UNLOCK (bd); 1814 splx (s); 1815 return 0; 1816 1817 case SERIAL_SETLOOP: 1818 CX_DEBUG2 (d, ("ioctl: setloop\n")); 1819 /* Only for superuser! */ 1820 error = priv_check (td, PRIV_DRIVER); 1821 if (error) 1822 return error; 1823 if (c->mode == M_ASYNC) 1824 return EINVAL; 1825 s = splhigh (); 1826 CX_LOCK (bd); 1827 cx_set_loop (c, *(int*)data); 1828 CX_UNLOCK (bd); 1829 splx (s); 1830 return 0; 1831 1832 case SERIAL_GETDPLL: 1833 CX_DEBUG2 (d, ("ioctl: getdpll\n")); 1834 if (c->mode == M_ASYNC) 1835 return EINVAL; 1836 s = splhigh (); 1837 CX_LOCK (bd); 1838 *(int*)data = cx_get_dpll (c); 1839 CX_UNLOCK (bd); 1840 splx (s); 1841 return 0; 1842 1843 case SERIAL_SETDPLL: 1844 CX_DEBUG2 (d, ("ioctl: setdpll\n")); 1845 /* Only for superuser! */ 1846 error = priv_check (td, PRIV_DRIVER); 1847 if (error) 1848 return error; 1849 if (c->mode == M_ASYNC) 1850 return EINVAL; 1851 s = splhigh (); 1852 CX_LOCK (bd); 1853 cx_set_dpll (c, *(int*)data); 1854 CX_UNLOCK (bd); 1855 splx (s); 1856 return 0; 1857 1858 case SERIAL_GETNRZI: 1859 CX_DEBUG2 (d, ("ioctl: getnrzi\n")); 1860 if (c->mode == M_ASYNC) 1861 return EINVAL; 1862 s = splhigh (); 1863 CX_LOCK (bd); 1864 *(int*)data = cx_get_nrzi (c); 1865 CX_UNLOCK (bd); 1866 splx (s); 1867 return 0; 1868 1869 case SERIAL_SETNRZI: 1870 CX_DEBUG2 (d, ("ioctl: setnrzi\n")); 1871 /* Only for superuser! */ 1872 error = priv_check (td, PRIV_DRIVER); 1873 if (error) 1874 return error; 1875 if (c->mode == M_ASYNC) 1876 return EINVAL; 1877 s = splhigh (); 1878 CX_LOCK (bd); 1879 cx_set_nrzi (c, *(int*)data); 1880 CX_UNLOCK (bd); 1881 splx (s); 1882 return 0; 1883 1884 case SERIAL_GETDEBUG: 1885 CX_DEBUG2 (d, ("ioctl: getdebug\n")); 1886 s = splhigh (); 1887 CX_LOCK (bd); 1888 *(int*)data = c->debug; 1889 CX_UNLOCK (bd); 1890 splx (s); 1891 return 0; 1892 1893 case SERIAL_SETDEBUG: 1894 CX_DEBUG2 (d, ("ioctl: setdebug\n")); 1895 /* Only for superuser! */ 1896 error = priv_check (td, PRIV_DRIVER); 1897 if (error) 1898 return error; 1899 s = splhigh (); 1900 CX_LOCK (bd); 1901#ifndef NETGRAPH 1902 if (c->mode == M_ASYNC) { 1903 c->debug = *(int*)data; 1904 } else { 1905 /* 1906 * The debug_shadow is always greater than zero for 1907 * logic simplicity. For switching debug off the 1908 * IFF_DEBUG is responsible (for !M_ASYNC mode). 1909 */ 1910 c->debug_shadow = (*(int*)data) ? (*(int*)data) : 1; 1911 if (d->ifp->if_flags & IFF_DEBUG) 1912 c->debug = c->debug_shadow; 1913 } 1914#else 1915 c->debug = *(int*)data; 1916#endif 1917 CX_UNLOCK (bd); 1918 splx (s); 1919 return 0; 1920 } 1921 1922 switch (cmd) { 1923 case TIOCSDTR: /* Set DTR */ 1924 CX_DEBUG2 (d, ("ioctl: tiocsdtr\n")); 1925 s = splhigh (); 1926 CX_LOCK (bd); 1927 cx_set_dtr (c, 1); 1928 CX_UNLOCK (bd); 1929 splx (s); 1930 return 0; 1931 1932 case TIOCCDTR: /* Clear DTR */ 1933 CX_DEBUG2 (d, ("ioctl: tioccdtr\n")); 1934 s = splhigh (); 1935 CX_LOCK (bd); 1936 cx_set_dtr (c, 0); 1937 CX_UNLOCK (bd); 1938 splx (s); 1939 return 0; 1940 1941 case TIOCMSET: /* Set DTR/RTS */ 1942 CX_DEBUG2 (d, ("ioctl: tiocmset\n")); 1943 s = splhigh (); 1944 CX_LOCK (bd); 1945 cx_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 1946 cx_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 1947 CX_UNLOCK (bd); 1948 splx (s); 1949 return 0; 1950 1951 case TIOCMBIS: /* Add DTR/RTS */ 1952 CX_DEBUG2 (d, ("ioctl: tiocmbis\n")); 1953 s = splhigh (); 1954 CX_LOCK (bd); 1955 if (*(int*)data & TIOCM_DTR) cx_set_dtr (c, 1); 1956 if (*(int*)data & TIOCM_RTS) cx_set_rts (c, 1); 1957 CX_UNLOCK (bd); 1958 splx (s); 1959 return 0; 1960 1961 case TIOCMBIC: /* Clear DTR/RTS */ 1962 CX_DEBUG2 (d, ("ioctl: tiocmbic\n")); 1963 s = splhigh (); 1964 CX_LOCK (bd); 1965 if (*(int*)data & TIOCM_DTR) cx_set_dtr (c, 0); 1966 if (*(int*)data & TIOCM_RTS) cx_set_rts (c, 0); 1967 CX_UNLOCK (bd); 1968 splx (s); 1969 return 0; 1970 1971 case TIOCMGET: /* Get modem status */ 1972 CX_DEBUG2 (d, ("ioctl: tiocmget\n")); 1973 *(int*)data = cx_modem_status (d); 1974 return 0; 1975 1976 } 1977 1978 CX_DEBUG2 (d, ("ioctl: 0x%lx\n", cmd)); 1979 return ENOTTY; 1980} 1981 1982void cx_softintr (void *unused) 1983{ 1984 drv_t *d; 1985 bdrv_t *bd; 1986 async_q *q; 1987 int i, s, ic, k; 1988 while (MY_SOFT_INTR) { 1989 MY_SOFT_INTR = 0; 1990 for (i=0; i<NCX*NCHAN; ++i) { 1991 d = channel [i]; 1992 if (!d || !d->chan || d->chan->type == T_NONE 1993 || d->chan->mode != M_ASYNC || !d->tty 1994 || !d->tty->t_dev) 1995 continue; 1996 bd = d->board->sys; 1997 s = splhigh (); 1998 CX_LOCK (bd); 1999 if (d->intr_action & CX_READ) { 2000 q = &(d->aqueue); 2001 if (d->tty->t_state & TS_CAN_BYPASS_L_RINT) { 2002 k = AQ_GSZ(q); 2003 if (d->tty->t_rawq.c_cc + k > 2004 d->tty->t_ihiwat 2005 && (d->tty->t_cflag & CRTS_IFLOW 2006 || d->tty->t_iflag & IXOFF) 2007 && !(d->tty->t_state & TS_TBLOCK)) 2008 ttyblock(d->tty); 2009 d->tty->t_rawcc += k; 2010 while (k>0) { 2011 k--; 2012 AQ_POP (q, ic); 2013 CX_UNLOCK (bd); 2014 splx (s); 2015 putc (ic, &d->tty->t_rawq); 2016 s = splhigh (); 2017 CX_LOCK (bd); 2018 } 2019 ttwakeup(d->tty); 2020 if (d->tty->t_state & TS_TTSTOP 2021 && (d->tty->t_iflag & IXANY 2022 || d->tty->t_cc[VSTART] == 2023 d->tty->t_cc[VSTOP])) { 2024 d->tty->t_state &= ~TS_TTSTOP; 2025 d->tty->t_lflag &= ~FLUSHO; 2026 d->intr_action |= CX_WRITE; 2027 } 2028 } else { 2029 while (q->end != q->beg) { 2030 AQ_POP (q, ic); 2031 CX_UNLOCK (bd); 2032 splx (s); 2033 ttyld_rint (d->tty, ic); 2034 s = splhigh (); 2035 CX_LOCK (bd); 2036 } 2037 } 2038 d->intr_action &= ~CX_READ; 2039 } 2040 splx (s); 2041 CX_UNLOCK (bd); 2042 2043 s = splhigh (); 2044 CX_LOCK (bd); 2045 if (d->intr_action & CX_WRITE) { 2046 if (d->tty->t_line) 2047 ttyld_start (d->tty); 2048 else 2049 cx_oproc (d->tty); 2050 d->intr_action &= ~CX_WRITE; 2051 } 2052 CX_UNLOCK (bd); 2053 splx (s); 2054 2055 } 2056 } 2057} 2058 2059/* 2060 * Fill transmitter buffer with data. 2061 */ 2062static void cx_oproc (struct tty *tp) 2063{ 2064 int s, k; 2065 drv_t *d; 2066 bdrv_t *bd; 2067 static u_char buf[DMABUFSZ]; 2068 u_char *p; 2069 u_short len = 0, sublen = 0; 2070 2071 d = tp->t_sc; 2072 bd = d->board->sys; 2073 2074 CX_DEBUG2 (d, ("cx_oproc\n")); 2075 2076 s = splhigh (); 2077 CX_LOCK (bd); 2078 2079 if (tp->t_cflag & CRTSCTS && (tp->t_state & TS_TBLOCK) && d->chan->rts) 2080 cx_set_rts (d->chan, 0); 2081 else if (tp->t_cflag & CRTSCTS && ! (tp->t_state & TS_TBLOCK) && ! d->chan->rts) 2082 cx_set_rts (d->chan, 1); 2083 2084 if (! (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))) { 2085 /* Start transmitter. */ 2086 cx_enable_transmit (d->chan, 1); 2087 2088 /* Is it busy? */ 2089 if (! cx_buf_free (d->chan)) { 2090 tp->t_state |= TS_BUSY; 2091 CX_UNLOCK (bd); 2092 splx (s); 2093 return; 2094 } 2095 if (tp->t_iflag & IXOFF) { 2096 p = (buf + (DMABUFSZ/2)); 2097 sublen = q_to_b (&tp->t_outq, p, (DMABUFSZ/2)); 2098 k = sublen; 2099 while (k--) { 2100 /* Send XON/XOFF out of band. */ 2101 if (*p == tp->t_cc[VSTOP]) { 2102 cx_xflow_ctl (d->chan, 0); 2103 p++; 2104 continue; 2105 } 2106 if (*p == tp->t_cc[VSTART]) { 2107 cx_xflow_ctl (d->chan, 1); 2108 p++; 2109 continue; 2110 } 2111 buf[len] = *p; 2112 len++; 2113 p++; 2114 } 2115 } else { 2116 p = buf; 2117 len = q_to_b (&tp->t_outq, p, (DMABUFSZ/2)); 2118 } 2119 if (len) { 2120 cx_send_packet (d->chan, buf, len, 0); 2121 tp->t_state |= TS_BUSY; 2122 d->atimeout = 10; 2123 CX_DEBUG2 (d, ("out %d bytes\n", len)); 2124 } 2125 } 2126 ttwwakeup (tp); 2127 CX_UNLOCK (bd); 2128 splx (s); 2129} 2130 2131static int cx_param (struct tty *tp, struct termios *t) 2132{ 2133 drv_t *d; 2134 bdrv_t *bd; 2135 int s, bits, parity; 2136 2137 d = tp->t_sc; 2138 bd = d->board->sys; 2139 2140 s = splhigh (); 2141 CX_LOCK (bd); 2142 if (t->c_ospeed == 0) { 2143 /* Clear DTR and RTS. */ 2144 cx_set_dtr (d->chan, 0); 2145 CX_UNLOCK (bd); 2146 splx (s); 2147 CX_DEBUG2 (d, ("cx_param (hangup)\n")); 2148 return 0; 2149 } 2150 CX_DEBUG2 (d, ("cx_param\n")); 2151 2152 /* Check requested parameters. */ 2153 if (t->c_ospeed < 300 || t->c_ospeed > 256*1024) { 2154 CX_UNLOCK (bd); 2155 splx (s); 2156 return EINVAL; 2157 } 2158 if (t->c_ispeed && (t->c_ispeed < 300 || t->c_ispeed > 256*1024)) { 2159 CX_UNLOCK (bd); 2160 splx (s); 2161 return EINVAL; 2162 } 2163 2164 /* And copy them to tty and channel structures. */ 2165 tp->t_ispeed = t->c_ispeed = tp->t_ospeed = t->c_ospeed; 2166 tp->t_cflag = t->c_cflag; 2167 2168 /* Set character length and parity mode. */ 2169 switch (t->c_cflag & CSIZE) { 2170 default: 2171 case CS8: bits = 8; break; 2172 case CS7: bits = 7; break; 2173 case CS6: bits = 6; break; 2174 case CS5: bits = 5; break; 2175 } 2176 2177 parity = ((t->c_cflag & PARENB) ? 1 : 0) * 2178 (1 + ((t->c_cflag & PARODD) ? 0 : 1)); 2179 2180 /* Set current channel number. */ 2181 if (! d->chan->dtr) 2182 cx_set_dtr (d->chan, 1); 2183 2184 ttyldoptim (tp); 2185 cx_set_async_param (d->chan, t->c_ospeed, bits, parity, (t->c_cflag & CSTOPB), 2186 !(t->c_cflag & PARENB), (t->c_cflag & CRTSCTS), 2187 (t->c_iflag & IXON), (t->c_iflag & IXANY), 2188 t->c_cc[VSTART], t->c_cc[VSTOP]); 2189 CX_UNLOCK (bd); 2190 splx (s); 2191 return 0; 2192} 2193 2194/* 2195 * Stop output on a line 2196 */ 2197static void cx_stop (struct tty *tp, int flag) 2198{ 2199 drv_t *d; 2200 bdrv_t *bd; 2201 int s; 2202 2203 d = tp->t_sc; 2204 bd = d->board->sys; 2205 2206 s = splhigh (); 2207 CX_LOCK (bd); 2208 if (tp->t_state & TS_BUSY) { 2209 /* Stop transmitter */ 2210 CX_DEBUG2 (d, ("cx_stop\n")); 2211 cx_transmitter_ctl (d->chan, 0); 2212 } 2213 CX_UNLOCK (bd); 2214 splx (s); 2215} 2216 2217/* 2218 * Process the (delayed) carrier signal setup. 2219 */ 2220static void cx_carrier (void *arg) 2221{ 2222 drv_t *d = arg; 2223 bdrv_t *bd = d->board->sys; 2224 cx_chan_t *c = d->chan; 2225 int s, cd; 2226 2227 s = splhigh (); 2228 CX_LOCK (bd); 2229 cd = cx_get_cd (c); 2230 if (d->cd != cd) { 2231 if (cd) { 2232 CX_DEBUG (d, ("carrier on\n")); 2233 d->cd = 1; 2234 CX_UNLOCK (bd); 2235 splx (s); 2236 if (d->tty) 2237 ttyld_modem(d->tty, 1); 2238 } else { 2239 CX_DEBUG (d, ("carrier loss\n")); 2240 d->cd = 0; 2241 CX_UNLOCK (bd); 2242 splx (s); 2243 if (d->tty) 2244 ttyld_modem(d->tty, 0); 2245 } 2246 } else { 2247 CX_UNLOCK (bd); 2248 splx (s); 2249 } 2250} 2251 2252/* 2253 * Modem signal callback function. 2254 */ 2255static void cx_modem (cx_chan_t *c) 2256{ 2257 drv_t *d = c->sys; 2258 2259 if (!d || c->mode != M_ASYNC) 2260 return; 2261 /* Handle carrier detect/loss. */ 2262 /* Carrier changed - delay processing DCD for a while 2263 * to give both sides some time to initialize. */ 2264 callout_reset (&d->dcd_timeout_handle, hz/2, cx_carrier, d); 2265} 2266 2267#ifdef NETGRAPH 2268static int ng_cx_constructor (node_p node) 2269{ 2270 drv_t *d = NG_NODE_PRIVATE (node); 2271 CX_DEBUG (d, ("Constructor\n")); 2272 return EINVAL; 2273} 2274 2275static int ng_cx_newhook (node_p node, hook_p hook, const char *name) 2276{ 2277 int s; 2278 drv_t *d = NG_NODE_PRIVATE (node); 2279 bdrv_t *bd = d->board->sys; 2280 2281 if (d->chan->mode == M_ASYNC) 2282 return EINVAL; 2283 2284 /* Attach debug hook */ 2285 if (strcmp (name, NG_CX_HOOK_DEBUG) == 0) { 2286 NG_HOOK_SET_PRIVATE (hook, NULL); 2287 d->debug_hook = hook; 2288 return 0; 2289 } 2290 2291 /* Check for raw hook */ 2292 if (strcmp (name, NG_CX_HOOK_RAW) != 0) 2293 return EINVAL; 2294 2295 NG_HOOK_SET_PRIVATE (hook, d); 2296 d->hook = hook; 2297 s = splhigh (); 2298 CX_LOCK (bd); 2299 cx_up (d); 2300 CX_UNLOCK (bd); 2301 splx (s); 2302 return 0; 2303} 2304 2305static int print_modems (char *s, cx_chan_t *c, int need_header) 2306{ 2307 int status = cx_modem_status (c->sys); 2308 int length = 0; 2309 2310 if (need_header) 2311 length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 2312 length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 2313 status & TIOCM_LE ? "On" : "-", 2314 status & TIOCM_DTR ? "On" : "-", 2315 status & TIOCM_DSR ? "On" : "-", 2316 status & TIOCM_RTS ? "On" : "-", 2317 status & TIOCM_CTS ? "On" : "-", 2318 status & TIOCM_CD ? "On" : "-"); 2319 return length; 2320} 2321 2322static int print_stats (char *s, cx_chan_t *c, int need_header) 2323{ 2324 int length = 0; 2325 2326 if (need_header) 2327 length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 2328 length += sprintf (s + length, "%7ld %7ld %7ld %8ld %7ld %7ld %8ld %7ld %7ld\n", 2329 c->rintr, c->tintr, c->mintr, c->ibytes, c->ipkts, 2330 c->ierrs, c->obytes, c->opkts, c->oerrs); 2331 return length; 2332} 2333 2334static int print_chan (char *s, cx_chan_t *c) 2335{ 2336 drv_t *d = c->sys; 2337 int length = 0; 2338 2339 length += sprintf (s + length, "cx%d", c->board->num * NCHAN + c->num); 2340 if (d->chan->debug) 2341 length += sprintf (s + length, " debug=%d", d->chan->debug); 2342 2343 if (cx_get_baud (c)) 2344 length += sprintf (s + length, " %ld", cx_get_baud (c)); 2345 else 2346 length += sprintf (s + length, " extclock"); 2347 2348 if (c->mode == M_HDLC) { 2349 length += sprintf (s + length, " dpll=%s", cx_get_dpll (c) ? "on" : "off"); 2350 length += sprintf (s + length, " nrzi=%s", cx_get_nrzi (c) ? "on" : "off"); 2351 } 2352 2353 length += sprintf (s + length, " loop=%s", cx_get_loop (c) ? "on\n" : "off\n"); 2354 return length; 2355} 2356 2357static int ng_cx_rcvmsg (node_p node, item_p item, hook_p lasthook) 2358{ 2359 drv_t *d = NG_NODE_PRIVATE (node); 2360 struct ng_mesg *msg; 2361 struct ng_mesg *resp = NULL; 2362 int error = 0; 2363 2364 if (!d) 2365 return EINVAL; 2366 2367 CX_DEBUG (d, ("Rcvmsg\n")); 2368 NGI_GET_MSG (item, msg); 2369 switch (msg->header.typecookie) { 2370 default: 2371 error = EINVAL; 2372 break; 2373 2374 case NGM_CX_COOKIE: 2375 printf ("Don't forget to implement\n"); 2376 error = EINVAL; 2377 break; 2378 2379 case NGM_GENERIC_COOKIE: 2380 switch (msg->header.cmd) { 2381 default: 2382 error = EINVAL; 2383 break; 2384 2385 case NGM_TEXT_STATUS: { 2386 char *s; 2387 int l = 0; 2388 int dl = sizeof (struct ng_mesg) + 730; 2389 2390 NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2391 if (! resp) { 2392 error = ENOMEM; 2393 break; 2394 } 2395 bzero (resp, dl); 2396 s = (resp)->data; 2397 l += print_chan (s + l, d->chan); 2398 l += print_stats (s + l, d->chan, 1); 2399 l += print_modems (s + l, d->chan, 1); 2400 strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRSIZ); 2401 } 2402 break; 2403 } 2404 break; 2405 } 2406 NG_RESPOND_MSG (error, node, item, resp); 2407 NG_FREE_MSG (msg); 2408 return error; 2409} 2410 2411static int ng_cx_rcvdata (hook_p hook, item_p item) 2412{ 2413 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2414 struct mbuf *m; 2415 struct ng_tag_prio *ptag; 2416 bdrv_t *bd; 2417 struct ifqueue *q; 2418 int s; 2419 2420 NGI_GET_M (item, m); 2421 NG_FREE_ITEM (item); 2422 if (! NG_HOOK_PRIVATE (hook) || ! d) { 2423 NG_FREE_M (m); 2424 return ENETDOWN; 2425 } 2426 2427 bd = d->board->sys; 2428 /* Check for high priority data */ 2429 if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, 2430 NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) 2431 q = &d->hi_queue; 2432 else 2433 q = &d->lo_queue; 2434 2435 s = splhigh (); 2436 CX_LOCK (bd); 2437 IF_LOCK (q); 2438 if (_IF_QFULL (q)) { 2439 _IF_DROP (q); 2440 IF_UNLOCK (q); 2441 CX_UNLOCK (bd); 2442 splx (s); 2443 NG_FREE_M (m); 2444 return ENOBUFS; 2445 } 2446 _IF_ENQUEUE (q, m); 2447 IF_UNLOCK (q); 2448 cx_start (d); 2449 CX_UNLOCK (bd); 2450 splx (s); 2451 return 0; 2452} 2453 2454static int ng_cx_rmnode (node_p node) 2455{ 2456 drv_t *d = NG_NODE_PRIVATE (node); 2457 bdrv_t *bd; 2458 2459 CX_DEBUG (d, ("Rmnode\n")); 2460 if (d && d->running) { 2461 int s = splhigh (); 2462 bd = d->board->sys; 2463 CX_LOCK (bd); 2464 cx_down (d); 2465 CX_UNLOCK (bd); 2466 splx (s); 2467 } 2468#ifdef KLD_MODULE 2469 if (node->nd_flags & NGF_REALLY_DIE) { 2470 NG_NODE_SET_PRIVATE (node, NULL); 2471 NG_NODE_UNREF (node); 2472 } 2473 NG_NODE_REVIVE(node); /* Persistant node */ 2474#endif 2475 return 0; 2476} 2477 2478static int ng_cx_connect (hook_p hook) 2479{ 2480 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2481 2482 callout_reset (&d->timeout_handle, hz, cx_watchdog_timer, d); 2483 return 0; 2484} 2485 2486static int ng_cx_disconnect (hook_p hook) 2487{ 2488 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2489 bdrv_t *bd = d->board->sys; 2490 int s; 2491 2492 s = splhigh (); 2493 CX_LOCK (bd); 2494 if (NG_HOOK_PRIVATE (hook)) 2495 cx_down (d); 2496 CX_UNLOCK (bd); 2497 splx (s); 2498 /* If we were wait it than it reasserted now, just stop it. */ 2499 if (!callout_drain (&d->timeout_handle)) 2500 callout_stop (&d->timeout_handle); 2501 return 0; 2502} 2503#endif /*NETGRAPH*/ 2504 2505static int cx_modevent (module_t mod, int type, void *unused) 2506{ 2507 static int load_count = 0; 2508 2509 switch (type) { 2510 case MOD_LOAD: 2511#ifdef NETGRAPH 2512 if (ng_newtype (&typestruct)) 2513 printf ("Failed to register ng_cx\n"); 2514#endif 2515 ++load_count; 2516 2517 callout_init (&timeout_handle, CALLOUT_MPSAFE); 2518 callout_reset (&timeout_handle, hz*5, cx_timeout, 0); 2519 /* Software interrupt. */ 2520 swi_add(&tty_intr_event, "cx", cx_softintr, NULL, SWI_TTY, 2521 INTR_MPSAFE, &cx_fast_ih); 2522 break; 2523 case MOD_UNLOAD: 2524 if (load_count == 1) { 2525 printf ("Removing device entry for Sigma\n"); 2526#ifdef NETGRAPH 2527 ng_rmtype (&typestruct); 2528#endif 2529 } 2530 /* If we were wait it than it reasserted now, just stop it. */ 2531 if (!callout_drain (&timeout_handle)) 2532 callout_stop (&timeout_handle); 2533 swi_remove (cx_fast_ih); 2534 --load_count; 2535 break; 2536 case MOD_SHUTDOWN: 2537 break; 2538 } 2539 return 0; 2540} 2541 2542#ifdef NETGRAPH 2543static struct ng_type typestruct = { 2544 .version = NG_ABI_VERSION, 2545 .name = NG_CX_NODE_TYPE, 2546 .constructor = ng_cx_constructor, 2547 .rcvmsg = ng_cx_rcvmsg, 2548 .shutdown = ng_cx_rmnode, 2549 .newhook = ng_cx_newhook, 2550 .connect = ng_cx_connect, 2551 .rcvdata = ng_cx_rcvdata, 2552 .disconnect = ng_cx_disconnect, 2553}; 2554#endif /*NETGRAPH*/ 2555 2556#ifdef NETGRAPH 2557MODULE_DEPEND (ng_cx, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 2558#else 2559MODULE_DEPEND (isa_cx, sppp, 1, 1, 1); 2560#endif 2561DRIVER_MODULE (cx, isa, cx_isa_driver, cx_devclass, cx_modevent, NULL); 2562MODULE_VERSION (cx, 1);
|