if_cx.c revision 130203
1/* 2 * Cronyx-Sigma adapter driver for FreeBSD. 3 * Supports PPP/HDLC and Cisco/HDLC protocol in synchronous mode, 4 * and asyncronous channels with full modem control. 5 * Keepalive protocol implemented in both Cisco and PPP modes. 6 * 7 * Copyright (C) 1994-2002 Cronyx Engineering. 8 * Author: Serge Vakulenko, <vak@cronyx.ru> 9 * 10 * Copyright (C) 1999-2004 Cronyx Engineering. 11 * Rewritten on DDK, ported to NETGRAPH, rewritten for FreeBSD 3.x-5.x by 12 * Kurakin Roman, <rik@cronyx.ru> 13 * 14 * This software is distributed with NO WARRANTIES, not even the implied 15 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * Authors grant any other persons or organisations a permission to use, 18 * modify and redistribute this software in source and binary forms, 19 * as long as this message is kept with the software, all derivative 20 * works or modified versions. 21 * 22 * Cronyx Id: if_cx.c,v 1.1.2.23 2004/02/26 17:56:40 rik Exp $ 23 */ 24#include <sys/cdefs.h> 25__FBSDID("$FreeBSD: head/sys/dev/cx/if_cx.c 130203 2004-06-07 20:45:45Z phk $"); 26 27#include <sys/param.h> 28 29#if __FreeBSD_version >= 500000 30# define NCX 1 31#else 32# include "cx.h" 33#endif 34 35#if NCX > 0 36#include <sys/systm.h> 37#include <sys/kernel.h> 38#include <sys/module.h> 39#include <sys/proc.h> 40#include <sys/mbuf.h> 41#include <sys/sockio.h> 42#include <sys/malloc.h> 43#include <sys/socket.h> 44#include <sys/conf.h> 45#include <sys/errno.h> 46#include <sys/tty.h> 47#if __FreeBSD_version >= 400000 48# include <sys/bus.h> 49# include <machine/bus.h> 50# include <sys/rman.h> 51# include <isa/isavar.h> 52#endif 53#include <sys/fcntl.h> 54#include <sys/interrupt.h> 55#include <vm/vm.h> 56#include <vm/pmap.h> 57#include <net/if.h> 58#include <machine/cpufunc.h> 59#include <machine/cserial.h> 60#include <machine/clock.h> 61#if __FreeBSD_version < 500000 62#include <machine/ipl.h> 63#include <i386/isa/isa_device.h> 64#endif 65#if __FreeBSD_version >= 400000 66# include <machine/resource.h> 67# if __FreeBSD_version <= 501000 68# include <i386/isa/intr_machdep.h> 69# endif 70#endif 71#if __FreeBSD_version >= 400000 72# include <dev/cx/machdep.h> 73# include <dev/cx/cxddk.h> 74# include <dev/cx/cronyxfw.h> 75#else 76# include <i386/isa/cronyx/machdep.h> 77# include <i386/isa/cronyx/cxddk.h> 78# include <i386/isa/cronyx/cronyxfw.h> 79#endif 80#include "opt_ng_cronyx.h" 81#ifdef NETGRAPH_CRONYX 82# include "opt_netgraph.h" 83# include <netgraph/ng_message.h> 84# include <netgraph/netgraph.h> 85# if __FreeBSD_version >= 400000 86# include <dev/cx/ng_cx.h> 87# else 88# include <netgraph/ng_cx.h> 89# endif 90#else 91# include <net/if_types.h> 92# if __FreeBSD_version < 500000 93# include "sppp.h" 94# if NSPPP <= 0 95# error The device cx requires sppp or netgraph. 96# endif 97# endif 98# include <net/if_sppp.h> 99# define PP_CISCO IFF_LINK2 100#if __FreeBSD_version < 400000 101# include <bpfilter.h> 102# if NBPFILTER > 0 103# include <net/bpf.h> 104# endif 105#else 106# if __FreeBSD_version < 500000 107# include <bpf.h> 108# endif 109# include <net/bpf.h> 110# define NBPFILTER NBPF 111#endif 112#endif 113 114#if __FreeBSD_version < 502113 115#define ttyld_modem(foo, bar) ((*linesw[(foo)->t_line].l_modem)((foo), (bar))) 116#define ttyld_rint(foo, bar) ((*linesw[(foo)->t_line].l_rint)((bar), (foo))) 117#define ttyld_start(foo) ((*linesw[(foo)->t_line].l_start)((foo))) 118#define ttyld_open(foo, bar) ((*linesw[(foo)->t_line].l_open) ((bar), (foo))) 119#define ttyld_close(foo, bar) ((*linesw[(foo)->t_line].l_close) ((foo), (bar))) 120#define ttyld_read(foo, bar, barf) ((*linesw[(foo)->t_line].l_read) ((foo), (bar), (barf))) 121#define ttyld_write(foo, bar, barf) ((*linesw[(foo)->t_line].l_write) ((foo), (bar), (barf))) 122#endif 123 124/* If we don't have Cronyx's sppp version, we don't have fr support via sppp */ 125#ifndef PP_FR 126#define PP_FR 0 127#endif 128 129#define CX_DEBUG(d,s) ({if (d->chan->debug) {\ 130 printf ("%s: ", d->name); printf s;}}) 131#define CX_DEBUG2(d,s) ({if (d->chan->debug>1) {\ 132 printf ("%s: ", d->name); printf s;}}) 133 134#define UNIT(d) (minor(d) & 0x3f) 135#define IF_CUNIT(d) (minor(d) & 0x40) 136#define UNIT_CTL 0x3f 137#define CALLOUT(d) (minor(d) & 0x80) 138#define CDEV_MAJOR 42 139 140typedef struct _async_q { 141 int beg; 142 int end; 143 #define BF_SZ 14400 144 int buf[BF_SZ+1]; 145} async_q; 146 147#define AQ_GSZ(q) ((BF_SZ + (q)->end - (q)->beg)%BF_SZ) 148#define AQ_PUSH(q,c) {*((q)->buf + (q)->end) = c;\ 149 (q)->end = ((q)->end + 1)%BF_SZ;} 150#define AQ_POP(q,c) {c = *((q)->buf + (q)->beg);\ 151 (q)->beg = ((q)->beg + 1)%BF_SZ;} 152 153#if __FreeBSD_version >= 400000 154static void cx_identify __P((driver_t *, device_t)); 155static int cx_probe __P((device_t)); 156static int cx_attach __P((device_t)); 157static int cx_detach __P((device_t)); 158 159static device_method_t cx_isa_methods [] = { 160 DEVMETHOD(device_identify, cx_identify), 161 DEVMETHOD(device_probe, cx_probe), 162 DEVMETHOD(device_attach, cx_attach), 163 DEVMETHOD(device_detach, cx_detach), 164 {0, 0} 165}; 166 167typedef struct _bdrv_t { 168 cx_board_t *board; 169 struct resource *base_res; 170 struct resource *drq_res; 171 struct resource *irq_res; 172 int base_rid; 173 int drq_rid; 174 int irq_rid; 175 void *intrhand; 176} bdrv_t; 177 178static driver_t cx_isa_driver = { 179 "cx", 180 cx_isa_methods, 181 sizeof (bdrv_t), 182}; 183 184static devclass_t cx_devclass; 185#endif 186 187typedef struct _drv_t { 188 char name [8]; 189 cx_chan_t *chan; 190 cx_board_t *board; 191 cx_buf_t buf; 192 struct tty tty; 193 struct callout_handle dcd_timeout_handle; 194 unsigned dtrwait; 195 unsigned dtroff; 196 unsigned callout; 197 unsigned lock; 198 int open_dev; 199 int cd; 200 int running; 201 struct callout_handle dtr_timeout_handle; 202#ifdef NETGRAPH 203 char nodename [NG_NODELEN+1]; 204 hook_p hook; 205 hook_p debug_hook; 206 node_p node; 207 struct ifqueue lo_queue; 208 struct ifqueue hi_queue; 209 short timeout; 210 struct callout_handle timeout_handle; 211#else 212 struct sppp pp; 213#endif 214#if __FreeBSD_version >= 400000 215 dev_t devt[3]; 216#endif 217 async_q aqueue; 218 #define CX_READ 1 219 #define CX_WRITE 2 220 int intr_action; 221 short atimeout; 222} drv_t; 223 224extern long csigma_fw_len; 225extern const char *csigma_fw_version; 226extern const char *csigma_fw_date; 227extern const char *csigma_fw_copyright; 228extern const cr_dat_tst_t csigma_fw_tvec[]; 229extern const u_char csigma_fw_data[]; 230static void cx_oproc (struct tty *tp); 231static int cx_param (struct tty *tp, struct termios *t); 232static void cx_stop (struct tty *tp, int flag); 233static void cx_dtrwakeup (void *a); 234static void cx_receive (cx_chan_t *c, char *data, int len); 235static void cx_transmit (cx_chan_t *c, void *attachment, int len); 236static void cx_error (cx_chan_t *c, int data); 237static void cx_modem (cx_chan_t *c); 238static void cx_up (drv_t *d); 239static void cx_start (drv_t *d); 240#if __FreeBSD_version < 502113 241static void ttyldoptim(struct tty *tp); 242#endif 243#if __FreeBSD_version < 500000 244static swihand_t cx_softintr; 245#else 246static void cx_softintr (void *); 247static void *cx_fast_ih; 248#endif 249static void cx_down (drv_t *d); 250static void cx_watchdog (drv_t *d); 251static void cx_carrier (void *arg); 252 253#ifdef NETGRAPH 254extern struct ng_type typestruct; 255#else 256static void cx_ifstart (struct ifnet *ifp); 257static void cx_tlf (struct sppp *sp); 258static void cx_tls (struct sppp *sp); 259static void cx_ifwatchdog (struct ifnet *ifp); 260static int cx_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 261static void cx_initialize (void *softc); 262#endif 263 264static cx_board_t *adapter [NCX]; 265static drv_t *channel [NCX*NCHAN]; 266static struct callout_handle led_timo [NCX]; 267static struct callout_handle timeout_handle; 268#if __FreeBSD_version >= 400000 269 extern struct cdevsw cx_cdevsw; 270#endif 271 272static int MY_SOFT_INTR; 273 274/* 275 * Print the mbuf chain, for debug purposes only. 276 */ 277static void printmbuf (struct mbuf *m) 278{ 279 printf ("mbuf:"); 280 for (; m; m=m->m_next) { 281 if (m->m_flags & M_PKTHDR) 282 printf (" HDR %d:", m->m_pkthdr.len); 283 if (m->m_flags & M_EXT) 284 printf (" EXT:"); 285 printf (" %d", m->m_len); 286 } 287 printf ("\n"); 288} 289 290/* 291 * Make an mbuf from data. 292 */ 293static struct mbuf *makembuf (void *buf, u_int len) 294{ 295 struct mbuf *m, *o, *p; 296 297 MGETHDR (m, M_DONTWAIT, MT_DATA); 298 299 if (! m) 300 return 0; 301 302 if (len >= MINCLSIZE) 303 MCLGET (m, M_DONTWAIT); 304 305 m->m_pkthdr.len = len; 306 m->m_len = 0; 307 308 p = m; 309 while (len) { 310 u_int n = M_TRAILINGSPACE (p); 311 if (n > len) 312 n = len; 313 if (! n) { 314 /* Allocate new mbuf. */ 315 o = p; 316 MGET (p, M_DONTWAIT, MT_DATA); 317 if (! p) { 318 m_freem (m); 319 return 0; 320 } 321 if (len >= MINCLSIZE) 322 MCLGET (p, M_DONTWAIT); 323 p->m_len = 0; 324 o->m_next = p; 325 326 n = M_TRAILINGSPACE (p); 327 if (n > len) 328 n = len; 329 } 330 bcopy (buf, mtod (p, caddr_t) + p->m_len, n); 331 332 p->m_len += n; 333 buf = n + (char*) buf; 334 len -= n; 335 } 336 return m; 337} 338 339/* 340 * Recover after lost transmit interrupts. 341 */ 342static void cx_timeout (void *arg) 343{ 344 drv_t *d; 345 int s, i; 346 347 for (i=0; i<NCX*NCHAN; ++i) { 348 d = channel[i]; 349 if (! d) 350 continue; 351 s = splhigh (); 352 if (d->atimeout == 1 && d->tty.t_state & TS_BUSY) { 353 d->tty.t_state &= ~TS_BUSY; 354 if (d->tty.t_dev) { 355 d->intr_action |= CX_WRITE; 356 MY_SOFT_INTR = 1; 357#if __FreeBSD_version >= 500000 358 swi_sched (cx_fast_ih, 0); 359#else 360 setsofttty (); 361#endif 362 } 363 CX_DEBUG (d, ("cx_timeout\n")); 364 } 365 if (d->atimeout) 366 d->atimeout--; 367 splx (s); 368 } 369 timeout_handle = timeout (cx_timeout, 0, hz*5); 370} 371 372static void cx_led_off (void *arg) 373{ 374 cx_board_t *b = arg; 375 int s = splhigh (); 376 377 cx_led (b, 0); 378 led_timo[b->num].callout = 0; 379 splx (s); 380} 381 382/* 383 * Activate interupt handler from DDK. 384 */ 385#if __FreeBSD_version >= 400000 386static void cx_intr (void *arg) 387{ 388 bdrv_t *bd = arg; 389 cx_board_t *b = bd->board; 390#else 391static void cx_intr (int bnum) 392{ 393 cx_board_t *b = adapter [bnum]; 394#endif 395 int s = splhigh (); 396 397 /* Turn LED on. */ 398 cx_led (b, 1); 399 400 cx_int_handler (b); 401 402 /* Turn LED off 50 msec later. */ 403 if (! led_timo[b->num].callout) 404 led_timo[b->num] = timeout (cx_led_off, b, hz/20); 405 splx (s); 406} 407 408static int probe_irq (cx_board_t *b, int irq) 409{ 410 int mask, busy, cnt; 411 412 /* Clear pending irq, if any. */ 413 cx_probe_irq (b, -irq); 414 DELAY (100); 415 for (cnt=0; cnt<5; ++cnt) { 416 /* Get the mask of pending irqs, assuming they are busy. 417 * Activate the adapter on given irq. */ 418 busy = cx_probe_irq (b, irq); 419 DELAY (100); 420 421 /* Get the mask of active irqs. 422 * Deactivate our irq. */ 423 mask = cx_probe_irq (b, -irq); 424 DELAY (100); 425 if ((mask & ~busy) == 1 << irq) { 426 cx_probe_irq (b, 0); 427 /* printf ("cx%d: irq %d ok, mask=0x%04x, busy=0x%04x\n", 428 b->num, irq, mask, busy); */ 429 return 1; 430 } 431 } 432 /* printf ("cx%d: irq %d not functional, mask=0x%04x, busy=0x%04x\n", 433 b->num, irq, mask, busy); */ 434 cx_probe_irq (b, 0); 435 return 0; 436} 437 438static short porttab [] = { 439 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 440 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 441}; 442static char dmatab [] = { 7, 6, 5, 0 }; 443static char irqtab [] = { 5, 10, 11, 7, 3, 15, 12, 0 }; 444 445#if __FreeBSD_version >= 400000 446static int cx_is_free_res (device_t dev, int rid, int type, u_long start, 447 u_long end, u_long count) 448{ 449 struct resource *res; 450 451 if (!(res = bus_alloc_resource (dev, type, &rid, start, end, count, 452 RF_ALLOCATED))) 453 return 0; 454 455 bus_release_resource (dev, type, rid, res); 456 457 return 1; 458} 459 460static void cx_identify (driver_t *driver, device_t dev) 461{ 462 u_long iobase, rescount; 463 int devcount; 464 device_t *devices; 465 device_t child; 466 devclass_t my_devclass; 467 int i, k; 468 469 if ((my_devclass = devclass_find ("cx")) == NULL) 470 return; 471 472 devclass_get_devices (my_devclass, &devices, &devcount); 473 474 if (devcount == 0) { 475 /* We should find all devices by our self. We could alter other 476 * devices, but we don't have a choise 477 */ 478 for (i = 0; (iobase = porttab [i]) != 0; i++) { 479 if (!cx_is_free_res (dev, 1, SYS_RES_IOPORT, 480 iobase, iobase + NPORT, NPORT)) 481 continue; 482 if (cx_probe_board (iobase, -1, -1) == 0) 483 continue; 484 485 devcount++; 486 487 child = BUS_ADD_CHILD (dev, ISA_ORDER_SPECULATIVE, "cx", 488 -1); 489 490 if (child == NULL) 491 return; 492 493 device_set_desc_copy (child, "Cronyx Sigma"); 494 device_set_driver (child, driver); 495 bus_set_resource (child, SYS_RES_IOPORT, 0, 496 iobase, NPORT); 497 498 if (devcount >= NCX) 499 break; 500 } 501 } else { 502 static short porttab [] = { 503 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 504 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 505 }; 506 /* Lets check user choise. 507 */ 508 for (k = 0; k < devcount; k++) { 509 if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0, 510 &iobase, &rescount) != 0) 511 continue; 512 513 for (i = 0; porttab [i] != 0; i++) { 514 if (porttab [i] != iobase) 515 continue; 516 if (!cx_is_free_res (devices[k], 1, SYS_RES_IOPORT, 517 iobase, iobase + NPORT, NPORT)) 518 continue; 519 if (cx_probe_board (iobase, -1, -1) == 0) 520 continue; 521 porttab [i] = -1; 522 device_set_desc_copy (devices[k], "Cronyx Sigma"); 523 break; 524 } 525 526 if (porttab [i] == 0) { 527 device_delete_child ( 528 device_get_parent (devices[k]), 529 devices [k]); 530 devices[k] = 0; 531 continue; 532 } 533 } 534 for (k = 0; k < devcount; k++) { 535 if (devices[k] == 0) 536 continue; 537 if (bus_get_resource (devices[k], SYS_RES_IOPORT, 0, 538 &iobase, &rescount) == 0) 539 continue; 540 for (i = 0; (iobase = porttab [i]) != 0; i++) { 541 if (porttab [i] == -1) { 542 continue; 543 } 544 if (!cx_is_free_res (devices[k], 1, SYS_RES_IOPORT, 545 iobase, iobase + NPORT, NPORT)) 546 continue; 547 if (cx_probe_board (iobase, -1, -1) == 0) 548 continue; 549 550 bus_set_resource (devices[k], SYS_RES_IOPORT, 0, 551 iobase, NPORT); 552 porttab [i] = -1; 553 device_set_desc_copy (devices[k], "Cronyx Sigma"); 554 break; 555 } 556 if (porttab [i] == 0) { 557 device_delete_child ( 558 device_get_parent (devices[k]), 559 devices [k]); 560 } 561 } 562 free (devices, M_TEMP); 563 } 564 565 return; 566} 567 568static int cx_probe (device_t dev) 569{ 570 int unit = device_get_unit (dev); 571 int i; 572 u_long iobase, rescount; 573 574 if (!device_get_desc (dev) || 575 strcmp (device_get_desc (dev), "Cronyx Sigma")) 576 return ENXIO; 577 578 if (bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount) != 0) { 579 printf ("cx%d: Couldn't get IOPORT\n", unit); 580 return ENXIO; 581 } 582 583 if (!cx_is_free_res (dev, 1, SYS_RES_IOPORT, 584 iobase, iobase + NPORT, NPORT)) { 585 printf ("cx%d: Resource IOPORT isn't free %lx\n", unit, iobase); 586 return ENXIO; 587 } 588 589 for (i = 0; porttab [i] != 0; i++) { 590 if (porttab [i] == iobase) { 591 porttab [i] = -1; 592 break; 593 } 594 } 595 596 if (porttab [i] == 0) { 597 return ENXIO; 598 } 599 600 if (!cx_probe_board (iobase, -1, -1)) { 601 printf ("cx%d: probing for Sigma at %lx faild\n", unit, iobase); 602 return ENXIO; 603 } 604 605 return 0; 606} 607#else /* __FreeBSD_version < 400000 */ 608static int cx_probe (struct isa_device *id) 609{ 610 cx_board_t *b; 611 int i; 612 613#ifndef NETGRAPH 614 if (! sppp_attach) { 615 printf ("cx%d: no synchronous PPP driver configured\n", 616 id->id_unit); 617 return 0; 618 } 619#endif 620 if (id->id_iobase < 0) { 621 /* Autodetect the adapter. */ 622 for (i=0; ; i++) { 623 if (! porttab[i]) { 624 id->id_iobase = -1; 625 return 0; 626 } 627 id->id_iobase = porttab[i]; 628 if (id->id_unit > 0 && adapter[0] && adapter[0]->port == id->id_iobase) 629 continue; 630 if (id->id_unit > 1 && adapter[1] && adapter[1]->port == id->id_iobase) 631 continue; 632 if (! haveseen_isadev (id, CC_IOADDR | CC_QUIET) && 633 cx_probe_board (id->id_iobase, -1, -1)) 634 break; 635 } 636 } else if (! cx_probe_board (id->id_iobase, -1, -1)) 637 return 0; 638 639 if (id->id_drq < 0) { 640 /* Find available 16-bit DRQ. */ 641 642 for (i=0; ; ++i) { 643 if (! dmatab[i]) { 644 printf ("cx%d: no available drq found\n", 645 id->id_unit); 646 id->id_drq = -1; 647 return 0; 648 } 649 id->id_drq = dmatab[i]; 650 if (! haveseen_isadev (id, CC_DRQ | CC_QUIET) 651 && !isa_dma_acquire (id->id_drq)) 652 break; 653 } 654 } 655 656 b = malloc (sizeof (cx_board_t), M_DEVBUF, M_WAITOK); 657 if (!b) { 658 printf ("cx:%d: Couldn't allocate memory\n", id->id_unit); 659 return (ENXIO); 660 } 661 adapter[id->id_unit] = b; 662 bzero (b, sizeof(cx_board_t)); 663 664 if (! cx_open_board (b, id->id_unit, id->id_iobase, 665 id->id_irq ? ffs (id->id_irq) - 1 : -1, id->id_drq)) { 666 printf ("cx%d: cannot initialize adapter\n", id->id_unit); 667 isa_dma_release (id->id_drq); 668 adapter[id->id_unit] = 0; 669 free (b, M_DEVBUF); 670 return 0; 671 } 672 673 if (id->id_irq) { 674 if (! probe_irq (b, ffs (id->id_irq) - 1)) 675 printf ("cx%d: irq %d not functional\n", 676 id->id_unit, ffs (id->id_irq) - 1); 677 } else { 678 /* Find available IRQ. */ 679 680 for (i=0; ; ++i) { 681 if (! irqtab[i]) { 682 printf ("cx%d: no available irq found\n", 683 id->id_unit); 684 id->id_irq = -1; 685 isa_dma_release (id->id_drq); 686 adapter[id->id_unit] = 0; 687 free (b, M_DEVBUF); 688 return 0; 689 } 690 id->id_irq = 1 << irqtab[i]; 691 if (haveseen_isadev (id, CC_IRQ | CC_QUIET)) 692 continue; 693#ifdef KLD_MODULE 694 if (register_intr (irqtab[i], 0, 0, (inthand2_t*) 695 cx_intr, &net_imask, id->id_unit) != 0) 696 continue; 697 unregister_intr (irqtab[i], (inthand2_t*) cx_intr); 698#endif 699 if (probe_irq (b, irqtab[i])) 700 break; 701 } 702 } 703 cx_init (b, b->num, b->port, ffs (id->id_irq) - 1, b->dma); 704 cx_setup_board (b, 0, 0, 0); 705 706 return 1; 707} 708#endif /* __FreeBSD_version < 400000 */ 709 710/* 711 * The adapter is present, initialize the driver structures. 712 */ 713#if __FreeBSD_version < 400000 714static int cx_attach (struct isa_device *id) 715{ 716#else 717static int cx_attach (device_t dev) 718{ 719 bdrv_t *bd = device_get_softc (dev); 720 u_long iobase, drq, irq, rescount; 721 int unit = device_get_unit (dev); 722 int i; 723 int s; 724#endif 725 cx_board_t *b; 726 cx_chan_t *c; 727 drv_t *d; 728 729#if __FreeBSD_version >= 400000 730 KASSERT ((bd != NULL), ("cx%d: NULL device softc\n", unit)); 731 732 bus_get_resource (dev, SYS_RES_IOPORT, 0, &iobase, &rescount); 733 bd->base_rid = 0; 734 bd->base_res = bus_alloc_resource (dev, SYS_RES_IOPORT, &bd->base_rid, 735 iobase, iobase + NPORT, NPORT, RF_ACTIVE); 736 if (! bd->base_res) { 737 printf ("cx%d: cannot allocate base address\n", unit); 738 return ENXIO; 739 } 740 741 if (bus_get_resource (dev, SYS_RES_DRQ, 0, &drq, &rescount) != 0) { 742 for (i = 0; (drq = dmatab [i]) != 0; i++) { 743 if (!cx_is_free_res (dev, 1, SYS_RES_DRQ, 744 drq, drq + 1, 1)) 745 continue; 746 bus_set_resource (dev, SYS_RES_DRQ, 0, drq, 1); 747 break; 748 } 749 750 if (dmatab[i] == 0) { 751 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 752 bd->base_res); 753 printf ("cx%d: Couldn't get DRQ\n", unit); 754 return ENXIO; 755 } 756 } 757 758 bd->drq_rid = 0; 759 bd->drq_res = bus_alloc_resource (dev, SYS_RES_DRQ, &bd->drq_rid, 760 drq, drq + 1, 1, RF_ACTIVE); 761 if (! bd->drq_res) { 762 printf ("cx%d: cannot allocate drq\n", unit); 763 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 764 bd->base_res); 765 return ENXIO; 766 } 767 768 if (bus_get_resource (dev, SYS_RES_IRQ, 0, &irq, &rescount) != 0) { 769 for (i = 0; (irq = irqtab [i]) != 0; i++) { 770 if (!cx_is_free_res (dev, 1, SYS_RES_IRQ, 771 irq, irq + 1, 1)) 772 continue; 773 bus_set_resource (dev, SYS_RES_IRQ, 0, irq, 1); 774 break; 775 } 776 777 if (irqtab[i] == 0) { 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 printf ("cx%d: Couldn't get IRQ\n", unit); 783 return ENXIO; 784 } 785 } 786 787 bd->irq_rid = 0; 788 bd->irq_res = bus_alloc_resource (dev, SYS_RES_IRQ, &bd->irq_rid, 789 irq, irq + 1, 1, RF_ACTIVE); 790 if (! bd->irq_res) { 791 printf ("cx%d: Couldn't allocate irq\n", unit); 792 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 793 bd->drq_res); 794 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 795 bd->base_res); 796 return ENXIO; 797 } 798 799 b = malloc (sizeof (cx_board_t), M_DEVBUF, M_WAITOK); 800 if (!b) { 801 printf ("cx:%d: Couldn't allocate memory\n", unit); 802 return (ENXIO); 803 } 804 adapter[unit] = b; 805 bzero (b, sizeof(cx_board_t)); 806 807 if (! cx_open_board (b, unit, iobase, irq, drq)) { 808 printf ("cx%d: error loading firmware\n", unit); 809 free (b, M_DEVBUF); 810 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 811 bd->irq_res); 812 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 813 bd->drq_res); 814 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 815 bd->base_res); 816 return ENXIO; 817 } 818 819 bd->board = b; 820 821 if (! probe_irq (b, irq)) { 822 printf ("cx%d: irq %ld not functional\n", unit, irq); 823 bd->board = 0; 824 adapter [unit] = 0; 825 free (b, M_DEVBUF); 826 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 827 bd->irq_res); 828 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 829 bd->drq_res); 830 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 831 bd->base_res); 832 return ENXIO; 833 } 834 835 s = splhigh (); 836 if (bus_setup_intr (dev, bd->irq_res, INTR_TYPE_NET, cx_intr, bd, 837 &bd->intrhand)) { 838 printf ("cx%d: Can't setup irq %ld\n", unit, irq); 839 bd->board = 0; 840 adapter [unit] = 0; 841 free (b, M_DEVBUF); 842 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, 843 bd->irq_res); 844 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, 845 bd->drq_res); 846 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, 847 bd->base_res); 848 splx (s); 849 return ENXIO; 850 } 851 852 cx_init (b, b->num, b->port, irq, drq); 853 cx_setup_board (b, 0, 0, 0); 854#else /* __FreeBSD_version >= 400000 */ 855 b = adapter[id->id_unit]; 856#endif /* __FreeBSD_version >= 400000 */ 857 858 printf ("cx%d: <Cronyx-Sigma-%s>\n", b->num, b->name); 859#if __FreeBSD_version < 400000 860 id->id_ointr = cx_intr; 861#endif 862 863 for (c=b->chan; c<b->chan+NCHAN; ++c) { 864#if __FreeBSD_version >= 400000 865 char *dnmt="tty %x"; 866 char *dnmc="cua %x"; 867#endif 868 if (c->type == T_NONE) 869 continue; 870 d = contigmalloc (sizeof(drv_t), M_DEVBUF, M_WAITOK, 871 0x100000, 0x1000000, 16, 0); 872 channel [b->num*NCHAN + c->num] = d; 873 bzero (d, sizeof(drv_t)); 874 sprintf (d->name, "cx%d.%d", b->num, c->num); 875 d->board = b; 876 d->chan = c; 877 d->tty.t_oproc = cx_oproc; 878 d->tty.t_param = cx_param; 879#if __FreeBSD_version >= 400000 880 d->tty.t_stop = cx_stop; 881#endif 882 d->dtrwait = 3 * hz; /* Default DTR off timeout is 3 seconds. */ 883 d->open_dev = 0; 884 c->sys = d; 885 886 switch (c->type) { 887 case T_SYNC_RS232: 888 case T_SYNC_V35: 889 case T_SYNC_RS449: 890 case T_UNIV: 891 case T_UNIV_RS232: 892 case T_UNIV_RS449: 893 case T_UNIV_V35: 894#ifdef NETGRAPH 895 if (ng_make_node_common (&typestruct, &d->node) != 0) { 896 printf ("%s: cannot make common node\n", d->name); 897 channel [b->num*NCHAN + c->num] = 0; 898 c->sys = 0; 899#if __FreeBSD_version < 400000 900 free (d, M_DEVBUF); 901#else 902 contigfree (d, sizeof (*d), M_DEVBUF); 903#endif 904 continue; 905 } 906#if __FreeBSD_version >= 500000 907 NG_NODE_SET_PRIVATE (d->node, d); 908#else 909 d->node->private = d; 910#endif 911 sprintf (d->nodename, "%s%d", NG_CX_NODE_TYPE, 912 c->board->num*NCHAN + c->num); 913 if (ng_name_node (d->node, d->nodename)) { 914 printf ("%s: cannot name node\n", d->nodename); 915#if __FreeBSD_version >= 500000 916 NG_NODE_UNREF (d->node); 917#else 918 ng_rmnode (d->node); 919 ng_unref (d->node); 920#endif 921 channel [b->num*NCHAN + c->num] = 0; 922 c->sys = 0; 923#if __FreeBSD_version < 400000 924 free (d, M_DEVBUF); 925#else 926 contigfree (d, sizeof (*d), M_DEVBUF); 927#endif 928 continue; 929 } 930 d->lo_queue.ifq_maxlen = IFQ_MAXLEN; 931 d->hi_queue.ifq_maxlen = IFQ_MAXLEN; 932#if __FreeBSD_version >= 500000 933 mtx_init (&d->lo_queue.ifq_mtx, "cx_queue_lo", NULL, MTX_DEF); 934 mtx_init (&d->hi_queue.ifq_mtx, "cx_queue_hi", NULL, MTX_DEF); 935#endif 936#else /*NETGRAPH*/ 937 d->pp.pp_if.if_softc = d; 938#if __FreeBSD_version > 501000 939 if_initname (&d->pp.pp_if, "cx", b->num * NCHAN + c->num); 940#else 941 d->pp.pp_if.if_unit = b->num * NCHAN + c->num; 942 d->pp.pp_if.if_name = "cx"; 943#endif 944 d->pp.pp_if.if_mtu = PP_MTU; 945 d->pp.pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 946 d->pp.pp_if.if_ioctl = cx_sioctl; 947 d->pp.pp_if.if_start = cx_ifstart; 948 d->pp.pp_if.if_watchdog = cx_ifwatchdog; 949 d->pp.pp_if.if_init = cx_initialize; 950 sppp_attach (&d->pp.pp_if); 951 if_attach (&d->pp.pp_if); 952 d->pp.pp_tlf = cx_tlf; 953 d->pp.pp_tls = cx_tls; 954#if __FreeBSD_version >= 400000 || NBPFILTER > 0 955 /* If BPF is in the kernel, call the attach for it. 956 * Size of PPP header is 4 bytes. */ 957 bpfattach (&d->pp.pp_if, DLT_PPP, 4); 958#endif 959#endif /*NETGRAPH*/ 960 } 961 cx_start_chan (c, &d->buf, vtophys (&d->buf)); 962 cx_register_receive (c, &cx_receive); 963 cx_register_transmit (c, &cx_transmit); 964 cx_register_error (c, &cx_error); 965 cx_register_modem (c, &cx_modem); 966#if __FreeBSD_version >= 400000 967 dnmt[3] = 'x'+b->num; 968 dnmc[3] = 'x'+b->num; 969 d->devt[0] = make_dev (&cx_cdevsw, b->num*NCHAN + c->num, UID_ROOT, GID_WHEEL, 0644, dnmt, b->num*NCHAN + c->num); 970 d->devt[1] = make_dev (&cx_cdevsw, b->num*NCHAN + c->num + 64, UID_ROOT, GID_WHEEL, 0600, "cx%d", b->num*NCHAN + c->num); 971 d->devt[2] = make_dev (&cx_cdevsw, b->num*NCHAN + c->num + 128, UID_ROOT, GID_WHEEL, 0660, dnmc, b->num*NCHAN + c->num); 972 } 973 splx (s); 974 975 return 0; 976#else /* __FreeBSD_version < 400000 */ 977 } 978 979 return 1; 980#endif 981} 982 983#if __FreeBSD_version >= 400000 984static int cx_detach (device_t dev) 985{ 986 bdrv_t *bd = device_get_softc (dev); 987 cx_board_t *b = bd->board; 988 cx_chan_t *c; 989 int s = splhigh (); 990 991 /* Check if the device is busy (open). */ 992 for (c = b->chan; c < b->chan + NCHAN; ++c) { 993 drv_t *d = (drv_t*) c->sys; 994 995 if (!d || d->chan->type == T_NONE) 996 continue; 997 if (d->lock) { 998 splx (s); 999 return EBUSY; 1000 } 1001 if (c->mode == M_ASYNC && (d->tty.t_state & TS_ISOPEN) && 1002 (d->open_dev|0x2)) { 1003 splx (s); 1004 return EBUSY; 1005 } 1006 if (d->running) { 1007 splx (s); 1008 return EBUSY; 1009 } 1010 } 1011 1012 /* Deactivate the timeout routine. And soft interrupt*/ 1013 if (led_timo[b->num].callout) 1014 untimeout (cx_led_off, b, led_timo[b->num]); 1015 1016 for (c = b->chan; c < b->chan + NCHAN; ++c) { 1017 drv_t *d = c->sys; 1018 1019 if (!d || d->chan->type == T_NONE) 1020 continue; 1021 1022 if (d->dtr_timeout_handle.callout) 1023 untimeout (cx_dtrwakeup, d, d->dtr_timeout_handle); 1024 if (d->dcd_timeout_handle.callout) 1025 untimeout (cx_carrier, c, d->dcd_timeout_handle); 1026 } 1027 bus_teardown_intr (dev, bd->irq_res, bd->intrhand); 1028 bus_deactivate_resource (dev, SYS_RES_IRQ, bd->irq_rid, bd->irq_res); 1029 bus_release_resource (dev, SYS_RES_IRQ, bd->irq_rid, bd->irq_res); 1030 1031 bus_deactivate_resource (dev, SYS_RES_DRQ, bd->drq_rid, bd->drq_res); 1032 bus_release_resource (dev, SYS_RES_DRQ, bd->drq_rid, bd->drq_res); 1033 1034 bus_deactivate_resource (dev, SYS_RES_IOPORT, bd->base_rid, bd->irq_res); 1035 bus_release_resource (dev, SYS_RES_IOPORT, bd->base_rid, bd->base_res); 1036 1037 cx_close_board (b); 1038 1039 /* Detach the interfaces, free buffer memory. */ 1040 for (c = b->chan; c < b->chan + NCHAN; ++c) { 1041 drv_t *d = (drv_t*) c->sys; 1042 1043 if (!d || d->chan->type == T_NONE) 1044 continue; 1045#ifdef NETGRAPH 1046#if __FreeBSD_version >= 500000 1047 if (d->node) { 1048 ng_rmnode_self (d->node); 1049 NG_NODE_UNREF (d->node); 1050 d->node = NULL; 1051 } 1052 mtx_destroy (&d->lo_queue.ifq_mtx); 1053 mtx_destroy (&d->hi_queue.ifq_mtx); 1054#else 1055 ng_rmnode (d->node); 1056 d->node = NULL; 1057#endif 1058#else 1059#if __FreeBSD_version >= 410000 && NBPFILTER > 0 1060 /* Detach from the packet filter list of interfaces. */ 1061 bpfdetach (&d->pp.pp_if); 1062#endif 1063 /* Detach from the sync PPP list. */ 1064 sppp_detach (&d->pp.pp_if); 1065 1066 if_detach (&d->pp.pp_if); 1067#endif 1068 destroy_dev (d->devt[0]); 1069 destroy_dev (d->devt[1]); 1070 destroy_dev (d->devt[2]); 1071 } 1072 1073 cx_led_off (b); 1074 if (led_timo[b->num].callout) 1075 untimeout (cx_led_off, b, led_timo[b->num]); 1076 splx (s); 1077 1078 s = splhigh (); 1079 for (c = b->chan; c < b->chan + NCHAN; ++c) { 1080 drv_t *d = (drv_t*) c->sys; 1081 1082 if (!d || d->chan->type == T_NONE) 1083 continue; 1084 1085 /* Deallocate buffers. */ 1086 contigfree (d, sizeof (*d), M_DEVBUF); 1087 } 1088 bd->board = 0; 1089 adapter [b->num] = 0; 1090 free (b, M_DEVBUF); 1091 splx (s); 1092 1093 return 0; 1094} 1095#endif 1096 1097#ifndef NETGRAPH 1098static void cx_ifstart (struct ifnet *ifp) 1099{ 1100 drv_t *d = ifp->if_softc; 1101 1102 cx_start (d); 1103} 1104 1105static void cx_ifwatchdog (struct ifnet *ifp) 1106{ 1107 drv_t *d = ifp->if_softc; 1108 1109 cx_watchdog (d); 1110} 1111 1112static void cx_tlf (struct sppp *sp) 1113{ 1114 drv_t *d = sp->pp_if.if_softc; 1115 1116 CX_DEBUG (d, ("cx_tlf\n")); 1117/* cx_set_dtr (d->chan, 0);*/ 1118/* cx_set_rts (d->chan, 0);*/ 1119 sp->pp_down (sp); 1120} 1121 1122static void cx_tls (struct sppp *sp) 1123{ 1124 drv_t *d = sp->pp_if.if_softc; 1125 1126 CX_DEBUG (d, ("cx_tls\n")); 1127 sp->pp_up (sp); 1128} 1129 1130/* 1131 * Initialization of interface. 1132 * It seems to be never called by upper level. 1133 */ 1134static void cx_initialize (void *softc) 1135{ 1136 drv_t *d = softc; 1137 1138 CX_DEBUG (d, ("cx_initialize\n")); 1139} 1140 1141/* 1142 * Process an ioctl request. 1143 */ 1144static int cx_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) 1145{ 1146 drv_t *d = ifp->if_softc; 1147 int error, s, was_up, should_be_up; 1148 1149 /* No socket ioctls while the channel is in async mode. */ 1150 if (d->chan->type == T_NONE || d->chan->mode == M_ASYNC) 1151 return EBUSY; 1152 1153 /* Socket ioctls on slave subchannels are not allowed. */ 1154 was_up = (ifp->if_flags & IFF_RUNNING) != 0; 1155 error = sppp_ioctl (ifp, cmd, data); 1156 if (error) 1157 return error; 1158 1159 if (! (ifp->if_flags & IFF_DEBUG)) 1160 d->chan->debug = 0; 1161 else if (! d->chan->debug) 1162 d->chan->debug = 1; 1163 1164 switch (cmd) { 1165 default: CX_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; 1166 case SIOCADDMULTI: CX_DEBUG2 (d, ("SIOCADDMULTI\n")); return 0; 1167 case SIOCDELMULTI: CX_DEBUG2 (d, ("SIOCDELMULTI\n")); return 0; 1168 case SIOCSIFFLAGS: CX_DEBUG2 (d, ("SIOCSIFFLAGS\n")); break; 1169 case SIOCSIFADDR: CX_DEBUG2 (d, ("SIOCSIFADDR\n")); break; 1170 } 1171 1172 /* We get here only in case of SIFFLAGS or SIFADDR. */ 1173 s = splhigh (); 1174 should_be_up = (ifp->if_flags & IFF_RUNNING) != 0; 1175 if (!was_up && should_be_up) { 1176 /* Interface goes up -- start it. */ 1177 cx_up (d); 1178 cx_start (d); 1179 } else if (was_up && !should_be_up) { 1180 /* Interface is going down -- stop it. */ 1181 /* if ((d->pp.pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ 1182 cx_down (d); 1183 } 1184 splx (s); 1185 return 0; 1186} 1187#endif /*NETGRAPH*/ 1188 1189/* 1190 * Stop the interface. Called on splimp(). 1191 */ 1192static void cx_down (drv_t *d) 1193{ 1194 int s = splhigh (); 1195 CX_DEBUG (d, ("cx_down\n")); 1196 cx_set_dtr (d->chan, 0); 1197 cx_set_rts (d->chan, 0); 1198 d->running = 0; 1199 splx (s); 1200} 1201 1202/* 1203 * Start the interface. Called on splimp(). 1204 */ 1205static void cx_up (drv_t *d) 1206{ 1207 int s = splhigh (); 1208 CX_DEBUG (d, ("cx_up\n")); 1209 cx_set_dtr (d->chan, 1); 1210 cx_set_rts (d->chan, 1); 1211 d->running = 1; 1212 splx (s); 1213} 1214 1215/* 1216 * Start output on the (slave) interface. Get another datagram to send 1217 * off of the interface queue, and copy it to the interface 1218 * before starting the output. 1219 */ 1220static void cx_send (drv_t *d) 1221{ 1222 struct mbuf *m; 1223 u_short len; 1224 1225 CX_DEBUG2 (d, ("cx_send\n")); 1226 1227 /* No output if the interface is down. */ 1228 if (! d->running) 1229 return; 1230 1231 /* No output if the modem is off. */ 1232 if (! cx_get_dsr (d->chan) && ! cx_get_loop(d->chan)) 1233 return; 1234 1235 if (cx_buf_free (d->chan)) { 1236 /* Get the packet to send. */ 1237#ifdef NETGRAPH 1238 IF_DEQUEUE (&d->hi_queue, m); 1239 if (! m) 1240 IF_DEQUEUE (&d->lo_queue, m); 1241#else 1242 m = sppp_dequeue (&d->pp.pp_if); 1243#endif 1244 if (! m) 1245 return; 1246#if (__FreeBSD_version >= 400000 || NBPFILTER > 0) && !defined (NETGRAPH) 1247 if (d->pp.pp_if.if_bpf) 1248#if __FreeBSD_version >= 500000 1249 BPF_MTAP (&d->pp.pp_if, m); 1250#else 1251 bpf_mtap (&d->pp.pp_if, m); 1252#endif 1253#endif 1254 len = m->m_pkthdr.len; 1255 if (! m->m_next) 1256 cx_send_packet (d->chan, (u_char*)mtod (m, caddr_t), 1257 len, 0); 1258 else { 1259 u_char buf [DMABUFSZ]; 1260 m_copydata (m, 0, len, buf); 1261 cx_send_packet (d->chan, buf, len, 0); 1262 } 1263 m_freem (m); 1264 1265 /* Set up transmit timeout, 10 seconds. */ 1266#ifdef NETGRAPH 1267 d->timeout = 10; 1268#else 1269 d->pp.pp_if.if_timer = 10; 1270#endif 1271 } 1272#ifndef NETGRAPH 1273 d->pp.pp_if.if_flags |= IFF_OACTIVE; 1274#endif 1275} 1276 1277/* 1278 * Start output on the interface. 1279 * Always called on splimp(). 1280 */ 1281static void cx_start (drv_t *d) 1282{ 1283 int s = splhigh (); 1284 if (d->running) { 1285 if (! d->chan->dtr) 1286 cx_set_dtr (d->chan, 1); 1287 if (! d->chan->rts) 1288 cx_set_rts (d->chan, 1); 1289 cx_send (d); 1290 } 1291 splx (s); 1292} 1293 1294/* 1295 * Handle transmit timeouts. 1296 * Recover after lost transmit interrupts. 1297 * Always called on splimp(). 1298 */ 1299static void cx_watchdog (drv_t *d) 1300{ 1301 int s = splhigh (); 1302 CX_DEBUG (d, ("device timeout\n")); 1303 if (d->running) { 1304 cx_setup_chan (d->chan); 1305 cx_start_chan (d->chan, 0, 0); 1306 cx_set_dtr (d->chan, 1); 1307 cx_set_rts (d->chan, 1); 1308 cx_start (d); 1309 } 1310 splx (s); 1311} 1312 1313/* 1314 * Transmit callback function. 1315 */ 1316static void cx_transmit (cx_chan_t *c, void *attachment, int len) 1317{ 1318 drv_t *d = c->sys; 1319 1320 if (!d) 1321 return; 1322 1323 if (c->mode == M_ASYNC) { 1324 d->tty.t_state &= ~(TS_BUSY | TS_FLUSH); 1325 d->atimeout = 0; 1326 if (d->tty.t_dev) { 1327 d->intr_action |= CX_WRITE; 1328 MY_SOFT_INTR = 1; 1329#if __FreeBSD_version >= 500000 1330 swi_sched (cx_fast_ih, 0); 1331#else 1332 setsofttty (); 1333#endif 1334 } 1335 return; 1336 } 1337#ifdef NETGRAPH 1338 d->timeout = 0; 1339#else 1340 ++d->pp.pp_if.if_opackets; 1341 d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 1342 d->pp.pp_if.if_timer = 0; 1343#endif 1344 cx_start (d); 1345} 1346 1347/* 1348 * Process the received packet. 1349 */ 1350static void cx_receive (cx_chan_t *c, char *data, int len) 1351{ 1352 drv_t *d = c->sys; 1353 struct mbuf *m; 1354 char *cc = data; 1355#if __FreeBSD_version >= 500000 && defined NETGRAPH 1356 int error; 1357#endif 1358 1359 if (!d) 1360 return; 1361 1362 if (c->mode == M_ASYNC) { 1363 if (d->tty.t_state & TS_ISOPEN) { 1364 async_q *q = &d->aqueue; 1365 int size = BF_SZ - 1 - AQ_GSZ (q); 1366 1367 if (len <= 0 && !size) 1368 return; 1369 1370 if (len > size) { 1371 c->ierrs++; 1372 cx_error (c, CX_OVERRUN); 1373 len = size - 1; 1374 } 1375 1376 while (len--) { 1377 AQ_PUSH (q, *(unsigned char *)cc); 1378 cc++; 1379 } 1380 1381 d->intr_action |= CX_READ; 1382 MY_SOFT_INTR = 1; 1383#if __FreeBSD_version >= 500000 1384 swi_sched (cx_fast_ih, 0); 1385#else 1386 setsofttty (); 1387#endif 1388 } 1389 return; 1390 } 1391 if (! d->running) 1392 return; 1393 1394 m = makembuf (data, len); 1395 if (! m) { 1396 CX_DEBUG (d, ("no memory for packet\n")); 1397#ifndef NETGRAPH 1398 ++d->pp.pp_if.if_iqdrops; 1399#endif 1400 return; 1401 } 1402 if (c->debug > 1) 1403 printmbuf (m); 1404#ifdef NETGRAPH 1405 m->m_pkthdr.rcvif = 0; 1406#if __FreeBSD_version >= 500000 1407 NG_SEND_DATA_ONLY (error, d->hook, m); 1408#else 1409 ng_queue_data (d->hook, m, 0); 1410#endif 1411#else 1412 ++d->pp.pp_if.if_ipackets; 1413 m->m_pkthdr.rcvif = &d->pp.pp_if; 1414#if __FreeBSD_version >= 400000 || NBPFILTER > 0 1415 /* Check if there's a BPF listener on this interface. 1416 * If so, hand off the raw packet to bpf. */ 1417 if (d->pp.pp_if.if_bpf) 1418#if __FreeBSD_version >= 500000 1419 BPF_TAP (&d->pp.pp_if, data, len); 1420#else 1421 bpf_tap (&d->pp.pp_if, data, len); 1422#endif 1423#endif 1424 sppp_input (&d->pp.pp_if, m); 1425#endif 1426} 1427 1428#define CONDITION(t,tp) (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))\ 1429 && (!(tp->t_iflag & BRKINT) || (tp->t_iflag & IGNBRK))\ 1430 && (!(tp->t_iflag & PARMRK)\ 1431 || (tp->t_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))\ 1432 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))\ 1433 && linesw[tp->t_line]->l_rint == ttyinput) 1434 1435/* 1436 * Error callback function. 1437 */ 1438static void cx_error (cx_chan_t *c, int data) 1439{ 1440 drv_t *d = c->sys; 1441 async_q *q; 1442 1443 if (!d) 1444 return; 1445 1446 q = &(d->aqueue); 1447 1448 switch (data) { 1449 case CX_FRAME: 1450 CX_DEBUG (d, ("frame error\n")); 1451 if (c->mode == M_ASYNC && (d->tty.t_state & TS_ISOPEN) 1452 && (AQ_GSZ (q) < BF_SZ - 1) 1453 && (!CONDITION((&d->tty.t_termios), (&d->tty)) 1454 || !(d->tty.t_iflag & (IGNPAR | PARMRK)))) { 1455 AQ_PUSH (q, TTY_FE); 1456 d->intr_action |= CX_READ; 1457 MY_SOFT_INTR = 1; 1458#if __FreeBSD_version >= 500000 1459 swi_sched (cx_fast_ih, 0); 1460#else 1461 setsofttty (); 1462#endif 1463 } 1464#ifndef NETGRAPH 1465 else 1466 ++d->pp.pp_if.if_ierrors; 1467#endif 1468 break; 1469 case CX_CRC: 1470 CX_DEBUG (d, ("crc error\n")); 1471 if (c->mode == M_ASYNC && (d->tty.t_state & TS_ISOPEN) 1472 && (AQ_GSZ (q) < BF_SZ - 1) 1473 && (!CONDITION((&d->tty.t_termios), (&d->tty)) 1474 || !(d->tty.t_iflag & INPCK) 1475 || !(d->tty.t_iflag & (IGNPAR | PARMRK)))) { 1476 AQ_PUSH (q, TTY_PE); 1477 d->intr_action |= CX_READ; 1478 MY_SOFT_INTR = 1; 1479#if __FreeBSD_version >= 500000 1480 swi_sched (cx_fast_ih, 0); 1481#else 1482 setsofttty (); 1483#endif 1484 } 1485#ifndef NETGRAPH 1486 else 1487 ++d->pp.pp_if.if_ierrors; 1488#endif 1489 break; 1490 case CX_OVERRUN: 1491 CX_DEBUG (d, ("overrun error\n")); 1492#ifdef TTY_OE 1493 if (c->mode == M_ASYNC && (d->tty.t_state & TS_ISOPEN) 1494 && (AQ_GSZ (q) < BF_SZ - 1) 1495 && (!CONDITION((&d->tty.t_termios), (&d->tty)))) { 1496 AQ_PUSH (q, TTY_OE); 1497 d->intr_action |= CX_READ; 1498 MY_SOFT_INTR = 1; 1499#if __FreeBSD_version >= 500000 1500 swi_sched (cx_fast_ih, 0); 1501#else 1502 setsofttty (); 1503#endif 1504 } 1505#endif 1506#ifndef NETGRAPH 1507 else { 1508 ++d->pp.pp_if.if_collisions; 1509 ++d->pp.pp_if.if_ierrors; 1510 } 1511#endif 1512 break; 1513 case CX_OVERFLOW: 1514 CX_DEBUG (d, ("overflow error\n")); 1515#ifndef NETGRAPH 1516 if (c->mode != M_ASYNC) 1517 ++d->pp.pp_if.if_ierrors; 1518#endif 1519 break; 1520 case CX_UNDERRUN: 1521 CX_DEBUG (d, ("underrun error\n")); 1522 if (c->mode != M_ASYNC) { 1523#ifdef NETGRAPH 1524 d->timeout = 0; 1525#else 1526 ++d->pp.pp_if.if_oerrors; 1527 d->pp.pp_if.if_flags &= ~IFF_OACTIVE; 1528 d->pp.pp_if.if_timer = 0; 1529 cx_start (d); 1530#endif 1531 } 1532 break; 1533 case CX_BREAK: 1534 CX_DEBUG (d, ("break error\n")); 1535 if (c->mode == M_ASYNC && (d->tty.t_state & TS_ISOPEN) 1536 && (AQ_GSZ (q) < BF_SZ - 1) 1537 && (!CONDITION((&d->tty.t_termios), (&d->tty)) 1538 || !(d->tty.t_iflag & (IGNBRK | BRKINT | PARMRK)))) { 1539 AQ_PUSH (q, TTY_BI); 1540 d->intr_action |= CX_READ; 1541 MY_SOFT_INTR = 1; 1542#if __FreeBSD_version >= 500000 1543 swi_sched (cx_fast_ih, 0); 1544#else 1545 setsofttty (); 1546#endif 1547 } 1548#ifndef NETGRAPH 1549 else 1550 ++d->pp.pp_if.if_ierrors; 1551#endif 1552 break; 1553 default: 1554 CX_DEBUG (d, ("error #%d\n", data)); 1555 } 1556} 1557 1558#if __FreeBSD_version < 500000 1559static int cx_open (dev_t dev, int flag, int mode, struct proc *p) 1560#else 1561static int cx_open (dev_t dev, int flag, int mode, struct thread *td) 1562#endif 1563{ 1564 int unit = UNIT (dev); 1565 drv_t *d; 1566 int error; 1567 1568 if (unit >= NCX*NCHAN || ! (d = channel[unit])) 1569 return ENXIO; 1570 CX_DEBUG2 (d, ("cx_open unit=%d, flag=0x%x, mode=0x%x\n", 1571 unit, flag, mode)); 1572 1573 if (d->chan->mode != M_ASYNC || IF_CUNIT(dev)) { 1574 d->open_dev |= 0x1; 1575 return 0; 1576 } 1577#if __FreeBSD_version >= 400000 1578 dev->si_tty = &d->tty; 1579#endif 1580 d->tty.t_dev = dev; 1581again: 1582 if (d->dtroff) { 1583 error = tsleep (&d->dtrwait, TTIPRI | PCATCH, "cxdtr", 0); 1584 if (error) 1585 return error; 1586 goto again; 1587 } 1588 1589 if ((d->tty.t_state & TS_ISOPEN) && (d->tty.t_state & TS_XCLUDE) && 1590#if __FreeBSD_version >= 500000 1591 suser (td)) 1592#else 1593 p->p_ucred->cr_uid != 0) 1594#endif 1595 return EBUSY; 1596 1597 if (d->tty.t_state & TS_ISOPEN) { 1598 /* 1599 * Cannot open /dev/cua if /dev/tty already opened. 1600 */ 1601 if (CALLOUT (dev) && ! d->callout) 1602 return EBUSY; 1603 1604 /* 1605 * Opening /dev/tty when /dev/cua is already opened. 1606 * Wait for close, then try again. 1607 */ 1608 if (! CALLOUT (dev) && d->callout) { 1609 if (flag & O_NONBLOCK) 1610 return EBUSY; 1611 error = tsleep (d, TTIPRI | PCATCH, "cxbi", 0); 1612 if (error) 1613 return error; 1614 goto again; 1615 } 1616 } else if (d->lock && ! CALLOUT (dev) && (flag & O_NONBLOCK)) 1617 /* 1618 * We try to open /dev/tty in non-blocking mode 1619 * while somebody is already waiting for carrier on it. 1620 */ 1621 return EBUSY; 1622 else { 1623 ttychars (&d->tty); 1624 if (d->tty.t_ispeed == 0) { 1625 d->tty.t_iflag = 0; 1626 d->tty.t_oflag = 0; 1627 d->tty.t_lflag = 0; 1628 d->tty.t_cflag = CREAD | CS8 | HUPCL; 1629 d->tty.t_ispeed = d->chan->rxbaud; 1630 d->tty.t_ospeed = d->chan->txbaud; 1631 } 1632 if (CALLOUT (dev)) 1633 d->tty.t_cflag |= CLOCAL; 1634 else 1635 d->tty.t_cflag &= ~CLOCAL; 1636 cx_param (&d->tty, &d->tty.t_termios); 1637 ttsetwater (&d->tty); 1638 } 1639 1640 splhigh (); 1641 if (! (d->tty.t_state & TS_ISOPEN)) { 1642 cx_start_chan (d->chan, 0, 0); 1643 cx_set_dtr (d->chan, 1); 1644 cx_set_rts (d->chan, 1); 1645 d->cd = cx_get_cd (d->chan); 1646 if (CALLOUT (dev) || cx_get_cd (d->chan)) 1647 ttyld_modem(&d->tty, 1); 1648 } 1649 1650 if (! (flag & O_NONBLOCK) && ! (d->tty.t_cflag & CLOCAL) && 1651 ! (d->tty.t_state & TS_CARR_ON)) { 1652 /* Lock the channel against cxconfig while we are 1653 * waiting for carrier. */ 1654 d->lock++; 1655 error = tsleep (&d->tty.t_rawq, TTIPRI | PCATCH, "cxdcd", 0); 1656 /* Unlock the channel. */ 1657 d->lock--; 1658 spl0 (); 1659 if (error) 1660 goto failed; 1661 goto again; 1662 } 1663 1664 error = ttyld_open (&d->tty, dev); 1665 ttyldoptim (&d->tty); 1666 spl0 (); 1667 if (error) { 1668failed: if (! (d->tty.t_state & TS_ISOPEN)) { 1669 splhigh (); 1670 cx_set_dtr (d->chan, 0); 1671 cx_set_rts (d->chan, 0); 1672 if (d->dtrwait) { 1673 d->dtr_timeout_handle = 1674 timeout (cx_dtrwakeup, d, d->dtrwait); 1675 d->dtroff = 1; 1676 } 1677 spl0 (); 1678 } 1679 return error; 1680 } 1681 1682 if (d->tty.t_state & TS_ISOPEN) 1683 d->callout = CALLOUT (dev) ? 1 : 0; 1684 1685 d->open_dev |= 0x2; 1686 CX_DEBUG2 (d, ("cx_open done\n")); 1687 return 0; 1688} 1689 1690#if __FreeBSD_version < 500000 1691static int cx_close (dev_t dev, int flag, int mode, struct proc *p) 1692#else 1693static int cx_close (dev_t dev, int flag, int mode, struct thread *td) 1694#endif 1695{ 1696 drv_t *d = channel [UNIT (dev)]; 1697 int s; 1698 1699 CX_DEBUG2 (d, ("cx_close\n")); 1700 if ((!(d->open_dev&0x2)) || IF_CUNIT(dev)){ 1701 d->open_dev &= ~0x1; 1702 return 0; 1703 } 1704 s = splhigh (); 1705 ttyld_close(&d->tty, flag); 1706 ttyldoptim (&d->tty); 1707 1708 /* Disable receiver. 1709 * Transmitter continues sending the queued data. */ 1710 cx_enable_receive (d->chan, 0); 1711 1712 /* Clear DTR and RTS. */ 1713 if ((d->tty.t_cflag & HUPCL) || ! (d->tty.t_state & TS_ISOPEN)) { 1714 cx_set_dtr (d->chan, 0); 1715 cx_set_rts (d->chan, 0); 1716 if (d->dtrwait) { 1717 d->dtr_timeout_handle = 1718 timeout (cx_dtrwakeup, d, d->dtrwait); 1719 d->dtroff = 1; 1720 } 1721 } 1722 ttyclose (&d->tty); 1723 splx (s); 1724 d->callout = 0; 1725 1726 /* Wake up bidirectional opens. */ 1727 wakeup (d); 1728 d->open_dev &= ~0x2; 1729 1730 return 0; 1731} 1732 1733static int cx_read (dev_t dev, struct uio *uio, int flag) 1734{ 1735 drv_t *d = channel [UNIT (dev)]; 1736 1737 if (d) CX_DEBUG2 (d, ("cx_read\n")); 1738 if (!d || d->chan->mode != M_ASYNC || IF_CUNIT(dev)) 1739 return EBADF; 1740 1741 return ttyld_read (&d->tty, uio, flag); 1742} 1743 1744static int cx_write (dev_t dev, struct uio *uio, int flag) 1745{ 1746 drv_t *d = channel [UNIT (dev)]; 1747 1748 if (d) CX_DEBUG2 (d, ("cx_write\n")); 1749 if (!d || d->chan->mode != M_ASYNC || IF_CUNIT(dev)) 1750 return EBADF; 1751 1752 return ttyld_write (&d->tty, uio, flag); 1753} 1754 1755static int cx_modem_status (drv_t *d) 1756{ 1757 int status = 0, s = splhigh (); 1758 /* Already opened by someone or network interface is up? */ 1759 if ((d->chan->mode == M_ASYNC && (d->tty.t_state & TS_ISOPEN) && 1760 (d->open_dev|0x2)) || (d->chan->mode != M_ASYNC && d->running)) 1761 status = TIOCM_LE; /* always enabled while open */ 1762 1763 if (cx_get_dsr (d->chan)) status |= TIOCM_DSR; 1764 if (cx_get_cd (d->chan)) status |= TIOCM_CD; 1765 if (cx_get_cts (d->chan)) status |= TIOCM_CTS; 1766 if (d->chan->dtr) status |= TIOCM_DTR; 1767 if (d->chan->rts) status |= TIOCM_RTS; 1768 splx (s); 1769 return status; 1770} 1771 1772#if __FreeBSD_version < 500000 1773static int cx_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 1774#else 1775static int cx_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 1776#endif 1777{ 1778 drv_t *d = channel [UNIT (dev)]; 1779 cx_chan_t *c; 1780 struct serial_statistics *st; 1781 int error, s; 1782 char mask[16]; 1783 1784 if (!d || !(c = d->chan)) 1785 return EINVAL; 1786 1787 switch (cmd) { 1788 case SERIAL_GETREGISTERED: 1789 CX_DEBUG2 (d, ("ioctl: getregistered\n")); 1790 bzero (mask, sizeof(mask)); 1791 for (s=0; s<NCX*NCHAN; ++s) 1792 if (channel [s]) 1793 mask [s/8] |= 1 << (s & 7); 1794 bcopy (mask, data, sizeof (mask)); 1795 return 0; 1796 1797 case SERIAL_GETPORT: 1798 CX_DEBUG2 (d, ("ioctl: getport\n")); 1799 s = splhigh (); 1800 *(int *)data = cx_get_port (c); 1801 splx (s); 1802 if (*(int *)data<0) 1803 return (EINVAL); 1804 else 1805 return 0; 1806 1807 case SERIAL_SETPORT: 1808 CX_DEBUG2 (d, ("ioctl: setproto\n")); 1809 /* Only for superuser! */ 1810#if __FreeBSD_version < 400000 1811 error = suser (p->p_ucred, &p->p_acflag); 1812#elif __FreeBSD_version < 500000 1813 error = suser (p); 1814#else /* __FreeBSD_version >= 500000 */ 1815 error = suser (td); 1816#endif /* __FreeBSD_version >= 500000 */ 1817 if (error) 1818 return error; 1819 1820 s = splhigh (); 1821 cx_set_port (c, *(int *)data); 1822 splx (s); 1823 return 0; 1824 1825#ifndef NETGRAPH 1826 case SERIAL_GETPROTO: 1827 CX_DEBUG2 (d, ("ioctl: getproto\n")); 1828 s = splhigh (); 1829 strcpy ((char*)data, (c->mode == M_ASYNC) ? "async" : 1830 (d->pp.pp_flags & PP_FR) ? "fr" : 1831 (d->pp.pp_if.if_flags & PP_CISCO) ? "cisco" : "ppp"); 1832 splx (s); 1833 return 0; 1834 1835 case SERIAL_SETPROTO: 1836 CX_DEBUG2 (d, ("ioctl: setproto\n")); 1837 /* Only for superuser! */ 1838#if __FreeBSD_version < 400000 1839 error = suser (p->p_ucred, &p->p_acflag); 1840#elif __FreeBSD_version < 500000 1841 error = suser (p); 1842#else /* __FreeBSD_version >= 500000 */ 1843 error = suser (td); 1844#endif /* __FreeBSD_version >= 500000 */ 1845 if (error) 1846 return error; 1847 if (c->mode == M_ASYNC) 1848 return EBUSY; 1849 if (d->pp.pp_if.if_flags & IFF_RUNNING) 1850 return EBUSY; 1851 if (! strcmp ("cisco", (char*)data)) { 1852 d->pp.pp_flags &= ~(PP_FR); 1853 d->pp.pp_flags |= PP_KEEPALIVE; 1854 d->pp.pp_if.if_flags |= PP_CISCO; 1855 } else if (! strcmp ("fr", (char*)data)) { 1856 d->pp.pp_if.if_flags &= ~(PP_CISCO); 1857 d->pp.pp_flags |= PP_FR | PP_KEEPALIVE; 1858 } else if (! strcmp ("ppp", (char*)data)) { 1859 d->pp.pp_flags &= ~(PP_FR | PP_KEEPALIVE); 1860 d->pp.pp_if.if_flags &= ~(PP_CISCO); 1861 } else 1862 return EINVAL; 1863 return 0; 1864 1865 case SERIAL_GETKEEPALIVE: 1866 CX_DEBUG2 (d, ("ioctl: getkeepalive\n")); 1867 if ((d->pp.pp_flags & PP_FR) || 1868 (d->pp.pp_if.if_flags & PP_CISCO) || 1869 (c->mode == M_ASYNC)) 1870 return EINVAL; 1871 s = splhigh (); 1872 *(int*)data = (d->pp.pp_flags & PP_KEEPALIVE) ? 1 : 0; 1873 splx (s); 1874 return 0; 1875 1876 case SERIAL_SETKEEPALIVE: 1877 CX_DEBUG2 (d, ("ioctl: setkeepalive\n")); 1878 /* Only for superuser! */ 1879#if __FreeBSD_version < 400000 1880 error = suser (p->p_ucred, &p->p_acflag); 1881#elif __FreeBSD_version < 500000 1882 error = suser (p); 1883#else /* __FreeBSD_version >= 500000 */ 1884 error = suser (td); 1885#endif /* __FreeBSD_version >= 500000 */ 1886 if (error) 1887 return error; 1888 if ((d->pp.pp_flags & PP_FR) || 1889 (d->pp.pp_if.if_flags & PP_CISCO)) 1890 return EINVAL; 1891 s = splhigh (); 1892 if (*(int*)data) 1893 d->pp.pp_flags |= PP_KEEPALIVE; 1894 else 1895 d->pp.pp_flags &= ~PP_KEEPALIVE; 1896 splx (s); 1897 return 0; 1898#endif /*NETGRAPH*/ 1899 1900 case SERIAL_GETMODE: 1901 CX_DEBUG2 (d, ("ioctl: getmode\n")); 1902 s = splhigh (); 1903 *(int*)data = (c->mode == M_ASYNC) ? 1904 SERIAL_ASYNC : SERIAL_HDLC; 1905 splx (s); 1906 return 0; 1907 1908 case SERIAL_SETMODE: 1909 CX_DEBUG2 (d, ("ioctl: setmode\n")); 1910 /* Only for superuser! */ 1911#if __FreeBSD_version < 400000 1912 error = suser (p->p_ucred, &p->p_acflag); 1913#elif __FreeBSD_version < 500000 1914 error = suser (p); 1915#else /* __FreeBSD_version >= 500000 */ 1916 error = suser (td); 1917#endif /* __FreeBSD_version >= 500000 */ 1918 if (error) 1919 return error; 1920 1921 /* Somebody is waiting for carrier? */ 1922 if (d->lock) 1923 return EBUSY; 1924 /* /dev/ttyXX is already opened by someone? */ 1925 if (c->mode == M_ASYNC && (d->tty.t_state & TS_ISOPEN) && 1926 (d->open_dev|0x2)) 1927 return EBUSY; 1928 /* Network interface is up? 1929 * Cannot change to async mode. */ 1930 if (c->mode != M_ASYNC && d->running && 1931 (*(int*)data == SERIAL_ASYNC)) 1932 return EBUSY; 1933 1934 s = splhigh (); 1935 if (c->mode == M_HDLC && *(int*)data == SERIAL_ASYNC) { 1936 cx_set_mode (c, M_ASYNC); 1937 cx_enable_receive (c, 0); 1938 cx_enable_transmit (c, 0); 1939 } else if (c->mode == M_ASYNC && *(int*)data == SERIAL_HDLC) { 1940 cx_set_mode (c, M_HDLC); 1941 cx_enable_receive (c, 1); 1942 cx_enable_transmit (c, 1); 1943 } 1944 splx (s); 1945 return 0; 1946 1947 case SERIAL_GETSTAT: 1948 CX_DEBUG2 (d, ("ioctl: getestat\n")); 1949 st = (struct serial_statistics*) data; 1950 s = splhigh (); 1951 st->rintr = c->rintr; 1952 st->tintr = c->tintr; 1953 st->mintr = c->mintr; 1954 st->ibytes = c->ibytes; 1955 st->ipkts = c->ipkts; 1956 st->ierrs = c->ierrs; 1957 st->obytes = c->obytes; 1958 st->opkts = c->opkts; 1959 st->oerrs = c->oerrs; 1960 splx (s); 1961 return 0; 1962 1963 case SERIAL_CLRSTAT: 1964 CX_DEBUG2 (d, ("ioctl: clrstat\n")); 1965 /* Only for superuser! */ 1966#if __FreeBSD_version < 400000 1967 error = suser (p->p_ucred, &p->p_acflag); 1968#elif __FreeBSD_version < 500000 1969 error = suser (p); 1970#else /* __FreeBSD_version >= 500000 */ 1971 error = suser (td); 1972#endif /* __FreeBSD_version >= 500000 */ 1973 if (error) 1974 return error; 1975 s = splhigh (); 1976 c->rintr = 0; 1977 c->tintr = 0; 1978 c->mintr = 0; 1979 c->ibytes = 0; 1980 c->ipkts = 0; 1981 c->ierrs = 0; 1982 c->obytes = 0; 1983 c->opkts = 0; 1984 c->oerrs = 0; 1985 splx (s); 1986 return 0; 1987 1988 case SERIAL_GETBAUD: 1989 CX_DEBUG2 (d, ("ioctl: getbaud\n")); 1990 if (c->mode == M_ASYNC) 1991 return EINVAL; 1992 s = splhigh (); 1993 *(long*)data = cx_get_baud(c); 1994 splx (s); 1995 return 0; 1996 1997 case SERIAL_SETBAUD: 1998 CX_DEBUG2 (d, ("ioctl: setbaud\n")); 1999 /* Only for superuser! */ 2000#if __FreeBSD_version < 400000 2001 error = suser (p->p_ucred, &p->p_acflag); 2002#elif __FreeBSD_version < 500000 2003 error = suser (p); 2004#else /* __FreeBSD_version >= 500000 */ 2005 error = suser (td); 2006#endif /* __FreeBSD_version >= 500000 */ 2007 if (error) 2008 return error; 2009 if (c->mode == M_ASYNC) 2010 return EINVAL; 2011 s = splhigh (); 2012 cx_set_baud (c, *(long*)data); 2013 splx (s); 2014 return 0; 2015 2016 case SERIAL_GETLOOP: 2017 CX_DEBUG2 (d, ("ioctl: getloop\n")); 2018 if (c->mode == M_ASYNC) 2019 return EINVAL; 2020 s = splhigh (); 2021 *(int*)data = cx_get_loop (c); 2022 splx (s); 2023 return 0; 2024 2025 case SERIAL_SETLOOP: 2026 CX_DEBUG2 (d, ("ioctl: setloop\n")); 2027 /* Only for superuser! */ 2028#if __FreeBSD_version < 400000 2029 error = suser (p->p_ucred, &p->p_acflag); 2030#elif __FreeBSD_version < 500000 2031 error = suser (p); 2032#else /* __FreeBSD_version >= 500000 */ 2033 error = suser (td); 2034#endif /* __FreeBSD_version >= 500000 */ 2035 if (error) 2036 return error; 2037 if (c->mode == M_ASYNC) 2038 return EINVAL; 2039 s = splhigh (); 2040 cx_set_loop (c, *(int*)data); 2041 splx (s); 2042 return 0; 2043 2044 case SERIAL_GETDPLL: 2045 CX_DEBUG2 (d, ("ioctl: getdpll\n")); 2046 if (c->mode == M_ASYNC) 2047 return EINVAL; 2048 s = splhigh (); 2049 *(int*)data = cx_get_dpll (c); 2050 splx (s); 2051 return 0; 2052 2053 case SERIAL_SETDPLL: 2054 CX_DEBUG2 (d, ("ioctl: setdpll\n")); 2055 /* Only for superuser! */ 2056#if __FreeBSD_version < 400000 2057 error = suser (p->p_ucred, &p->p_acflag); 2058#elif __FreeBSD_version < 500000 2059 error = suser (p); 2060#else /* __FreeBSD_version >= 500000 */ 2061 error = suser (td); 2062#endif /* __FreeBSD_version >= 500000 */ 2063 if (error) 2064 return error; 2065 if (c->mode == M_ASYNC) 2066 return EINVAL; 2067 s = splhigh (); 2068 cx_set_dpll (c, *(int*)data); 2069 splx (s); 2070 return 0; 2071 2072 case SERIAL_GETNRZI: 2073 CX_DEBUG2 (d, ("ioctl: getnrzi\n")); 2074 if (c->mode == M_ASYNC) 2075 return EINVAL; 2076 s = splhigh (); 2077 *(int*)data = cx_get_nrzi (c); 2078 splx (s); 2079 return 0; 2080 2081 case SERIAL_SETNRZI: 2082 CX_DEBUG2 (d, ("ioctl: setnrzi\n")); 2083 /* Only for superuser! */ 2084#if __FreeBSD_version < 400000 2085 error = suser (p->p_ucred, &p->p_acflag); 2086#elif __FreeBSD_version < 500000 2087 error = suser (p); 2088#else /* __FreeBSD_version >= 500000 */ 2089 error = suser (td); 2090#endif /* __FreeBSD_version >= 500000 */ 2091 if (error) 2092 return error; 2093 if (c->mode == M_ASYNC) 2094 return EINVAL; 2095 s = splhigh (); 2096 cx_set_nrzi (c, *(int*)data); 2097 splx (s); 2098 return 0; 2099 2100 case SERIAL_GETDEBUG: 2101 CX_DEBUG2 (d, ("ioctl: getdebug\n")); 2102 s = splhigh (); 2103 *(int*)data = c->debug; 2104 splx (s); 2105 return 0; 2106 2107 case SERIAL_SETDEBUG: 2108 CX_DEBUG2 (d, ("ioctl: setdebug\n")); 2109 /* Only for superuser! */ 2110#if __FreeBSD_version < 400000 2111 error = suser (p->p_ucred, &p->p_acflag); 2112#elif __FreeBSD_version < 500000 2113 error = suser (p); 2114#else /* __FreeBSD_version >= 500000 */ 2115 error = suser (td); 2116#endif /* __FreeBSD_version >= 500000 */ 2117 if (error) 2118 return error; 2119 s = splhigh (); 2120 c->debug = *(int*)data; 2121 splx (s); 2122#ifndef NETGRAPH 2123 if (d->chan->debug) 2124 d->pp.pp_if.if_flags |= IFF_DEBUG; 2125 else 2126 d->pp.pp_if.if_flags &= (~IFF_DEBUG); 2127#endif 2128 return 0; 2129 } 2130 2131 if (c->mode == M_ASYNC) { 2132#if __FreeBSD_version >= 502113 2133 error = ttyioctl (dev, cmd, data, flag, td); 2134 ttyldoptim (&d->tty); 2135 if (error != ENOTTY) { 2136 if (error) 2137 CX_DEBUG2 (d, ("ttioctl: 0x%lx, error %d\n", cmd, error)); 2138 return error; 2139 } 2140#else 2141#if __FreeBSD_version >= 500000 2142 error = (*linesw[d->tty.t_line].l_ioctl) (&d->tty, cmd, data, flag, td); 2143#else 2144 error = (*linesw[d->tty.t_line].l_ioctl) (&d->tty, cmd, data, flag, p); 2145#endif 2146 ttyldoptim (&d->tty); 2147 if (error != ENOIOCTL) { 2148 if (error) 2149 CX_DEBUG2 (d, ("l_ioctl: 0x%lx, error %d\n", cmd, error)); 2150 return error; 2151 } 2152 error = ttioctl (&d->tty, cmd, data, flag); 2153 ttyldoptim (&d->tty); 2154 if (error != ENOIOCTL) { 2155 if (error) 2156 CX_DEBUG2 (d, ("ttioctl: 0x%lx, error %d\n", cmd, error)); 2157 return error; 2158 } 2159#endif 2160 } 2161 2162 switch (cmd) { 2163 case TIOCSBRK: /* Start sending line break */ 2164 CX_DEBUG2 (d, ("ioctl: tiocsbrk\n")); 2165 s = splhigh (); 2166 cx_send_break (c, 500); 2167 splx (s); 2168 return 0; 2169 2170 case TIOCCBRK: /* Stop sending line break */ 2171 CX_DEBUG2 (d, ("ioctl: tioccbrk\n")); 2172 return 0; 2173 2174 case TIOCSDTR: /* Set DTR */ 2175 CX_DEBUG2 (d, ("ioctl: tiocsdtr\n")); 2176 s = splhigh (); 2177 cx_set_dtr (c, 1); 2178 splx (s); 2179 return 0; 2180 2181 case TIOCCDTR: /* Clear DTR */ 2182 CX_DEBUG2 (d, ("ioctl: tioccdtr\n")); 2183 s = splhigh (); 2184 cx_set_dtr (c, 0); 2185 splx (s); 2186 return 0; 2187 2188 case TIOCMSET: /* Set DTR/RTS */ 2189 CX_DEBUG2 (d, ("ioctl: tiocmset\n")); 2190 s = splhigh (); 2191 cx_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); 2192 cx_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); 2193 splx (s); 2194 return 0; 2195 2196 case TIOCMBIS: /* Add DTR/RTS */ 2197 CX_DEBUG2 (d, ("ioctl: tiocmbis\n")); 2198 s = splhigh (); 2199 if (*(int*)data & TIOCM_DTR) cx_set_dtr (c, 1); 2200 if (*(int*)data & TIOCM_RTS) cx_set_rts (c, 1); 2201 splx (s); 2202 return 0; 2203 2204 case TIOCMBIC: /* Clear DTR/RTS */ 2205 CX_DEBUG2 (d, ("ioctl: tiocmbic\n")); 2206 s = splhigh (); 2207 if (*(int*)data & TIOCM_DTR) cx_set_dtr (c, 0); 2208 if (*(int*)data & TIOCM_RTS) cx_set_rts (c, 0); 2209 splx (s); 2210 return 0; 2211 2212 case TIOCMGET: /* Get modem status */ 2213 CX_DEBUG2 (d, ("ioctl: tiocmget\n")); 2214 *(int*)data = cx_modem_status (d); 2215 return 0; 2216 2217#ifdef TIOCMSDTRWAIT 2218 case TIOCMSDTRWAIT: 2219 CX_DEBUG2 (d, ("ioctl: tiocmsdtrwait\n")); 2220 /* Only for superuser! */ 2221#if __FreeBSD_version < 400000 2222 error = suser (p->p_ucred, &p->p_acflag); 2223#elif __FreeBSD_version < 500000 2224 error = suser (p); 2225#else /* __FreeBSD_version >= 500000 */ 2226 error = suser (td); 2227#endif /* __FreeBSD_version >= 500000 */ 2228 if (error) 2229 return error; 2230 s = splhigh (); 2231 d->dtrwait = *(int*)data * hz / 100; 2232 splx (s); 2233 return 0; 2234#endif 2235 2236#ifdef TIOCMGDTRWAIT 2237 case TIOCMGDTRWAIT: 2238 CX_DEBUG2 (d, ("ioctl: tiocmgdtrwait\n")); 2239 s = splhigh (); 2240 *(int*)data = d->dtrwait * 100 / hz; 2241 splx (s); 2242 return 0; 2243#endif 2244 } 2245 CX_DEBUG2 (d, ("ioctl: 0x%lx\n", cmd)); 2246 return ENOTTY; 2247} 2248 2249/* 2250 * Wake up opens() waiting for DTR ready. 2251 */ 2252static void cx_dtrwakeup (void *arg) 2253{ 2254 drv_t *d = arg; 2255 2256 d->dtroff = 0; 2257 wakeup (&d->dtrwait); 2258} 2259 2260 2261#if __FreeBSD_version < 502113 2262static void 2263ttyldoptim(tp) 2264 struct tty *tp; 2265{ 2266 struct termios *t; 2267 2268 t = &tp->t_termios; 2269 if (CONDITION(t,tp)) 2270 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2271 else 2272 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2273} 2274#endif 2275 2276#if __FreeBSD_version >= 500000 2277void cx_softintr (void *unused) 2278#else 2279void cx_softintr () 2280#endif 2281{ 2282 drv_t *d; 2283 async_q *q; 2284 int i, s, ic, k; 2285 while (MY_SOFT_INTR) { 2286 MY_SOFT_INTR = 0; 2287 for (i=0; i<NCX*NCHAN; ++i) { 2288 d = channel [i]; 2289 if (!d || !d->chan || d->chan->type == T_NONE 2290 || d->chan->mode != M_ASYNC || !d->tty.t_dev) 2291 continue; 2292 s = splhigh (); 2293 if (d->intr_action & CX_READ) { 2294 q = &(d->aqueue); 2295 if (d->tty.t_state & TS_CAN_BYPASS_L_RINT) { 2296 k = AQ_GSZ(q); 2297 if (d->tty.t_rawq.c_cc + k > 2298 d->tty.t_ihiwat 2299 && (d->tty.t_cflag & CRTS_IFLOW 2300 || d->tty.t_iflag & IXOFF) 2301 && !(d->tty.t_state & TS_TBLOCK)) 2302 ttyblock(&d->tty); 2303 d->tty.t_rawcc += k; 2304 while (k>0) { 2305 k--; 2306 AQ_POP (q, ic); 2307 splx (s); 2308 putc (ic, &d->tty.t_rawq); 2309 s = splhigh (); 2310 } 2311 ttwakeup(&d->tty); 2312 if (d->tty.t_state & TS_TTSTOP 2313 && (d->tty.t_iflag & IXANY 2314 || d->tty.t_cc[VSTART] == 2315 d->tty.t_cc[VSTOP])) { 2316 d->tty.t_state &= ~TS_TTSTOP; 2317 d->tty.t_lflag &= ~FLUSHO; 2318 d->intr_action |= CX_WRITE; 2319 } 2320 } else { 2321 while (q->end != q->beg) { 2322 AQ_POP (q, ic); 2323 splx (s); 2324 ttyld_rint (&d->tty, ic); 2325 s = splhigh (); 2326 } 2327 } 2328 d->intr_action &= ~CX_READ; 2329 } 2330 splx (s); 2331 2332 s = splhigh (); 2333 if (d->intr_action & CX_WRITE) { 2334 if (d->tty.t_line) 2335 ttyld_start (&d->tty); 2336 else 2337 cx_oproc (&d->tty); 2338 d->intr_action &= ~CX_WRITE; 2339 } 2340 splx (s); 2341 2342 } 2343 } 2344} 2345 2346/* 2347 * Fill transmitter buffer with data. 2348 */ 2349static void cx_oproc (struct tty *tp) 2350{ 2351 int s = splhigh (), k; 2352 drv_t *d = channel [UNIT (tp->t_dev)]; 2353 static u_char buf[DMABUFSZ]; 2354 u_char *p; 2355 u_short len = 0, sublen = 0; 2356 2357 if (!d) { 2358 splx (s); 2359 return; 2360 } 2361 2362 CX_DEBUG2 (d, ("cx_oproc\n")); 2363 if (tp->t_cflag & CRTSCTS && (tp->t_state & TS_TBLOCK) && d->chan->rts) 2364 cx_set_rts (d->chan, 0); 2365 else if (tp->t_cflag & CRTSCTS && ! (tp->t_state & TS_TBLOCK) && ! d->chan->rts) 2366 cx_set_rts (d->chan, 1); 2367 2368 if (! (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))) { 2369 /* Start transmitter. */ 2370 cx_enable_transmit (d->chan, 1); 2371 2372 /* Is it busy? */ 2373 if (! cx_buf_free (d->chan)) { 2374 tp->t_state |= TS_BUSY; 2375 splx (s); 2376 return; 2377 } 2378 if (tp->t_iflag & IXOFF) { 2379 p = (buf + (DMABUFSZ/2)); 2380 sublen = q_to_b (&tp->t_outq, p, (DMABUFSZ/2)); 2381 k = sublen; 2382 while (k--) { 2383 /* Send XON/XOFF out of band. */ 2384 if (*p == tp->t_cc[VSTOP]) { 2385 cx_xflow_ctl (d->chan, 0); 2386 p++; 2387 continue; 2388 } 2389 if (*p == tp->t_cc[VSTART]) { 2390 cx_xflow_ctl (d->chan, 1); 2391 p++; 2392 continue; 2393 } 2394 buf[len] = *p; 2395 len++; 2396 p++; 2397 } 2398 } else { 2399 p = buf; 2400 len = q_to_b (&tp->t_outq, p, (DMABUFSZ/2)); 2401 } 2402 if (len) { 2403 cx_send_packet (d->chan, buf, len, 0); 2404 tp->t_state |= TS_BUSY; 2405 d->atimeout = 10; 2406 CX_DEBUG2 (d, ("out %d bytes\n", len)); 2407 } 2408 } 2409 ttwwakeup (tp); 2410 splx (s); 2411} 2412 2413static int cx_param (struct tty *tp, struct termios *t) 2414{ 2415 drv_t *d = channel [UNIT (tp->t_dev)]; 2416 int s, bits, parity; 2417 2418 if (!d) 2419 return EINVAL; 2420 2421 s = splhigh (); 2422 if (t->c_ospeed == 0) { 2423 /* Clear DTR and RTS. */ 2424 cx_set_dtr (d->chan, 0); 2425 splx (s); 2426 CX_DEBUG2 (d, ("cx_param (hangup)\n")); 2427 return 0; 2428 } 2429 CX_DEBUG2 (d, ("cx_param\n")); 2430 2431 /* Check requested parameters. */ 2432 if (t->c_ospeed < 300 || t->c_ospeed > 256*1024) { 2433 splx (s); 2434 return EINVAL; 2435 } 2436 if (t->c_ispeed && (t->c_ispeed < 300 || t->c_ispeed > 256*1024)) { 2437 splx (s); 2438 return EINVAL; 2439 } 2440 2441 /* And copy them to tty and channel structures. */ 2442 tp->t_ispeed = t->c_ispeed = tp->t_ospeed = t->c_ospeed; 2443 tp->t_cflag = t->c_cflag; 2444 2445 /* Set character length and parity mode. */ 2446 switch (t->c_cflag & CSIZE) { 2447 default: 2448 case CS8: bits = 8; break; 2449 case CS7: bits = 7; break; 2450 case CS6: bits = 6; break; 2451 case CS5: bits = 5; break; 2452 } 2453 2454 parity = ((t->c_cflag & PARENB) ? 1 : 0) * 2455 (1 + ((t->c_cflag & PARODD) ? 0 : 1)); 2456 2457 /* Set current channel number. */ 2458 if (! d->chan->dtr) 2459 cx_set_dtr (d->chan, 1); 2460 2461 ttyldoptim (&d->tty); 2462 cx_set_async_param (d->chan, t->c_ospeed, bits, parity, (t->c_cflag & CSTOPB), 2463 !(t->c_cflag & PARENB), (t->c_cflag & CRTSCTS), 2464 (t->c_iflag & IXON), (t->c_iflag & IXANY), 2465 t->c_cc[VSTART], t->c_cc[VSTOP]); 2466 splx (s); 2467 return 0; 2468} 2469 2470#if __FreeBSD_version < 400000 2471static struct tty *cx_devtotty (dev_t dev) 2472{ 2473 int unit = UNIT (dev); 2474 2475 if (unit == UNIT_CTL || unit >= NCX*NCHAN || ! channel[unit]) 2476 return 0; 2477 return &channel[unit]->tty; 2478} 2479#endif 2480 2481/* 2482 * Stop output on a line 2483 */ 2484static void cx_stop (struct tty *tp, int flag) 2485{ 2486 drv_t *d = channel [UNIT (tp->t_dev)]; 2487 int s; 2488 2489 if (!d) 2490 return; 2491 2492 s = splhigh (); 2493 2494 if (tp->t_state & TS_BUSY) { 2495 /* Stop transmitter */ 2496 CX_DEBUG2 (d, ("cx_stop\n")); 2497 cx_transmitter_ctl (d->chan, 0); 2498 } 2499 splx (s); 2500} 2501 2502/* 2503 * Process the (delayed) carrier signal setup. 2504 */ 2505static void cx_carrier (void *arg) 2506{ 2507 drv_t *d = arg; 2508 cx_chan_t *c = d->chan; 2509 int s, cd; 2510 2511 s = splhigh (); 2512 cd = cx_get_cd (c); 2513 if (d->cd != cd) { 2514 if (cd) { 2515 CX_DEBUG (d, ("carrier on\n")); 2516 d->cd = 1; 2517 splx (s); 2518 ttyld_modem(&d->tty, 1); 2519 } else { 2520 CX_DEBUG (d, ("carrier loss\n")); 2521 d->cd = 0; 2522 splx (s); 2523 ttyld_modem(&d->tty, 0); 2524 } 2525 } 2526} 2527 2528/* 2529 * Modem signal callback function. 2530 */ 2531static void cx_modem (cx_chan_t *c) 2532{ 2533 drv_t *d = c->sys; 2534 2535 if (!d || c->mode != M_ASYNC) 2536 return; 2537 /* Handle carrier detect/loss. */ 2538 untimeout (cx_carrier, c, d->dcd_timeout_handle); 2539 /* Carrier changed - delay processing DCD for a while 2540 * to give both sides some time to initialize. */ 2541 d->dcd_timeout_handle = timeout (cx_carrier, d, hz/2); 2542} 2543 2544#if __FreeBSD_version < 400000 2545struct isa_driver cxdriver = { cx_probe, cx_attach, "cx" }; 2546static struct cdevsw cx_cdevsw = { 2547 cx_open, cx_close, cx_read, cx_write, 2548 cx_ioctl, cx_stop, noreset, cx_devtotty, 2549 ttpoll, nommap, NULL, "cx", 2550 NULL, -1, 2551}; 2552#elif __FreeBSD_version < 500000 2553static struct cdevsw cx_cdevsw = { 2554 cx_open, cx_close, cx_read, cx_write, 2555 cx_ioctl, ttypoll, nommap, nostrategy, 2556 "cx", CDEV_MAJOR, nodump, nopsize, 2557 D_TTY, -1 2558}; 2559#elif __FreeBSD_version == 500000 2560static struct cdevsw cx_cdevsw = { 2561 cx_open, cx_close, cx_read, cx_write, 2562 cx_ioctl, ttypoll, nommap, nostrategy, 2563 "cx", CDEV_MAJOR, nodump, nopsize, 2564 D_TTY, 2565 }; 2566#elif __FreeBSD_version <= 501000 2567static struct cdevsw cx_cdevsw = { 2568 .d_open = cx_open, 2569 .d_close = cx_close, 2570 .d_read = cx_read, 2571 .d_write = cx_write, 2572 .d_ioctl = cx_ioctl, 2573 .d_poll = ttypoll, 2574 .d_mmap = nommap, 2575 .d_strategy = nostrategy, 2576 .d_name = "cx", 2577 .d_maj = CDEV_MAJOR, 2578 .d_dump = nodump, 2579 .d_flags = D_TTY, 2580}; 2581#elif __FreeBSD_version < 502103 2582static struct cdevsw cx_cdevsw = { 2583 .d_open = cx_open, 2584 .d_close = cx_close, 2585 .d_read = cx_read, 2586 .d_write = cx_write, 2587 .d_ioctl = cx_ioctl, 2588 .d_poll = ttypoll, 2589 .d_name = "cx", 2590 .d_maj = CDEV_MAJOR, 2591 .d_flags = D_TTY, 2592}; 2593#else /* __FreeBSD_version >= 502103 */ 2594static struct cdevsw cx_cdevsw = { 2595 .d_version = D_VERSION, 2596 .d_open = cx_open, 2597 .d_close = cx_close, 2598 .d_read = cx_read, 2599 .d_write = cx_write, 2600 .d_ioctl = cx_ioctl, 2601 .d_name = "cx", 2602 .d_maj = CDEV_MAJOR, 2603 .d_flags = D_TTY | D_NEEDGIANT, 2604}; 2605#endif 2606 2607#ifdef NETGRAPH 2608#if __FreeBSD_version >= 500000 2609static int ng_cx_constructor (node_p node) 2610{ 2611 drv_t *d = NG_NODE_PRIVATE (node); 2612#else 2613static int ng_cx_constructor (node_p *node) 2614{ 2615 drv_t *d = (*node)->private; 2616#endif 2617 CX_DEBUG (d, ("Constructor\n")); 2618 return EINVAL; 2619} 2620 2621static int ng_cx_newhook (node_p node, hook_p hook, const char *name) 2622{ 2623 int s; 2624#if __FreeBSD_version >= 500000 2625 drv_t *d = NG_NODE_PRIVATE (node); 2626#else 2627 drv_t *d = node->private; 2628#endif 2629 2630 if (d->chan->mode == M_ASYNC) 2631 return EINVAL; 2632 2633 /* Attach debug hook */ 2634 if (strcmp (name, NG_CX_HOOK_DEBUG) == 0) { 2635#if __FreeBSD_version >= 500000 2636 NG_HOOK_SET_PRIVATE (hook, NULL); 2637#else 2638 hook->private = 0; 2639#endif 2640 d->debug_hook = hook; 2641 return 0; 2642 } 2643 2644 /* Check for raw hook */ 2645 if (strcmp (name, NG_CX_HOOK_RAW) != 0) 2646 return EINVAL; 2647 2648#if __FreeBSD_version >= 500000 2649 NG_HOOK_SET_PRIVATE (hook, d); 2650#else 2651 hook->private = d; 2652#endif 2653 d->hook = hook; 2654 s = splhigh (); 2655 cx_up (d); 2656 splx (s); 2657 return 0; 2658} 2659 2660static int print_modems (char *s, cx_chan_t *c, int need_header) 2661{ 2662 int status = cx_modem_status (c->sys); 2663 int length = 0; 2664 2665 if (need_header) 2666 length += sprintf (s + length, " LE DTR DSR RTS CTS CD\n"); 2667 length += sprintf (s + length, "%4s %4s %4s %4s %4s %4s\n", 2668 status & TIOCM_LE ? "On" : "-", 2669 status & TIOCM_DTR ? "On" : "-", 2670 status & TIOCM_DSR ? "On" : "-", 2671 status & TIOCM_RTS ? "On" : "-", 2672 status & TIOCM_CTS ? "On" : "-", 2673 status & TIOCM_CD ? "On" : "-"); 2674 return length; 2675} 2676 2677static int print_stats (char *s, cx_chan_t *c, int need_header) 2678{ 2679 int length = 0; 2680 2681 if (need_header) 2682 length += sprintf (s + length, " Rintr Tintr Mintr Ibytes Ipkts Ierrs Obytes Opkts Oerrs\n"); 2683 length += sprintf (s + length, "%7ld %7ld %7ld %8ld %7ld %7ld %8ld %7ld %7ld\n", 2684 c->rintr, c->tintr, c->mintr, c->ibytes, c->ipkts, 2685 c->ierrs, c->obytes, c->opkts, c->oerrs); 2686 return length; 2687} 2688 2689static int print_chan (char *s, cx_chan_t *c) 2690{ 2691 drv_t *d = c->sys; 2692 int length = 0; 2693 2694 length += sprintf (s + length, "cx%d", c->board->num * NCHAN + c->num); 2695 if (d->chan->debug) 2696 length += sprintf (s + length, " debug=%d", d->chan->debug); 2697 2698 if (cx_get_baud (c)) 2699 length += sprintf (s + length, " %ld", cx_get_baud (c)); 2700 else 2701 length += sprintf (s + length, " extclock"); 2702 2703 if (c->mode == M_HDLC) { 2704 length += sprintf (s + length, " dpll=%s", cx_get_dpll (c) ? "on" : "off"); 2705 length += sprintf (s + length, " nrzi=%s", cx_get_nrzi (c) ? "on" : "off"); 2706 } 2707 2708 length += sprintf (s + length, " loop=%s", cx_get_loop (c) ? "on\n" : "off\n"); 2709 return length; 2710} 2711 2712#if __FreeBSD_version >= 500000 2713static int ng_cx_rcvmsg (node_p node, item_p item, hook_p lasthook) 2714{ 2715 drv_t *d = NG_NODE_PRIVATE (node); 2716 struct ng_mesg *msg; 2717#else 2718static int ng_cx_rcvmsg (node_p node, struct ng_mesg *msg, 2719 const char *retaddr, struct ng_mesg **rptr) 2720{ 2721 drv_t *d = node->private; 2722#endif 2723 struct ng_mesg *resp = NULL; 2724 int error = 0; 2725 2726 if (!d) 2727 return EINVAL; 2728 2729 CX_DEBUG (d, ("Rcvmsg\n")); 2730#if __FreeBSD_version >= 500000 2731 NGI_GET_MSG (item, msg); 2732#endif 2733 switch (msg->header.typecookie) { 2734 default: 2735 error = EINVAL; 2736 break; 2737 2738 case NGM_CX_COOKIE: 2739 printf ("Don't forget to implement\n"); 2740 error = EINVAL; 2741 break; 2742 2743 case NGM_GENERIC_COOKIE: 2744 switch (msg->header.cmd) { 2745 default: 2746 error = EINVAL; 2747 break; 2748 2749 case NGM_TEXT_STATUS: { 2750 char *s; 2751 int l = 0; 2752 int dl = sizeof (struct ng_mesg) + 730; 2753 2754#if __FreeBSD_version >= 500000 2755 NG_MKRESPONSE (resp, msg, dl, M_NOWAIT); 2756 if (! resp) { 2757 error = ENOMEM; 2758 break; 2759 } 2760#else 2761 MALLOC (resp, struct ng_mesg *, dl, 2762 M_NETGRAPH, M_NOWAIT); 2763 if (! resp) { 2764 error = ENOMEM; 2765 break; 2766 } 2767#endif 2768 bzero (resp, dl); 2769 s = (resp)->data; 2770 l += print_chan (s + l, d->chan); 2771 l += print_stats (s + l, d->chan, 1); 2772 l += print_modems (s + l, d->chan, 1); 2773#if __FreeBSD_version < 500000 2774 (resp)->header.version = NG_VERSION; 2775 (resp)->header.arglen = strlen (s) + 1; 2776 (resp)->header.token = msg->header.token; 2777 (resp)->header.typecookie = NGM_CX_COOKIE; 2778 (resp)->header.cmd = msg->header.cmd; 2779#endif 2780 strncpy ((resp)->header.cmdstr, "status", NG_CMDSTRLEN); 2781 } 2782 break; 2783 } 2784 break; 2785 } 2786#if __FreeBSD_version >= 500000 2787 NG_RESPOND_MSG (error, node, item, resp); 2788 NG_FREE_MSG (msg); 2789#else 2790 *rptr = resp; 2791 FREE (msg, M_NETGRAPH); 2792#endif 2793 return error; 2794} 2795 2796#if __FreeBSD_version >= 500000 2797static int ng_cx_rcvdata (hook_p hook, item_p item) 2798{ 2799 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); 2800 struct mbuf *m; 2801 meta_p meta; 2802#else 2803static int ng_cx_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) 2804{ 2805 drv_t *d = hook->node->private; 2806#endif 2807 struct ifqueue *q; 2808 int s; 2809 2810#if __FreeBSD_version >= 500000 2811 NGI_GET_M (item, m); 2812 NGI_GET_META (item, meta); 2813 NG_FREE_ITEM (item); 2814 if (! NG_HOOK_PRIVATE (hook) || ! d) { 2815 NG_FREE_M (m); 2816 NG_FREE_META (meta); 2817#else 2818 if (! hook->private || ! d) { 2819 NG_FREE_DATA (m,meta); 2820#endif 2821 return ENETDOWN; 2822 } 2823 q = (meta && meta->priority > 0) ? &d->hi_queue : &d->lo_queue; 2824 s = splhigh (); 2825#if __FreeBSD_version >= 500000 2826 IF_LOCK (q); 2827 if (_IF_QFULL (q)) { 2828 _IF_DROP (q); 2829 IF_UNLOCK (q); 2830 splx (s); 2831 NG_FREE_M (m); 2832 NG_FREE_META (meta); 2833 return ENOBUFS; 2834 } 2835 _IF_ENQUEUE (q, m); 2836 IF_UNLOCK (q); 2837#else 2838 if (IF_QFULL (q)) { 2839 IF_DROP (q); 2840 splx (s); 2841 NG_FREE_DATA (m, meta); 2842 return ENOBUFS; 2843 } 2844 IF_ENQUEUE (q, m); 2845#endif 2846 cx_start (d); 2847 splx (s); 2848 return 0; 2849} 2850 2851static int ng_cx_rmnode (node_p node) 2852{ 2853#if __FreeBSD_version >= 500000 2854 drv_t *d = NG_NODE_PRIVATE (node); 2855 2856 CX_DEBUG (d, ("Rmnode\n")); 2857 if (d && d->running) { 2858 int s = splhigh (); 2859 cx_down (d); 2860 splx (s); 2861 } 2862#ifdef KLD_MODULE 2863 if (node->nd_flags & NG_REALLY_DIE) { 2864 NG_NODE_SET_PRIVATE (node, NULL); 2865 NG_NODE_UNREF (node); 2866 } 2867 node->nd_flags &= ~NG_INVALID; 2868#endif 2869#else /* __FreeBSD_version < 500000 */ 2870 drv_t *d = node->private; 2871 int s; 2872 2873 s = splhigh (); 2874 cx_down (d); 2875 splx (s); 2876 node->flags |= NG_INVALID; 2877 ng_cutlinks (node); 2878#ifdef KLD_MODULE 2879 ng_unname (node); 2880 ng_unref (node); 2881#else 2882 node->flags &= ~NG_INVALID; 2883#endif 2884#endif 2885 return 0; 2886} 2887 2888static void ng_cx_watchdog (void *arg) 2889{ 2890 drv_t *d = arg; 2891 2892 if (d->timeout == 1) 2893 cx_watchdog (d); 2894 if (d->timeout) 2895 d->timeout--; 2896 d->timeout_handle = timeout (ng_cx_watchdog, d, hz); 2897} 2898 2899static int ng_cx_connect (hook_p hook) 2900{ 2901#if __FreeBSD_version >= 500000 2902 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2903#else 2904 drv_t *d = hook->node->private; 2905#endif 2906 2907 d->timeout_handle = timeout (ng_cx_watchdog, d, hz); 2908 return 0; 2909} 2910 2911static int ng_cx_disconnect (hook_p hook) 2912{ 2913#if __FreeBSD_version >= 500000 2914 drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 2915#else 2916 drv_t *d = hook->node->private; 2917#endif 2918 int s; 2919 2920 s = splhigh (); 2921#if __FreeBSD_version >= 500000 2922 if (NG_HOOK_PRIVATE (hook)) 2923#else 2924 if (hook->private) 2925#endif 2926 cx_down (d); 2927 splx (s); 2928 untimeout (ng_cx_watchdog, d, d->timeout_handle); 2929 return 0; 2930} 2931#endif /*NETGRAPH*/ 2932 2933#ifdef KLD_MODULE 2934#if __FreeBSD_version < 400000 2935/* 2936 * Function called when loading the driver. 2937 */ 2938static int cx_load (void) 2939{ 2940 int i; 2941 2942 for (i=0;i<NCX; ++i) { 2943 struct isa_device id = {-1, &cxdriver, -1, 0, -1, 0, 0, (inthand2_t *)cx_intr, i, 0, 0, 0, 0 ,0 ,1 ,0 ,0}; 2944 2945 disable_intr(); 2946 if (!cx_probe (&id)) { 2947 enable_intr(); 2948 break; 2949 } 2950 cx_attach (&id); 2951 register_intr ((adapter [i])->irq, 0, 0, (inthand2_t*) cx_intr, 2952 &net_imask, id.id_unit); 2953 enable_intr(); 2954 } 2955 if (!i) { 2956 /* Deactivate the timeout routine. And soft interrupt*/ 2957 untimeout (cx_timeout, 0, timeout_handle); 2958 unregister_swi (SWI_TTY, cx_softintr); 2959 return ENXIO; 2960 } 2961 return 0; 2962} 2963 2964/* 2965 * Function called when unloading the driver. 2966 */ 2967static int cx_unload (void) 2968{ 2969 int i, s; 2970 2971 /* Check if the device is busy (open). */ 2972 for (i=0; i<NCX*NCHAN; ++i) { 2973 drv_t *d = channel[i]; 2974 cx_chan_t *c; 2975 2976 if (!d || (c=d->chan)->type == T_NONE) 2977 continue; 2978 if (d->lock) 2979 return EBUSY; 2980 if (c->mode == M_ASYNC && (d->tty.t_state & TS_ISOPEN) && 2981 (d->open_dev|0x2)) 2982 return EBUSY; 2983 if (d->running) 2984 return EBUSY; 2985 2986 } 2987 2988 s = splhigh (); 2989 2990 /* Deactivate the timeout routine. And soft interrupt*/ 2991 for (i=0; i<NCX; ++i) { 2992 cx_board_t *b = adapter [i]; 2993 2994 if (!b || ! b->port) 2995 continue; 2996 untimeout (cx_timeout, 0, timeout_handle); 2997 unregister_swi (SWI_TTY, cx_softintr); 2998 break; 2999 } 3000 3001 for (i=0; i<NCX*NCHAN; ++i) { 3002 drv_t *d = channel[i]; 3003 cx_chan_t *c; 3004 3005 if (!d || (c=d->chan)->type == T_NONE) 3006 continue; 3007 3008 if (d->dtr_timeout_handle.callout) 3009 untimeout (cx_dtrwakeup, d, d->dtr_timeout_handle); 3010 if (d->dcd_timeout_handle.callout) 3011 untimeout (cx_carrier, c, d->dcd_timeout_handle); 3012 } 3013 3014 /* Close all active boards. */ 3015 for (i=0; i<NCX; ++i) { 3016 cx_board_t *b = adapter [i]; 3017 3018 if (!b || ! b->port) 3019 continue; 3020 3021 cx_close_board (b); 3022 } 3023 3024 for (i=0; i<NCX; ++i) { 3025 cx_board_t *b = adapter [i]; 3026 3027 if (!b || ! b->port) 3028 continue; 3029 3030 if (led_timo[i].callout) 3031 untimeout (cx_led_off, b, led_timo[i]); 3032 } 3033 3034 /* OK to unload the driver, unregister the interrupt first. */ 3035 for (i=0; i<NCX; ++i) { 3036 cx_board_t *b = adapter [i]; 3037 3038 if (!b || ! b->port) 3039 continue; 3040 /* Disable the interrupt request. */ 3041 disable_intr(); 3042 unregister_intr (b->irq, (inthand2_t *)cx_intr); 3043 isa_dma_release (b->dma); 3044 enable_intr(); 3045 } 3046 splx (s); 3047 3048 s = splhigh (); 3049 /* Detach the interfaces, free buffer memory. */ 3050 for (i=0; i<NCX*NCHAN; ++i) { 3051 drv_t *d = channel[i]; 3052 cx_chan_t *c; 3053 3054 if (!d || (c=d->chan)->type == T_NONE) 3055 continue; 3056 3057#ifndef NETGRAPH 3058#if NBPFILTER > 0 3059 /* Detach from the packet filter list of interfaces. */ 3060 { 3061 struct bpf_if *q, **b = &bpf_iflist; 3062 3063 while ((q = *b)) { 3064 if (q->bif_ifp == d->pp.pp_if) { 3065 *b = q->bif_next; 3066 free (q, M_DEVBUF); 3067 } 3068 b = &(q->bif_next); 3069 } 3070 } 3071#endif /* NBPFILTER */ 3072 /* Detach from the sync PPP list. */ 3073 sppp_detach (&d->pp.pp_if); 3074 3075 /* Detach from the system list of interfaces. */ 3076 { 3077 struct ifaddr *ifa; 3078 TAILQ_FOREACH (ifa, &d->pp.pp_if.if_addrhead, ifa_link) { 3079 TAILQ_REMOVE (&d->pp.pp_if.if_addrhead, ifa, ifa_link); 3080 free (ifa, M_IFADDR); 3081 } 3082 TAILQ_REMOVE (&ifnet, &d->pp.pp_if, if_link); 3083 } 3084#endif /* !NETGRAPH */ 3085 /* Deallocate buffers. */ 3086/* free (d, M_DEVBUF);*/ 3087 } 3088 3089 for (i=0; i<NCX; ++i) { 3090 cx_board_t *b = adapter [i]; 3091 if (!b) 3092 continue; 3093 adapter [b->num] = 0; 3094 free (b, M_DEVBUF); 3095 } 3096 3097 splx (s); 3098 3099 return 0; 3100} 3101 3102#define devsw(a) cdevsw[major((a))] 3103#endif /* __FreeBSD_version < 400000 */ 3104#endif /* KLD_MODULE */ 3105 3106#if __FreeBSD_version < 400000 3107#ifdef KLD_MODULE 3108static int cx_modevent (module_t mod, int type, void *unused) 3109{ 3110 dev_t dev; 3111 int result; 3112 static int load_count = 0; 3113 3114 dev = makedev (CDEV_MAJOR, 0); 3115 switch (type) { 3116 case MOD_LOAD: 3117 if (devsw(dev)) 3118 return (ENXIO); 3119 load_count ++; 3120 cdevsw_add (&dev, &cx_cdevsw, NULL); 3121 timeout_handle = timeout (cx_timeout, 0, hz*5); 3122 3123 /* Software interrupt. */ 3124 register_swi (SWI_TTY, cx_softintr); 3125 3126 result = cx_load (); 3127 return result; 3128 case MOD_UNLOAD: 3129 result = cx_unload (); 3130 if (result) 3131 return result; 3132 if (devsw(dev)&&!(load_count-1)) { 3133 cdevsw_add (&dev, NULL, NULL); 3134 } 3135 load_count --; 3136 return result; 3137 case MOD_SHUTDOWN: 3138 break; 3139 } 3140 return 0; 3141} 3142#endif /* KLD_MODULE */ 3143#else /* __FreeBSD_version >= 400000 */ 3144static int cx_modevent (module_t mod, int type, void *unused) 3145{ 3146 dev_t dev; 3147 static int load_count = 0; 3148 struct cdevsw *cdsw; 3149 3150#if __FreeBSD_version >= 502103 3151 dev = udev2dev (makeudev(CDEV_MAJOR, 0)); 3152#else 3153 dev = makedev (CDEV_MAJOR, 0); 3154#endif 3155 switch (type) { 3156 case MOD_LOAD: 3157 if (dev != NODEV && 3158 (cdsw = devsw (dev)) && 3159 cdsw->d_maj == CDEV_MAJOR) { 3160 printf ("Sigma driver is already in system\n"); 3161 return (EEXIST); 3162 } 3163#if __FreeBSD_version >= 500000 && defined NETGRAPH 3164 if (ng_newtype (&typestruct)) 3165 printf ("Failed to register ng_cx\n"); 3166#endif 3167 ++load_count; 3168#if __FreeBSD_version <= 500000 3169 cdevsw_add (&cx_cdevsw); 3170#endif 3171 timeout_handle = timeout (cx_timeout, 0, hz*5); 3172 /* Software interrupt. */ 3173#if __FreeBSD_version < 500000 3174 register_swi (SWI_TTY, cx_softintr); 3175#else 3176 swi_add(&tty_ithd, "tty:cx", cx_softintr, NULL, SWI_TTY, 0, 3177 &cx_fast_ih); 3178#endif 3179 break; 3180 case MOD_UNLOAD: 3181 if (load_count == 1) { 3182 printf ("Removing device entry for Sigma\n"); 3183#if __FreeBSD_version <= 500000 3184 cdevsw_remove (&cx_cdevsw); 3185#endif 3186#if __FreeBSD_version >= 500000 && defined NETGRAPH 3187 ng_rmtype (&typestruct); 3188#endif 3189 } 3190 if (timeout_handle.callout) 3191 untimeout (cx_timeout, 0, timeout_handle); 3192#if __FreeBSD_version >= 500000 3193 ithread_remove_handler (cx_fast_ih); 3194#else 3195 unregister_swi (SWI_TTY, cx_softintr); 3196#endif 3197 --load_count; 3198 break; 3199 case MOD_SHUTDOWN: 3200 break; 3201 } 3202 return 0; 3203} 3204#endif /* __FreeBSD_version >= 400000 */ 3205 3206#ifdef NETGRAPH 3207static struct ng_type typestruct = { 3208 .version = NG_ABI_VERSION, 3209 .name = NG_CX_NODE_TYPE, 3210 .constructor = ng_cx_constructor, 3211 .rcvmsg = ng_cx_rcvmsg, 3212 .shutdown = ng_cx_rmnode, 3213 .newhook = ng_cx_newhook, 3214 .connect = ng_cx_connect, 3215 .rcvdata = ng_cx_rcvdata, 3216 .disconnect = ng_cx_disconnect 3217}; 3218 3219#if __FreeBSD_version < 400000 3220NETGRAPH_INIT_ORDERED (cx, &typestruct, SI_SUB_DRIVERS,\ 3221 SI_ORDER_MIDDLE + CDEV_MAJOR); 3222#endif 3223#endif /*NETGRAPH*/ 3224 3225#if __FreeBSD_version >= 500000 3226#ifdef NETGRAPH 3227MODULE_DEPEND (ng_cx, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 3228#else 3229MODULE_DEPEND (isa_cx, sppp, 1, 1, 1); 3230#endif 3231#ifdef KLD_MODULE 3232DRIVER_MODULE (cxmod, isa, cx_isa_driver, cx_devclass, cx_modevent, NULL); 3233#else 3234DRIVER_MODULE (cx, isa, cx_isa_driver, cx_devclass, cx_modevent, NULL); 3235#endif 3236#elif __FreeBSD_version >= 400000 3237#ifdef NETGRAPH 3238DRIVER_MODULE(cx, isa, cx_isa_driver, cx_devclass, ng_mod_event, &typestruct); 3239#else 3240DRIVER_MODULE(cx, isa, cx_isa_driver, cx_devclass, cx_modevent, 0); 3241#endif 3242#else /* __FreeBSD_version < 400000 */ 3243#ifdef KLD_MODULE 3244#ifndef NETGRAPH 3245static moduledata_t cxmod = { "cx", cx_modevent, NULL}; 3246DECLARE_MODULE (cx, cxmod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR); 3247#endif 3248#else /* KLD_MODULE */ 3249 3250/* 3251 * Now for some driver initialisation. 3252 * Occurs ONCE during boot (very early). 3253 * This is if we are NOT a loadable module. 3254 */ 3255static void cx_drvinit (void *unused) 3256{ 3257#if __FreeBSD_version < 400000 3258 dev_t dev; 3259 3260 dev = makedev (CDEV_MAJOR, 0); 3261 cdevsw_add (&dev, &cx_cdevsw, NULL); 3262#else 3263 cdevsw_add (&cx_cdevsw); 3264#endif 3265 3266 /* Activate the timeout routine. */ 3267 timeout_handle = timeout (cx_timeout, 0, hz*5); 3268 3269 /* Software interrupt. */ 3270 register_swi (SWI_TTY, cx_softintr); 3271#ifdef NETGRAPH 3272#if 0 3273 /* Register our node type in netgraph */ 3274 if (ng_newtype (&typestruct)) 3275 printf ("Failed to register ng_cx\n"); 3276#endif 3277#endif 3278} 3279 3280SYSINIT (cxdev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR, cx_drvinit, 0) 3281 3282#endif /* KLD_MODULE */ 3283#endif /* __FreeBSD_version < 400000 */ 3284#endif /* NCX */ 3285