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