160 161#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 162#define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE) 163#define RS_IBUFSIZE 256 164 165#define CALLOUT_MASK 0x80 166#define CONTROL_MASK 0x60 167#define CONTROL_INIT_STATE 0x20 168#define CONTROL_LOCK_STATE 0x40 169#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 170#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 171#define MINOR_TO_UNIT(mynor) ((mynor) & ~MINOR_MAGIC_MASK) 172 173/* 174 * Input buffer watermarks. 175 * The external device is asked to stop sending when the buffer exactly reaches 176 * high water, or when the high level requests it. 177 * The high level is notified immediately (rather than at a later clock tick) 178 * when this watermark is reached. 179 * The buffer size is chosen so the watermark should almost never be reached. 180 * The low watermark is invisibly 0 since the buffer is always emptied all at 181 * once. 182 */ 183#define RS_IHIGHWATER (3 * RS_IBUFSIZE / 4) 184 185/* 186 * com state bits. 187 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 188 * than the other bits so that they can be tested as a group without masking 189 * off the low bits. 190 * 191 * The following com and tty flags correspond closely: 192 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and 193 * siostop()) 194 * CS_TTGO = ~TS_TTSTOP (maintained by comstart() and siostop()) 195 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 196 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 197 * TS_FLUSH is not used. 198 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 199 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 200 */ 201#define CS_BUSY 0x80 /* output in progress */ 202#define CS_TTGO 0x40 /* output not stopped by XOFF */ 203#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 204#define CS_CHECKMSR 1 /* check of MSR scheduled */ 205#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 206#define CS_DTR_OFF 0x10 /* DTR held off */ 207#define CS_ODONE 4 /* output completed */ 208#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 209 210static char const * const error_desc[] = { 211#define CE_OVERRUN 0 212 "silo overflow", 213#define CE_INTERRUPT_BUF_OVERFLOW 1 214 "interrupt-level buffer overflow", 215#define CE_TTY_BUF_OVERFLOW 2 216 "tty-level buffer overflow", 217}; 218 219#define CE_NTYPES 3 220#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 221 222/* types. XXX - should be elsewhere */ 223typedef u_char bool_t; /* boolean */ 224typedef u_char volatile *cy_addr; 225 226/* queue of linear buffers */ 227struct lbq { 228 u_char *l_head; /* next char to process */ 229 u_char *l_tail; /* one past the last char to process */ 230 struct lbq *l_next; /* next in queue */ 231 bool_t l_queued; /* nonzero if queued */ 232}; 233 234/* com device structure */ 235struct com_s { 236 u_char state; /* miscellaneous flag bits */ 237 bool_t active_out; /* nonzero if the callout device is open */ 238#if 0 239 u_char cfcr_image; /* copy of value written to CFCR */ 240 u_char ftl; /* current rx fifo trigger level */ 241 u_char ftl_init; /* ftl_max for next open() */ 242 u_char ftl_max; /* maximum ftl for curent open() */ 243 bool_t hasfifo; /* nonzero for 16550 UARTs */ 244 bool_t loses_outints; /* nonzero if device loses output interrupts */ 245#endif 246 u_char mcr_image; /* copy of value written to MCR */ 247#if 0 248#ifdef COM_MULTIPORT 249 bool_t multiport; /* is this unit part of a multiport device? */ 250#endif /* COM_MULTIPORT */ 251 bool_t no_irq; /* nonzero if irq is not attached */ 252 bool_t poll; /* nonzero if polling is required */ 253 bool_t poll_output; /* nonzero if polling for output is required */ 254#endif 255 int unit; /* unit number */ 256 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 257#if 0 258 u_int tx_fifo_size; 259#endif 260 u_int wopeners; /* # processes waiting for DCD in open() */ 261 262 /* 263 * The high level of the driver never reads status registers directly 264 * because there would be too many side effects to handle conveniently. 265 * Instead, it reads copies of the registers stored here by the 266 * interrupt handler. 267 */ 268 u_char last_modem_status; /* last MSR read by intr handler */ 269 u_char prev_modem_status; /* last MSR handled by high level */ 270 271 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 272 u_char *ibuf; /* start of input buffer */ 273 u_char *ibufend; /* end of input buffer */ 274 u_char *ihighwater; /* threshold in input buffer */ 275 u_char *iptr; /* next free spot in input buffer */ 276 277 struct lbq obufq; /* head of queue of output buffers */ 278 struct lbq obufs[2]; /* output buffers */ 279 280 cy_addr cy_iobase; /* base address of this port's cyclom */ 281 cy_addr iobase; /* base address of this port's cd1400 */ 282 283 struct tty *tp; /* cross reference */ 284 285 /* Initial state. */ 286 struct termios it_in; /* should be in struct tty */ 287 struct termios it_out; 288 289 /* Lock state. */ 290 struct termios lt_in; /* should be in struct tty */ 291 struct termios lt_out; 292 293 bool_t do_timestamp; 294 struct timeval timestamp; 295 296 u_long bytes_in; /* statistics */ 297 u_long bytes_out; 298 u_int delta_error_counts[CE_NTYPES]; 299 u_long error_counts[CE_NTYPES]; 300 301 u_int recv_exception; /* exception chars received */ 302 u_int mdm; /* modem signal changes */ 303#ifdef CyDebug 304 u_int start_count; /* no. of calls to comstart() */ 305 u_int start_real; /* no. of calls that did something */ 306#endif 307 u_char channel_control;/* CD1400 CCR control command shadow */ 308 u_char cor[3]; /* CD1400 COR1-3 shadows */ 309 u_char intr_enable; /* CD1400 SRER shadow */ 310 311 /* 312 * Ping-pong input buffers. The extra factor of 2 in the sizes is 313 * to allow for an error byte for each input byte. 314 */ 315#define CE_INPUT_OFFSET RS_IBUFSIZE 316 u_char ibuf1[2 * RS_IBUFSIZE]; 317 u_char ibuf2[2 * RS_IBUFSIZE]; 318 319 /* 320 * Data area for output buffers. Someday we should build the output 321 * buffer queue without copying data. 322 */ 323 u_char obuf1[256]; 324 u_char obuf2[256]; 325 326 struct kern_devconf kdc; 327}; 328 329/* 330 * XXX public functions in drivers should be declared in headers produced 331 * by `config', not here. 332 */ 333 334/* Interrupt handling entry points. */ 335void siointr __P((int unit)); 336void siointrts __P((int unit)); 337void siopoll __P((void)); 338 339/* Device switch entry points. */ 340int sioopen __P((dev_t dev, int oflags, int devtype, 341 struct proc *p)); 342int sioclose __P((dev_t dev, int fflag, int devtype, 343 struct proc *p)); 344int sioread __P((dev_t dev, struct uio *uio, int ioflag)); 345int siowrite __P((dev_t dev, struct uio *uio, int ioflag)); 346int sioioctl __P((dev_t dev, int cmd, caddr_t data, 347 int fflag, struct proc *p)); 348void siostop __P((struct tty *tp, int rw)); 349#define sioreset noreset 350struct tty *siodevtotty __P((dev_t dev)); 351#define siommap nommap 352#define siostrategy nostrategy 353 354static int sioattach __P((struct isa_device *dev)); 355static void cd1400_channel_cmd __P((cy_addr iobase, int cmd)); 356static timeout_t siodtrwakeup; 357static void comhardclose __P((struct com_s *com)); 358static void siointr1 __P((struct com_s *com)); 359static int commctl __P((struct com_s *com, int bits, int how)); 360static int comparam __P((struct tty *tp, struct termios *t)); 361static int sioprobe __P((struct isa_device *dev)); 362static void sioregisterdev __P((struct isa_device *id)); 363static void siosettimeout __P((void)); 364static int comspeed __P((speed_t speed, int *prescaler_io)); 365static void comstart __P((struct tty *tp)); 366static timeout_t comwakeup; 367static void disc_optim __P((struct tty *tp, struct termios *t, 368 struct com_s *com)); 369 370#ifdef CyDebug 371void cystatus __P((int unit)); 372#endif 373 374/* table and macro for fast conversion from a unit number to its com struct */ 375static struct com_s *p_com_addr[NSIO]; 376#define com_addr(unit) (p_com_addr[unit]) 377 378static struct timeval intr_timestamp; 379 380struct isa_driver siodriver = { 381 sioprobe, sioattach, "cy" 382}; 383 384#ifdef COMCONSOLE 385#undef COMCONSOLE 386#define COMCONSOLE 1 387#else 388#define COMCONSOLE 0 389#endif 390 391#ifndef CONUNIT 392#define CONUNIT (0) 393#endif 394 395static int comconsole = CONUNIT; 396static speed_t comdefaultrate = TTYDEF_SPEED; 397static u_int com_events; /* input chars + weighted output completions */ 398static int commajor; 399static int sio_timeout; 400static int sio_timeouts_until_log; 401#if 0 /* XXX TK2.0 */ 402static struct tty *sio_tty[NSIO]; 403#else 404static struct tty sio_tty[NSIO]; 405static int nsio_tty = NSIO; 406#endif 407 408#ifdef KGDB 409#include <machine/remote-sl.h> 410 411extern int kgdb_dev; 412extern int kgdb_rate; 413extern int kgdb_debug_init; 414#endif 415 416#ifdef CyDebug 417static u_int cd_inbs; 418static u_int cy_inbs; 419static u_int cd_outbs; 420static u_int cy_outbs; 421static u_int cy_svrr_probes; 422static u_int cy_timeouts; 423#endif 424 425static int cy_nr_cd1400s[NCY]; 426#undef RxFifoThreshold 427static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); 428 429static struct kern_devconf kdc_sio[NCY] = { { 430 0, 0, 0, /* filled in by dev_attach */ 431 "cyc", 0, { MDDT_ISA, 0, "tty" }, 432 isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, 433 &kdc_isa0, /* parent */ 434 0, /* parentdata */ 435 DC_UNCONFIGURED, /* state */ 436 "Cyclades multiport board", 437 DC_CLS_MISC /* just an ordinary device */ 438} }; 439 440static void 441sioregisterdev(id) 442 struct isa_device *id; 443{ 444 int unit; 445 446 unit = id->id_unit; 447 if (unit != 0) 448 kdc_sio[unit] = kdc_sio[0]; 449 kdc_sio[unit].kdc_unit = unit; 450 kdc_sio[unit].kdc_isa = id; 451 dev_attach(&kdc_sio[unit]); 452} 453 454static int 455sioprobe(dev) 456 struct isa_device *dev; 457{ 458 int cyu; 459 u_char firmware_version; 460 cy_addr iobase; 461 int unit; 462 463 unit = dev->id_unit; 464 if ((u_int)unit >= NCY) 465 return (0); 466 cy_nr_cd1400s[unit] = 0; 467 sioregisterdev(dev); 468 469 /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ 470 cy_inb((cy_addr)dev->id_maddr, CY16_RESET); /* XXX? */ 471 472 DELAY(500); /* wait for the board to get its act together */ 473 474 for (cyu = 0, iobase = (cy_addr)dev->id_maddr; cyu < CY_MAX_CD1400s; 475 ++cyu, iobase += CY_CD1400_MEMSIZE) { 476 int i; 477 478 /* wait for chip to become ready for new command */ 479 for (i = 0; i < 100; i += 50) { 480 DELAY(50); 481 if (!cd_inb(iobase, CD1400_CCR)) 482 break; 483 } 484 485 /* clear the GFRCR register */ 486 cd_outb(iobase, CD1400_GFRCR, 0); 487 488 /* issue a reset command */ 489 cd_outb(iobase, CD1400_CCR, 490 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 491 492 /* wait for the CD1400 to initialize itself */ 493 for (i = 0; i < 1000; i += 50) { 494 DELAY(50); 495 496 /* retrieve firmware version */ 497 firmware_version = cd_inb(iobase, CD1400_GFRCR); 498 if (firmware_version != 0) 499 break; 500 } 501 502 /* 503 * Anything in the 0x40-0x4F range is fine. 504 * If one CD1400 is bad then we don't support higher 505 * numbered good ones on this board. 506 */ 507 if ((firmware_version & 0xF0) != 0x40) 508 break; 509 ++cy_nr_cd1400s[unit]; 510 } 511 return (cy_nr_cd1400s[unit] == 0 ? 0 : -1); 512} 513 514static int 515sioattach(isdp) 516 struct isa_device *isdp; 517{ 518 int cyu; 519 cy_addr cy_iobase; 520 cy_addr iobase; 521 int ncyu; 522 int unit; 523 524 unit = isdp->id_unit; 525 if ((u_int)unit >= NCY) 526 return (0); 527 ncyu = cy_nr_cd1400s[unit]; 528 if (ncyu == 0) 529 return (0); 530 isdp->id_ri_flags |= RI_FAST; 531 532 cy_iobase = (cy_addr)isdp->id_maddr; 533 unit *= CY_MAX_PORTS; 534 for (cyu = 0, iobase = cy_iobase; cyu < ncyu; 535 ++cyu, iobase += CY_CD1400_MEMSIZE) { 536 int cdu; 537 538 /* Set up a receive timeout period of than 1+ ms. */ 539 cd_outb(iobase, CD1400_PPR, 540 howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000)); 541 542 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { 543 struct com_s *com; 544 int s; 545 546 com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT); 547 if (com == NULL) 548 break; 549 bzero(com, sizeof *com); 550 com->unit = unit; 551 com->dtr_wait = 3 * hz; 552 com->iptr = com->ibuf = com->ibuf1; 553 com->ibufend = com->ibuf1 + RS_IBUFSIZE; 554 com->ihighwater = com->ibuf1 + RS_IHIGHWATER; 555 com->obufs[0].l_head = com->obuf1; 556 com->obufs[1].l_head = com->obuf2; 557 558 com->cy_iobase = cy_iobase; 559 com->iobase = iobase; 560 561 /* 562 * We don't use all the flags from <sys/ttydefaults.h> since they 563 * are only relevant for logins. It's important to have echo off 564 * initially so that the line doesn't start blathering before the 565 * echo flag can be turned off. 566 */ 567 com->it_in.c_iflag = 0; 568 com->it_in.c_oflag = 0; 569 com->it_in.c_cflag = TTYDEF_CFLAG; 570 com->it_in.c_lflag = 0; 571 if (unit == comconsole && (COMCONSOLE || boothowto & RB_SERIAL)) { 572 com->it_in.c_iflag = TTYDEF_IFLAG; 573 com->it_in.c_oflag = TTYDEF_OFLAG; 574 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 575 com->it_in.c_lflag = TTYDEF_LFLAG; 576 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 577 } 578 termioschars(&com->it_in); 579 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 580 com->it_out = com->it_in; 581 582 com->kdc = kdc_sio[0]; 583 com->kdc.kdc_name = "cy"; 584 com->kdc.kdc_unit = unit; 585 com->kdc.kdc_isa = isdp; 586 com->kdc.kdc_parent = &kdc_sio[isdp->id_unit]; 587 com->kdc.kdc_state = DC_IDLE; 588 com->kdc.kdc_description = 589 "Serial port: Cirrus Logic CD1400"; 590 com->kdc.kdc_class = DC_CLS_SERIAL; 591 dev_attach(&com->kdc); 592 593 s = spltty(); 594 com_addr(unit) = com; 595 splx(s); 596 } 597 } 598 kdc_sio[isdp->id_unit].kdc_state = DC_BUSY; /* XXX */ 599 600 /* ensure an edge for the next interrupt */ 601 cy_outb(cy_iobase, CY_CLEAR_INTR, 0); 602 603 return (1); 604} 605 606int 607sioopen(dev, flag, mode, p) 608 dev_t dev; 609 int flag; 610 int mode; 611 struct proc *p; 612{ 613 struct com_s *com; 614 int error; 615 cy_addr iobase; 616 int mynor; 617 int s; 618 struct tty *tp; 619 int unit; 620 621 mynor = minor(dev); 622 unit = MINOR_TO_UNIT(mynor); 623 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) 624 return (ENXIO); 625 if (mynor & CONTROL_MASK) 626 return (0); 627#if 0 /* XXX TK2.0 */ 628 tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]); 629#else 630 tp = com->tp = &sio_tty[unit]; 631#endif 632 s = spltty(); 633 /* 634 * We jump to this label after all non-interrupted sleeps to pick 635 * up any changes of the device state. 636 */ 637open_top: 638 while (com->state & CS_DTR_OFF) { 639 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0); 640 if (error != 0) 641 goto out; 642 } 643 com->kdc.kdc_state = DC_BUSY; 644 if (tp->t_state & TS_ISOPEN) { 645 /* 646 * The device is open, so everything has been initialized. 647 * Handle conflicts. 648 */ 649 if (mynor & CALLOUT_MASK) { 650 if (!com->active_out) { 651 error = EBUSY; 652 goto out; 653 } 654 } else { 655 if (com->active_out) { 656 if (flag & O_NONBLOCK) { 657 error = EBUSY; 658 goto out; 659 } 660 error = tsleep(&com->active_out, 661 TTIPRI | PCATCH, "cybi", 0); 662 if (error != 0) 663 goto out; 664 goto open_top; 665 } 666 } 667 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { 668 error = EBUSY; 669 goto out; 670 } 671 } else { 672 /* 673 * The device isn't open, so there are no conflicts. 674 * Initialize it. Initialization is done twice in many 675 * cases: to preempt sleeping callin opens if we are 676 * callout, and to complete a callin open after DCD rises. 677 */ 678 tp->t_oproc = comstart; 679 tp->t_param = comparam; 680 tp->t_dev = dev; 681 tp->t_termios = mynor & CALLOUT_MASK 682 ? com->it_out : com->it_in; 683#if 0 684 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 685 com->ftl_max = com->ftl_init; 686 com->poll = com->no_irq; 687 com->poll_output = com->loses_outints; 688#endif 689 ++com->wopeners; 690 iobase = com->iobase; 691 692 /* reset this channel */ 693 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 694 cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET); 695 696 /* 697 * Resetting disables the transmitter and receiver as well as 698 * flushing the fifos so some of our cached state becomes 699 * invalid. The documentation suggests that all registers 700 * for the current channel are reset to defaults, but 701 * apparently none are. We wouldn't want DTR cleared. 702 */ 703 com->channel_control = 0; 704 705 /* Encode per-board unit in LIVR for access in intr routines. */ 706 cd_outb(iobase, CD1400_LIVR, 707 (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); 708 709 /* 710 * raise dtr and generally set things up correctly. this 711 * has the side-effect of selecting the appropriate cd1400 712 * channel, to help us with subsequent channel control stuff 713 */ 714 error = comparam(tp, &tp->t_termios); 715 --com->wopeners; 716 if (error != 0) 717 goto out; 718 /* 719 * XXX we should goto open_top if comparam() slept. 720 */ 721 ttsetwater(tp); 722#if 0 723 if (com->hasfifo) { 724 /* 725 * (Re)enable and drain fifos. 726 * 727 * Certain SMC chips cause problems if the fifos 728 * are enabled while input is ready. Turn off the 729 * fifo if necessary to clear the input. We test 730 * the input ready bit after enabling the fifos 731 * since we've already enabled them in comparam() 732 * and to handle races between enabling and fresh 733 * input. 734 */ 735 while (TRUE) { 736 outb(iobase + com_fifo, 737 FIFO_RCV_RST | FIFO_XMT_RST 738 | FIFO_ENABLE | com->ftl); 739 DELAY(100); 740 if (!(inb(com->line_status_port) & LSR_RXRDY)) 741 break; 742 outb(iobase + com_fifo, 0); 743 DELAY(100); 744 (void) inb(com->data_port); 745 } 746 } 747 748 disable_intr(); 749 (void) inb(com->line_status_port); 750 (void) inb(com->data_port); 751 com->prev_modem_status = com->last_modem_status 752 = inb(com->modem_status_port); 753 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS 754 | IER_EMSC); 755 enable_intr(); 756#else /* !0 */ 757 /* XXX raise RTS too */ 758 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 759 disable_intr(); 760 com->prev_modem_status = com->last_modem_status 761 = cd_inb(iobase, CD1400_MSVR2); 762 cd_outb(iobase, CD1400_SRER, 763 com->intr_enable 764 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 765 enable_intr(); 766#endif /* 0 */ 767 /* 768 * Handle initial DCD. Callout devices get a fake initial 769 * DCD (trapdoor DCD). If we are callout, then any sleeping 770 * callin opens get woken up and resume sleeping on "cybi" 771 * instead of "cydcd". 772 */ 773 /* 774 * XXX `mynor & CALLOUT_MASK' should be 775 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 776 * TRAPDOOR_CARRIER is the default initial state for callout 777 * devices and SOFT_CARRIER is like CLOCAL except it hides 778 * the true carrier. 779 */ 780 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 781 (*linesw[tp->t_line].l_modem)(tp, 1); 782 } 783 /* 784 * Wait for DCD if necessary. 785 */ 786 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 787 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 788 ++com->wopeners; 789 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0); 790 --com->wopeners; 791 if (error != 0) 792 goto out; 793 goto open_top; 794 } 795 error = (*linesw[tp->t_line].l_open)(dev, tp); 796 disc_optim(tp, &tp->t_termios, com); 797 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 798 com->active_out = TRUE; 799 siosettimeout(); 800out: 801 splx(s); 802 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 803 comhardclose(com); 804 return (error); 805} 806 807int 808sioclose(dev, flag, mode, p) 809 dev_t dev; 810 int flag; 811 int mode; 812 struct proc *p; 813{ 814 struct com_s *com; 815 int mynor; 816 int s; 817 struct tty *tp; 818 819 mynor = minor(dev); 820 if (mynor & CONTROL_MASK) 821 return (0); 822 com = com_addr(MINOR_TO_UNIT(mynor)); 823 tp = com->tp; 824 s = spltty(); 825 (*linesw[tp->t_line].l_close)(tp, flag); 826 disc_optim(tp, &tp->t_termios, com); 827 siostop(tp, FREAD | FWRITE); 828 comhardclose(com); 829 ttyclose(tp); 830 siosettimeout(); 831 splx(s); 832#ifdef broken /* session holds a ref to the tty; can't deallocate */ 833 ttyfree(tp); 834 com->tp = sio_tty[unit] = NULL; 835#endif 836 return (0); 837} 838 839static void 840comhardclose(com) 841 struct com_s *com; 842{ 843 cy_addr iobase; 844 int s; 845 struct tty *tp; 846 int unit; 847 848 unit = com->unit; 849 iobase = com->iobase; 850 s = spltty(); 851#if 0 852 com->poll = FALSE; 853 com->poll_output = FALSE; 854#endif 855 com->do_timestamp = 0; 856 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 857#if 0 858 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 859#endif 860 861#ifdef KGDB 862 /* do not disable interrupts or hang up if debugging */ 863 if (kgdb_dev != makedev(commajor, unit)) 864#endif 865 { 866#if 0 867 outb(iobase + com_ier, 0); 868#else 869 disable_intr(); 870 cd_outb(iobase, CD1400_SRER, com->intr_enable = 0); 871 enable_intr(); 872#endif 873 tp = com->tp; 874 if (tp->t_cflag & HUPCL 875 /* 876 * XXX we will miss any carrier drop between here and the 877 * next open. Perhaps we should watch DCD even when the 878 * port is closed; it is not sufficient to check it at 879 * the next open because it might go up and down while 880 * we're not watching. 881 */ 882 || !com->active_out 883 && !(com->prev_modem_status & MSR_DCD) 884 && !(com->it_in.c_cflag & CLOCAL) 885 || !(tp->t_state & TS_ISOPEN)) { 886 (void)commctl(com, TIOCM_DTR, DMBIC); 887 888 /* Disable receiver (leave transmitter enabled). */ 889 com->channel_control = CD1400_CCR_CMDCHANCTL 890 | CD1400_CCR_XMTEN 891 | CD1400_CCR_RCVDIS; 892 cd1400_channel_cmd(iobase, com->channel_control); 893 894 if (com->dtr_wait != 0) { 895 timeout(siodtrwakeup, com, com->dtr_wait); 896 com->state |= CS_DTR_OFF; 897 } 898 } 899 } 900 com->active_out = FALSE; 901 wakeup(&com->active_out); 902 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 903 if (!(com->state & CS_DTR_OFF) 904 && !(unit == comconsole && (COMCONSOLE || boothowto & RB_SERIAL))) 905 com->kdc.kdc_state = DC_IDLE; 906 splx(s); 907} 908 909int 910sioread(dev, uio, flag) 911 dev_t dev; 912 struct uio *uio; 913 int flag; 914{ 915 int mynor; 916 struct tty *tp; 917 918 mynor = minor(dev); 919 if (mynor & CONTROL_MASK) 920 return (ENODEV); 921 tp = com_addr(MINOR_TO_UNIT(mynor))->tp; 922 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 923} 924 925int 926siowrite(dev, uio, flag) 927 dev_t dev; 928 struct uio *uio; 929 int flag; 930{ 931 int mynor; 932 struct tty *tp; 933 int unit; 934 935 mynor = minor(dev); 936 if (mynor & CONTROL_MASK) 937 return (ENODEV); 938 939 unit = MINOR_TO_UNIT(mynor); 940 tp = com_addr(unit)->tp; 941 /* 942 * (XXX) We disallow virtual consoles if the physical console is 943 * a serial port. This is in case there is a display attached that 944 * is not the console. In that situation we don't need/want the X 945 * server taking over the console. 946 */ 947 if (constty && unit == comconsole 948 && (COMCONSOLE || boothowto & RB_SERIAL)) 949 constty = NULL; 950#ifdef Smarts 951 /* XXX duplicate ttwrite(), but without so much output processing on 952 * CR & LF chars. Hardly worth the effort, given that high-throughput 953 * sessions are raw anyhow. 954 */ 955#else 956 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 957#endif 958} 959 960static void 961siodtrwakeup(chan) 962 void *chan; 963{ 964 struct com_s *com; 965 966 com = (struct com_s *)chan; 967 com->state &= ~CS_DTR_OFF; 968 if (!(com->unit == comconsole && (COMCONSOLE || boothowto & RB_SERIAL))) 969 com->kdc.kdc_state = DC_IDLE; 970 wakeup(&com->dtr_wait); 971} 972 973/* Interrupt routine for timekeeping purposes */ 974void 975siointrts(unit) 976 int unit; 977{ 978 /* 979 * XXX microtime() reenables CPU interrupts. We can't afford to 980 * be interrupted and don't want to slow down microtime(), so lock 981 * out interrupts in another way. 982 */ 983 outb(IO_ICU1 + 1, 0xff); 984 microtime(&intr_timestamp); 985 disable_intr(); 986 outb(IO_ICU1 + 1, imen); 987 988 siointr(unit); 989} 990 991void 992siointr(unit) 993 int unit; 994{ 995 int baseu; 996 cy_addr cy_iobase; 997 int cyu; 998 cy_addr iobase; 999 u_char status; 1000 1001 baseu = unit * CY_MAX_PORTS; 1002 cy_iobase = com_addr(baseu)->cy_iobase; 1003 1004 /* check each CD1400 in turn */ 1005 for (cyu = 0, iobase = cy_iobase; cyu < cy_nr_cd1400s[unit]; 1006 ++cyu, iobase += CY_CD1400_MEMSIZE) { 1007 /* poll to see if it has any work */ 1008 status = cd_inb(iobase, CD1400_SVRR); 1009 if (status == 0) 1010 continue; 1011#ifdef CyDebug 1012 ++cy_svrr_probes; 1013#endif 1014 /* service requests as appropriate, giving priority to RX */ 1015 if (status & CD1400_SVRR_RXRDY) { 1016 struct com_s *com; 1017 u_int count; 1018 u_char *ioptr; 1019 u_char line_status; 1020 u_char recv_data; 1021 u_char serv_type; 1022#ifdef PollMode 1023 u_char save_car; 1024 u_char save_rir; 1025#endif 1026 1027#ifdef PollMode 1028 save_rir = cd_inb(iobase, CD1400_RIR); 1029 save_car = cd_inb(iobase, CD1400_CAR); 1030 1031 /* enter rx service */ 1032 cd_outb(iobase, CD1400_CAR, save_rir); 1033 1034 serv_type = cd_inb(iobase, CD1400_RIVR); 1035 com = com_addr(baseu 1036 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1037 & CD1400_xIVR_CHAN)); 1038#else 1039 /* ack receive service */ 1040 serv_type = cy_inb(iobase, CY8_SVCACKR); 1041 1042 com = com_addr(baseu + 1043 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1044 & CD1400_xIVR_CHAN)); 1045#endif 1046 1047 if (com->do_timestamp) 1048 /* XXX a little bloat here... */ 1049 com->timestamp = intr_timestamp; 1050 1051 if (serv_type & CD1400_RIVR_EXCEPTION) { 1052 ++com->recv_exception; 1053 line_status = cd_inb(iobase, CD1400_RDSR); 1054 /* break/unnattached error bits or real input? */ 1055 recv_data = cd_inb(iobase, CD1400_RDSR); 1056#ifndef SOFT_HOTCHAR 1057 if (line_status & CD1400_RDSR_SPECIAL 1058 && com->hotchar != 0) 1059 setsofttty(); 1060#endif 1061#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ 1062 if (line_status & (LSR_PE|LSR_FE|LSR_BI)) { 1063 /* 1064 Don't store PE if IGNPAR and BI if IGNBRK, 1065 this hack allows "raw" tty optimization 1066 works even if IGN* is set. 1067 */ 1068 if ( com->tp == NULL 1069 || !(com->tp->t_state & TS_ISOPEN) 1070 || (line_status & (LSR_PE|LSR_FE)) 1071 && (com->tp->t_iflag & IGNPAR) 1072 || (line_status & LSR_BI) 1073 && (com->tp->t_iflag & IGNBRK)) 1074 goto cont; 1075 if ( (line_status & (LSR_PE|LSR_FE)) 1076 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) 1077 && ((line_status & LSR_FE) 1078 || (line_status & LSR_PE) 1079 && (com->tp->t_iflag & INPCK))) 1080 recv_data = 0; 1081 } 1082#endif /* 1 */ 1083 ++com->bytes_in; 1084#ifdef SOFT_HOTCHAR 1085 if (com->hotchar != 0 && recv_data == com->hotchar) 1086 setsofttty(); 1087#endif 1088 ioptr = com->iptr; 1089 if (ioptr >= com->ibufend) 1090 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1091 else { 1092 ++com_events; 1093 ioptr[0] = recv_data; 1094 ioptr[CE_INPUT_OFFSET] = line_status; 1095 com->iptr = ++ioptr; 1096 if (ioptr == com->ihighwater 1097 && com->state & CS_RTS_IFLOW) 1098#if 0 1099 outb(com->modem_ctl_port, 1100 com->mcr_image &= ~MCR_RTS); 1101#else 1102 cd_outb(iobase, CD1400_MSVR1, 1103 com->mcr_image &= ~MCR_RTS); 1104#endif 1105 if (line_status & LSR_OE) 1106 CE_RECORD(com, CE_OVERRUN); 1107 } 1108 goto cont; 1109 } else { 1110 int ifree; 1111 1112 count = cd_inb(iobase, CD1400_RDCR); 1113 com->bytes_in += count; 1114 ioptr = com->iptr; 1115 ifree = com->ibufend - ioptr; 1116 if (count > ifree) { 1117 count -= ifree; 1118 com_events += ifree; 1119 while (ifree-- != 0) { 1120 recv_data = cd_inb(iobase, CD1400_RDSR); 1121#ifdef SOFT_HOTCHAR 1122 if (com->hotchar != 0 1123 && recv_data == com->hotchar) 1124 setsofttty(); 1125#endif 1126 ioptr[0] = recv_data; 1127 ioptr[CE_INPUT_OFFSET] = 0; 1128 ++ioptr; 1129 } 1130 com->delta_error_counts 1131 [CE_INTERRUPT_BUF_OVERFLOW] += count; 1132 do { 1133 recv_data = cd_inb(iobase, CD1400_RDSR); 1134#ifdef SOFT_HOTCHAR 1135 if (com->hotchar != 0 1136 && recv_data == com->hotchar) 1137 setsofttty(); 1138#endif 1139 } while (--count != 0); 1140 } else { 1141 if (ioptr <= com->ihighwater 1142 && ioptr + count > com->ihighwater 1143 && com->state & CS_RTS_IFLOW) 1144#if 0 1145 outb(com->modem_ctl_port, 1146 com->mcr_image &= ~MCR_RTS); 1147#else 1148 cd_outb(iobase, CD1400_MSVR1, 1149 com->mcr_image &= ~MCR_RTS); 1150#endif 1151 com_events += count; 1152 do { 1153 recv_data = cd_inb(iobase, CD1400_RDSR); 1154#ifdef SOFT_HOTCHAR 1155 if (com->hotchar != 0 1156 && recv_data == com->hotchar) 1157 setsofttty(); 1158#endif 1159 ioptr[0] = recv_data; 1160 ioptr[CE_INPUT_OFFSET] = 0; 1161 ++ioptr; 1162 } while (--count != 0); 1163 } 1164 com->iptr = ioptr; 1165 } 1166cont: 1167 1168 /* terminate service context */ 1169#ifdef PollMode 1170 cd_outb(iobase, CD1400_RIR, 1171 save_rir 1172 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); 1173 cd_outb(iobase, CD1400_CAR, save_car); 1174#else 1175 cd_outb(iobase, CD1400_EOSRR, 0); 1176#endif 1177 } 1178 if (status & CD1400_SVRR_MDMCH) { 1179 struct com_s *com; 1180 u_char modem_status; 1181#ifdef PollMode 1182 u_char save_car; 1183 u_char save_mir; 1184#else 1185 u_char vector; 1186#endif 1187 1188#ifdef PollMode 1189 save_mir = cd_inb(iobase, CD1400_MIR); 1190 save_car = cd_inb(iobase, CD1400_CAR); 1191 1192 /* enter modem service */ 1193 cd_outb(iobase, CD1400_CAR, save_mir); 1194 1195 com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS 1196 + (save_mir & CD1400_MIR_CHAN)); 1197#else 1198 /* ack modem service */ 1199 vector = cy_inb(iobase, CY8_SVCACKM); 1200 1201 com = com_addr(baseu 1202 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1203 & CD1400_xIVR_CHAN)); 1204#endif 1205 ++com->mdm; 1206 modem_status = cd_inb(iobase, CD1400_MSVR2); 1207 if (modem_status != com->last_modem_status) { 1208 /* 1209 * Schedule high level to handle DCD changes. Note 1210 * that we don't use the delta bits anywhere. Some 1211 * UARTs mess them up, and it's easy to remember the 1212 * previous bits and calculate the delta. 1213 */ 1214 com->last_modem_status = modem_status; 1215 if (!(com->state & CS_CHECKMSR)) { 1216 com_events += LOTS_OF_EVENTS; 1217 com->state |= CS_CHECKMSR; 1218 setsofttty(); 1219 } 1220 1221#ifdef SOFT_CTS_OFLOW 1222 /* handle CTS change immediately for crisp flow ctl */ 1223 if (com->state & CS_CTS_OFLOW) { 1224 if (modem_status & MSR_CTS) { 1225 com->state |= CS_ODEVREADY; 1226 if (com->state >= (CS_BUSY | CS_TTGO 1227 | CS_ODEVREADY) 1228 && !(com->intr_enable 1229 & CD1400_SRER_TXRDY)) 1230 cd_outb(iobase, CD1400_SRER, 1231 com->intr_enable 1232 |= CD1400_SRER_TXRDY); 1233 } else { 1234 com->state &= ~CS_ODEVREADY; 1235 if (com->intr_enable & CD1400_SRER_TXRDY) 1236 cd_outb(iobase, CD1400_SRER, 1237 com->intr_enable 1238 &= ~CD1400_SRER_TXRDY); 1239 } 1240 } 1241#endif 1242 } 1243 1244 /* terminate service context */ 1245#ifdef PollMode 1246 cd_outb(iobase, CD1400_MIR, 1247 save_mir 1248 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); 1249 cd_outb(iobase, CD1400_CAR, save_car); 1250#else 1251 cd_outb(iobase, CD1400_EOSRR, 0); 1252#endif 1253 } 1254 if (status & CD1400_SVRR_TXRDY) { 1255 struct com_s *com; 1256#ifdef PollMode 1257 u_char save_car; 1258 u_char save_tir; 1259#else 1260 u_char vector; 1261#endif 1262 1263#ifdef PollMode 1264 save_tir = cd_inb(iobase, CD1400_TIR); 1265 save_car = cd_inb(iobase, CD1400_CAR); 1266 1267 /* enter tx service */ 1268 cd_outb(iobase, CD1400_CAR, save_tir); 1269 com = com_addr(baseu 1270 + cyu * CD1400_NO_OF_CHANNELS 1271 + (save_tir & CD1400_TIR_CHAN)); 1272#else 1273 /* ack transmit service */ 1274 vector = cy_inb(iobase, CY8_SVCACKT); 1275 1276 com = com_addr(baseu 1277 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1278 & CD1400_xIVR_CHAN)); 1279#endif 1280 1281 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1282 u_char *ioptr; 1283 u_int ocount; 1284 1285 ioptr = com->obufq.l_head; 1286 ocount = com->obufq.l_tail - ioptr; 1287 if (ocount > CD1400_TX_FIFO_SIZE) 1288 ocount = CD1400_TX_FIFO_SIZE; 1289 com->bytes_out += ocount; 1290 do 1291 cd_outb(iobase, CD1400_TDR, *ioptr++); 1292 while (--ocount != 0); 1293 com->obufq.l_head = ioptr; 1294 if (ioptr >= com->obufq.l_tail) { 1295 struct lbq *qp; 1296 1297 qp = com->obufq.l_next; 1298 qp->l_queued = FALSE; 1299 qp = qp->l_next; 1300 if (qp != NULL) { 1301 com->obufq.l_head = qp->l_head; 1302 com->obufq.l_tail = qp->l_tail; 1303 com->obufq.l_next = qp; 1304 } else { 1305 /* output just completed */ 1306 com->state &= ~CS_BUSY; 1307 cd_outb(iobase, CD1400_SRER, 1308 com->intr_enable 1309 &= ~CD1400_SRER_TXRDY); 1310 } 1311 if (!(com->state & CS_ODONE)) { 1312 com_events += LOTS_OF_EVENTS; 1313 com->state |= CS_ODONE; 1314 setsofttty(); /* handle at high level ASAP */ 1315 } 1316 } 1317 } 1318 1319 /* terminate service context */ 1320#ifdef PollMode 1321 cd_outb(iobase, CD1400_TIR, 1322 save_tir 1323 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); 1324 cd_outb(iobase, CD1400_CAR, save_car); 1325#else 1326 cd_outb(iobase, CD1400_EOSRR, 0); 1327#endif 1328 } 1329 } 1330 1331 /* ensure an edge for the next interrupt */ 1332 cy_outb(cy_iobase, CY_CLEAR_INTR, 0); 1333 1334 schedsofttty(); 1335} 1336 1337static void 1338siointr1(com) 1339 struct com_s *com; 1340{ 1341} 1342 1343int 1344sioioctl(dev, cmd, data, flag, p) 1345 dev_t dev; 1346 int cmd; 1347 caddr_t data; 1348 int flag; 1349 struct proc *p; 1350{ 1351 struct com_s *com; 1352 int error; 1353 cy_addr iobase; 1354 int mynor; 1355 int s; 1356 struct tty *tp; 1357#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1358 int oldcmd; 1359 struct termios term; 1360#endif 1361 1362 mynor = minor(dev); 1363 com = com_addr(MINOR_TO_UNIT(mynor)); 1364 iobase = com->iobase; 1365 if (mynor & CONTROL_MASK) { 1366 struct termios *ct; 1367 1368 switch (mynor & CONTROL_MASK) { 1369 case CONTROL_INIT_STATE: 1370 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 1371 break; 1372 case CONTROL_LOCK_STATE: 1373 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 1374 break; 1375 default: 1376 return (ENODEV); /* /dev/nodev */ 1377 } 1378 switch (cmd) { 1379 case TIOCSETA: 1380 error = suser(p->p_ucred, &p->p_acflag); 1381 if (error != 0) 1382 return (error); 1383 *ct = *(struct termios *)data; 1384 return (0); 1385 case TIOCGETA: 1386 *(struct termios *)data = *ct; 1387 return (0); 1388 case TIOCGETD: 1389 *(int *)data = TTYDISC; 1390 return (0); 1391 case TIOCGWINSZ: 1392 bzero(data, sizeof(struct winsize)); 1393 return (0); 1394 default: 1395 return (ENOTTY); 1396 } 1397 } 1398 tp = com->tp; 1399#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1400 term = tp->t_termios; 1401 oldcmd = cmd; 1402 error = ttsetcompat(tp, &cmd, data, &term); 1403 if (error != 0) 1404 return (error); 1405 if (cmd != oldcmd) 1406 data = (caddr_t)&term; 1407#endif 1408 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1409 int cc; 1410 struct termios *dt = (struct termios *)data; 1411 struct termios *lt = mynor & CALLOUT_MASK 1412 ? &com->lt_out : &com->lt_in; 1413 1414 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1415 | (dt->c_iflag & ~lt->c_iflag); 1416 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1417 | (dt->c_oflag & ~lt->c_oflag); 1418 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1419 | (dt->c_cflag & ~lt->c_cflag); 1420 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1421 | (dt->c_lflag & ~lt->c_lflag); 1422 for (cc = 0; cc < NCCS; ++cc) 1423 if (lt->c_cc[cc] != 0) 1424 dt->c_cc[cc] = tp->t_cc[cc]; 1425 if (lt->c_ispeed != 0) 1426 dt->c_ispeed = tp->t_ispeed; 1427 if (lt->c_ospeed != 0) 1428 dt->c_ospeed = tp->t_ospeed; 1429 } 1430 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1431 if (error >= 0) 1432 return (error); 1433 s = spltty(); 1434 error = ttioctl(tp, cmd, data, flag); 1435 disc_optim(tp, &tp->t_termios, com); 1436 if (error >= 0) { 1437 splx(s); 1438 return (error); 1439 } 1440 cd_outb(iobase, CD1400_CAR, MINOR_TO_UNIT(mynor) & CD1400_CAR_CHAN); 1441 switch (cmd) { 1442#if 0 1443 case TIOCSBRK: 1444 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 1445 break; 1446 case TIOCCBRK: 1447 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1448 break; 1449#endif /* 0 */ 1450 case TIOCSDTR: 1451 (void)commctl(com, TIOCM_DTR, DMBIS); 1452 break; 1453 case TIOCCDTR: 1454 (void)commctl(com, TIOCM_DTR, DMBIC); 1455 break; 1456 case TIOCMSET: 1457 (void)commctl(com, *(int *)data, DMSET); 1458 break; 1459 case TIOCMBIS: 1460 (void)commctl(com, *(int *)data, DMBIS); 1461 break; 1462 case TIOCMBIC: 1463 (void)commctl(com, *(int *)data, DMBIC); 1464 break; 1465 case TIOCMGET: 1466 *(int *)data = commctl(com, 0, DMGET); 1467 break; 1468 case TIOCMSDTRWAIT: 1469 /* must be root since the wait applies to following logins */ 1470 error = suser(p->p_ucred, &p->p_acflag); 1471 if (error != 0) { 1472 splx(s); 1473 return (error); 1474 } 1475 com->dtr_wait = *(int *)data * hz / 100; 1476 break; 1477 case TIOCMGDTRWAIT: 1478 *(int *)data = com->dtr_wait * 100 / hz; 1479 break; 1480 case TIOCTIMESTAMP: 1481 com->do_timestamp = TRUE; 1482 *(struct timeval *)data = com->timestamp; 1483 break; 1484 default: 1485 splx(s); 1486 return (ENOTTY); 1487 } 1488 splx(s); 1489 return (0); 1490} 1491 1492void 1493siopoll() 1494{ 1495 int unit; 1496 1497#ifdef CyDebug 1498 ++cy_timeouts; 1499#endif 1500 if (com_events == 0) 1501 return; 1502repeat: 1503 for (unit = 0; unit < NSIO; ++unit) { 1504 u_char *buf; 1505 struct com_s *com; 1506 u_char *ibuf; 1507 cy_addr iobase; 1508 int incc; 1509 struct tty *tp; 1510 1511 com = com_addr(unit); 1512 if (com == NULL) 1513 continue; 1514 tp = com->tp; 1515 if (tp == NULL) { 1516 /* 1517 * XXX forget any events related to closed devices 1518 * (actually never opened devices) so that we don't 1519 * loop. 1520 */ 1521 disable_intr(); 1522 incc = com->iptr - com->ibuf; 1523 com->iptr = com->ibuf; 1524 if (com->state & CS_CHECKMSR) { 1525 incc += LOTS_OF_EVENTS; 1526 com->state &= ~CS_CHECKMSR; 1527 } 1528 com_events -= incc; 1529 enable_intr(); 1530 if (incc != 0) 1531 log(LOG_DEBUG, 1532 "sio%d: %d events for device with no tp\n", 1533 unit, incc); 1534 continue; 1535 } 1536 1537 /* switch the role of the low-level input buffers */ 1538 if (com->iptr == (ibuf = com->ibuf)) { 1539 buf = NULL; /* not used, but compiler can't tell */ 1540 incc = 0; 1541 } else { 1542 buf = ibuf; 1543 disable_intr(); 1544 incc = com->iptr - buf; 1545 com_events -= incc; 1546 if (ibuf == com->ibuf1) 1547 ibuf = com->ibuf2; 1548 else 1549 ibuf = com->ibuf1; 1550 com->ibufend = ibuf + RS_IBUFSIZE; 1551 com->ihighwater = ibuf + RS_IHIGHWATER; 1552 com->iptr = ibuf; 1553 1554 /* 1555 * There is now room for another low-level buffer full 1556 * of input, so enable RTS if it is now disabled and 1557 * there is room in the high-level buffer. 1558 */ 1559 /* 1560 * XXX this used not to look at CS_RTS_IFLOW. The 1561 * change is to allow full control of MCR_RTS via 1562 * ioctls after turning CS_RTS_IFLOW off. Check 1563 * for races. We shouldn't allow the ioctls while 1564 * CS_RTS_IFLOW is on. 1565 */ 1566 if ((com->state & CS_RTS_IFLOW) 1567 && !(com->mcr_image & MCR_RTS) 1568 && !(tp->t_state & TS_TBLOCK)) 1569#if 0 1570 outb(com->modem_ctl_port, 1571 com->mcr_image |= MCR_RTS); 1572#else 1573 iobase = com->iobase, 1574 cd_outb(iobase, CD1400_CAR, 1575 unit & CD1400_CAR_CHAN), 1576 cd_outb(iobase, CD1400_MSVR1, 1577 com->mcr_image |= MCR_RTS); 1578#endif 1579 enable_intr(); 1580 com->ibuf = ibuf; 1581 } 1582 1583 if (com->state & CS_CHECKMSR) { 1584 u_char delta_modem_status; 1585 1586 disable_intr(); 1587 delta_modem_status = com->last_modem_status 1588 ^ com->prev_modem_status; 1589 com->prev_modem_status = com->last_modem_status; 1590 com_events -= LOTS_OF_EVENTS; 1591 com->state &= ~CS_CHECKMSR; 1592 enable_intr(); 1593 if (delta_modem_status & MSR_DCD) 1594 (*linesw[tp->t_line].l_modem) 1595 (tp, com->prev_modem_status & MSR_DCD); 1596 } 1597 if (com->state & CS_ODONE) { 1598 disable_intr(); 1599 com_events -= LOTS_OF_EVENTS; 1600 com->state &= ~CS_ODONE; 1601 if (!(com->state & CS_BUSY)) 1602 com->tp->t_state &= ~TS_BUSY; 1603 enable_intr(); 1604 (*linesw[tp->t_line].l_start)(tp); 1605 } 1606 if (incc <= 0 || !(tp->t_state & TS_ISOPEN)) 1607 continue; 1608 /* 1609 * XXX only do this when we bypass ttyinput. 1610 */ 1611 if (tp->t_rawq.c_cc + incc >= RB_I_HIGH_WATER 1612 && (com->state & CS_RTS_IFLOW || tp->t_iflag & IXOFF) 1613 && !(tp->t_state & TS_TBLOCK) 1614 /* 1615 * XXX - need flow control for all line disciplines. 1616 * Only have it in standard one now. 1617 */ 1618 && linesw[tp->t_line].l_rint == ttyinput) { 1619 int putc_status = 0; 1620 1621 if ((tp->t_iflag & IXOFF 1622 && tp->t_cc[VSTOP] != _POSIX_VDISABLE 1623 && (putc_status = putc(tp->t_cc[VSTOP], 1624 &tp->t_outq)) == 0) 1625 || com->state & CS_RTS_IFLOW) { 1626 tp->t_state |= TS_TBLOCK; 1627 ttstart(tp); 1628 if (putc_status != 0) 1629 /* Try again later. */ 1630 tp->t_state &= ~TS_TBLOCK; 1631 } 1632 } 1633 /* 1634 * Avoid the grotesquely inefficient lineswitch routine 1635 * (ttyinput) in "raw" mode. It usually takes about 450 1636 * instructions (that's without canonical processing or echo!). 1637 * slinput is reasonably fast (usually 40 instructions plus 1638 * call overhead). 1639 */ 1640 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 1641 tk_nin += incc; 1642 tk_rawcc += incc; 1643 tp->t_rawcc += incc; 1644 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 1645 += b_to_q((char *)buf, incc, &tp->t_rawq); 1646 ttwakeup(tp); 1647 if (tp->t_state & TS_TTSTOP 1648 && (tp->t_iflag & IXANY 1649 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 1650 tp->t_state &= ~TS_TTSTOP; 1651 tp->t_lflag &= ~FLUSHO; 1652 ttstart(tp); 1653 } 1654 } else { 1655 do { 1656 u_char line_status; 1657 int recv_data; 1658 1659 line_status = (u_char) buf[CE_INPUT_OFFSET]; 1660 recv_data = (u_char) *buf++; 1661 if (line_status 1662 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 1663 if (line_status & LSR_BI) 1664 recv_data |= TTY_BI; 1665 if (line_status & LSR_FE) 1666 recv_data |= TTY_FE; 1667 if (line_status & LSR_OE) 1668 recv_data |= TTY_OE; 1669 if (line_status & LSR_PE) 1670 recv_data |= TTY_PE; 1671 } 1672 (*linesw[tp->t_line].l_rint)(recv_data, tp); 1673 } while (--incc > 0); 1674 } 1675 if (com_events == 0) 1676 break; 1677 } 1678 if (com_events >= LOTS_OF_EVENTS) 1679 goto repeat; 1680} 1681 1682static int 1683comparam(tp, t) 1684 struct tty *tp; 1685 struct termios *t; 1686{ 1687 int bits; 1688 int cflag; 1689 struct com_s *com; 1690 u_char cor_change; 1691 int idivisor; 1692 int iflag; 1693 cy_addr iobase; 1694 int iprescaler; 1695 int itimeout; 1696 int odivisor; 1697 int oprescaler; 1698 u_char opt; 1699 int s; 1700 int unit; 1701 1702 /* do historical conversions */ 1703 if (t->c_ispeed == 0) 1704 t->c_ispeed = t->c_ospeed; 1705 1706 /* check requested parameters */ 1707 idivisor = comspeed(t->c_ispeed, &iprescaler); 1708 if (idivisor < 0) 1709 return (EINVAL); 1710 odivisor = comspeed(t->c_ospeed, &oprescaler); 1711 if (odivisor < 0) 1712 return (EINVAL); 1713 1714 /* parameters are OK, convert them to the com struct and the device */ 1715 unit = DEV_TO_UNIT(tp->t_dev); 1716 com = com_addr(unit); 1717 iobase = com->iobase; 1718 s = spltty(); 1719 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 1720 if (odivisor == 0) 1721 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 1722 else 1723 (void)commctl(com, TIOCM_DTR, DMBIS); 1724 1725 cd_outb(iobase, CD1400_RBPR, idivisor); 1726 cd_outb(iobase, CD1400_RCOR, iprescaler); 1727 cd_outb(iobase, CD1400_TBPR, odivisor); 1728 cd_outb(iobase, CD1400_TCOR, oprescaler); 1729 1730 /* 1731 * channel control 1732 * receiver enable 1733 * transmitter enable (always set) 1734 */ 1735 cflag = t->c_cflag; 1736 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 1737 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 1738 if (opt != com->channel_control) { 1739 com->channel_control = opt; 1740 cd1400_channel_cmd(iobase, opt); 1741 } 1742 1743#ifdef Smarts 1744 /* set special chars */ 1745 /* XXX if one is _POSIX_VDISABLE, can't use some others */ 1746 if (t->c_cc[VSTOP] != _POSIX_VDISABLE) 1747 cd_outb(iobase, CD1400_SCHR1, t->c_cc[VSTOP]); 1748 if (t->c_cc[VSTART] != _POSIX_VDISABLE) 1749 cd_outb(iobase, CD1400_SCHR2, t->c_cc[VSTART]); 1750 if (t->c_cc[VINTR] != _POSIX_VDISABLE) 1751 cd_outb(iobase, CD1400_SCHR3, t->c_cc[VINTR]); 1752 if (t->c_cc[VSUSP] != _POSIX_VDISABLE) 1753 cd_outb(iobase, CD1400_SCHR4, t->c_cc[VSUSP]); 1754#endif 1755 1756 /* 1757 * set channel option register 1 - 1758 * parity mode 1759 * stop bits 1760 * char length 1761 */ 1762 opt = 0; 1763 /* parity */ 1764 if (cflag & PARENB) { 1765 if (cflag & PARODD) 1766 opt |= CD1400_COR1_PARODD; 1767 opt |= CD1400_COR1_PARNORMAL; 1768 } 1769 iflag = t->c_iflag; 1770 if (!(iflag & INPCK)) 1771 opt |= CD1400_COR1_NOINPCK; 1772 bits = 1 + 1; 1773 /* stop bits */ 1774 if (cflag & CSTOPB) { 1775 ++bits; 1776 opt |= CD1400_COR1_STOP2; 1777 } 1778 /* char length */ 1779 switch (cflag & CSIZE) { 1780 case CS5: 1781 bits += 5; 1782 opt |= CD1400_COR1_CS5; 1783 break; 1784 case CS6: 1785 bits += 6; 1786 opt |= CD1400_COR1_CS6; 1787 break; 1788 case CS7: 1789 bits += 7; 1790 opt |= CD1400_COR1_CS7; 1791 break; 1792 default: 1793 bits += 8; 1794 opt |= CD1400_COR1_CS8; 1795 break; 1796 } 1797 cor_change = 0; 1798 if (opt != com->cor[0]) { 1799 cor_change |= CD1400_CCR_COR1; 1800 cd_outb(iobase, CD1400_COR1, com->cor[0] = opt); 1801 } 1802 1803 /* 1804 * Set receive time-out period, normally to max(one char time, 5 ms). 1805 */ 1806 if (t->c_ispeed == 0) 1807 itimeout = cd_inb(iobase, CD1400_RTPR); 1808 else { 1809 itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; 1810#ifdef SOFT_HOTCHAR 1811#define MIN_RTP 1 1812#else 1813#define MIN_RTP 5 1814#endif 1815 if (itimeout < MIN_RTP) 1816 itimeout = MIN_RTP; 1817 } 1818 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 1819 && t->c_cc[VTIME] * 10 > itimeout) 1820 itimeout = t->c_cc[VTIME] * 10; 1821 if (itimeout > 255) 1822 itimeout = 255; 1823 cd_outb(iobase, CD1400_RTPR, itimeout); 1824 1825 /* 1826 * set channel option register 2 - 1827 * flow control 1828 */ 1829 opt = 0; 1830#ifdef Smarts 1831 if (iflag & IXANY) 1832 opt |= CD1400_COR2_IXANY; 1833 if (iflag & IXOFF) 1834 opt |= CD1400_COR2_IXOFF; 1835#endif 1836#ifndef SOFT_CTS_OFLOW 1837 if (cflag & CCTS_OFLOW) 1838 opt |= CD1400_COR2_CCTS_OFLOW; 1839#endif 1840 if (opt != com->cor[1]) { 1841 cor_change |= CD1400_CCR_COR2; 1842 cd_outb(iobase, CD1400_COR2, com->cor[1] = opt); 1843 } 1844 1845 /* 1846 * set channel option register 3 - 1847 * receiver FIFO interrupt threshold 1848 * flow control 1849 */ 1850 opt = RxFifoThreshold; 1851#ifdef Smarts 1852 if (t->c_lflag & ICANON) 1853 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 1854 if (iflag & IXOFF) 1855 /* detect and transparently handle START and STOP chars */ 1856 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 1857#endif 1858 if (opt != com->cor[2]) { 1859 cor_change |= CD1400_CCR_COR3; 1860 cd_outb(iobase, CD1400_COR3, com->cor[2] = opt); 1861 } 1862 1863 /* notify the CD1400 if COR1-3 have changed */ 1864 if (cor_change) 1865 cd1400_channel_cmd(iobase, CD1400_CCR_CMDCORCHG | cor_change); 1866 1867 /* 1868 * set channel option register 4 - 1869 * CR/NL processing 1870 * break processing 1871 * received exception processing 1872 */ 1873 opt = 0; 1874 if (iflag & IGNCR) 1875 opt |= CD1400_COR4_IGNCR; 1876#ifdef Smarts 1877 /* 1878 * we need a new ttyinput() for this, as we don't want to 1879 * have ICRNL && INLCR being done in both layers, or to have 1880 * synchronisation problems 1881 */ 1882 if (iflag & ICRNL) 1883 opt |= CD1400_COR4_ICRNL; 1884 if (iflag & INLCR) 1885 opt |= CD1400_COR4_INLCR; 1886#endif 1887 if (iflag & IGNBRK) 1888 opt |= CD1400_COR4_IGNBRK; 1889 if (!(iflag & BRKINT)) 1890 opt |= CD1400_COR4_NOBRKINT; 1891#if 0 1892 /* XXX using this "intelligence" breaks reporting of overruns. */ 1893 if (iflag & IGNPAR) 1894 opt |= CD1400_COR4_PFO_DISCARD; 1895 else { 1896 if (iflag & PARMRK) 1897 opt |= CD1400_COR4_PFO_ESC; 1898 else 1899 opt |= CD1400_COR4_PFO_NUL; 1900 } 1901#else 1902 opt |= CD1400_COR4_PFO_EXCEPTION; 1903#endif 1904 cd_outb(iobase, CD1400_COR4, opt); 1905 1906 /* 1907 * set channel option register 5 - 1908 */ 1909 opt = 0; 1910 if (iflag & ISTRIP) 1911 opt |= CD1400_COR5_ISTRIP; 1912 if (t->c_iflag & IEXTEN) 1913 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 1914 opt |= CD1400_COR5_LNEXT; 1915#ifdef Smarts 1916 if (t->c_oflag & ONLCR) 1917 opt |= CD1400_COR5_ONLCR; 1918 if (t->c_oflag & OCRNL) 1919 opt |= CD1400_COR5_OCRNL; 1920#endif 1921 cd_outb(iobase, CD1400_COR5, opt); 1922 1923 /* 1924 * XXX we probably alway want to track carrier changes, so that 1925 * TS_CARR_ON gives the true carrier. If we don't track them, 1926 * then we should set TS_CARR_ON when CLOCAL drops. 1927 */ 1928 /* 1929 * set modem change option register 1 1930 * generate modem interrupts on which 1 -> 0 input transitions 1931 * also controls auto-DTR output flow-control, which we don't use 1932 */ 1933 opt = cflag & CLOCAL ? 0 : CD1400_MCOR1_CDzd; 1934#ifdef SOFT_CTS_OFLOW 1935 if (cflag & CCTS_OFLOW) 1936 opt |= CD1400_MCOR1_CTSzd; 1937#endif 1938 cd_outb(iobase, CD1400_MCOR1, opt); 1939 1940 /* 1941 * set modem change option register 2 1942 * generate modem interrupts on specific 0 -> 1 input transitions 1943 */ 1944 opt = cflag & CLOCAL ? 0 : CD1400_MCOR2_CDod; 1945#ifdef SOFT_CTS_OFLOW 1946 if (cflag & CCTS_OFLOW) 1947 opt |= CD1400_MCOR2_CTSod; 1948#endif 1949 cd_outb(iobase, CD1400_MCOR2, opt); 1950 1951 /* 1952 * XXX should have done this long ago, but there is too much state 1953 * to change all atomically. 1954 */ 1955 disable_intr(); 1956 1957 com->state &= ~CS_TTGO; 1958 if (!(tp->t_state & TS_TTSTOP)) 1959 com->state |= CS_TTGO; 1960 if (cflag & CRTS_IFLOW) 1961 com->state |= CS_RTS_IFLOW; /* XXX - secondary changes? */ 1962 else 1963 com->state &= ~CS_RTS_IFLOW; 1964 1965 /* 1966 * Set up state to handle output flow control. 1967 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 1968 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 1969 */ 1970 com->state |= CS_ODEVREADY; 1971#ifdef SOFT_CTS_OFLOW 1972 com->state &= ~CS_CTS_OFLOW; 1973 if (cflag & CCTS_OFLOW) { 1974 com->state |= CS_CTS_OFLOW; 1975 if (!(com->last_modem_status & MSR_CTS)) 1976 com->state &= ~CS_ODEVREADY; 1977 } 1978#endif 1979 /* XXX shouldn't call functions while intrs are disabled. */ 1980 disc_optim(tp, t, com); 1981#if 0 1982 /* 1983 * Recover from fiddling with CS_TTGO. We used to call siointr1() 1984 * unconditionally, but that defeated the careful discarding of 1985 * stale input in sioopen(). 1986 */ 1987 if (com->state >= (CS_BUSY | CS_TTGO)) 1988 siointr1(com); 1989#endif 1990 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1991 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 1992 cd_outb(iobase, CD1400_SRER, 1993 com->intr_enable |= CD1400_SRER_TXRDY); 1994 } else { 1995 if (com->intr_enable & CD1400_SRER_TXRDY) 1996 cd_outb(iobase, CD1400_SRER, 1997 com->intr_enable &= ~CD1400_SRER_TXRDY); 1998 } 1999 2000 enable_intr(); 2001 splx(s); 2002 return (0); 2003} 2004 2005static void 2006comstart(tp) 2007 struct tty *tp; 2008{ 2009 struct com_s *com; 2010 cy_addr iobase; 2011 int s; 2012#ifdef CyDebug 2013 bool_t started; 2014#endif 2015 int unit; 2016 2017 unit = DEV_TO_UNIT(tp->t_dev); 2018 com = com_addr(unit); 2019 iobase = com->iobase; 2020 s = spltty(); 2021 2022#ifdef CyDebug 2023 ++com->start_count; 2024 started = FALSE; 2025#endif 2026 2027 disable_intr(); 2028 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 2029 if (tp->t_state & TS_TTSTOP) { 2030 com->state &= ~CS_TTGO; 2031 if (com->intr_enable & CD1400_SRER_TXRDY) 2032 cd_outb(iobase, CD1400_SRER, 2033 com->intr_enable &= ~CD1400_SRER_TXRDY); 2034 } else { 2035 com->state |= CS_TTGO; 2036 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2037 && !(com->intr_enable & CD1400_SRER_TXRDY)) 2038 cd_outb(iobase, CD1400_SRER, 2039 com->intr_enable |= CD1400_SRER_TXRDY); 2040 } 2041 if (tp->t_state & TS_TBLOCK) { 2042 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 2043#if 0 2044 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2045#else 2046 cd_outb(iobase, CD1400_MSVR1, 2047 com->mcr_image &= ~MCR_RTS); 2048#endif 2049 } else { 2050 /* 2051 * XXX don't raise MCR_RTS if CTS_RTS_IFLOW is off. Set it 2052 * appropriately in comparam() if RTS-flow is being changed. 2053 * Check for races. 2054 */ 2055 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater) 2056#if 0 2057 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2058#else 2059 cd_outb(iobase, CD1400_MSVR1, 2060 com->mcr_image |= MCR_RTS); 2061#endif 2062 } 2063 enable_intr(); 2064 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2065 splx(s); 2066 return; 2067 } 2068 if (tp->t_outq.c_cc != 0) { 2069 struct lbq *qp; 2070 struct lbq *next; 2071 2072 if (!com->obufs[0].l_queued) { 2073#ifdef CyDebug 2074 started = TRUE; 2075#endif 2076 com->obufs[0].l_tail 2077 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2078 sizeof com->obuf1); 2079 com->obufs[0].l_next = NULL; 2080 com->obufs[0].l_queued = TRUE; 2081 disable_intr(); 2082 if (com->state & CS_BUSY) { 2083 qp = com->obufq.l_next; 2084 while ((next = qp->l_next) != NULL) 2085 qp = next; 2086 qp->l_next = &com->obufs[0]; 2087 } else { 2088 com->obufq.l_head = com->obufs[0].l_head; 2089 com->obufq.l_tail = com->obufs[0].l_tail; 2090 com->obufq.l_next = &com->obufs[0]; 2091 com->state |= CS_BUSY; 2092 if (com->state >= (CS_BUSY | CS_TTGO 2093 | CS_ODEVREADY)) 2094 cd_outb(iobase, CD1400_SRER, 2095 com->intr_enable 2096 |= CD1400_SRER_TXRDY); 2097 } 2098 enable_intr(); 2099 } 2100 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2101#ifdef CyDebug 2102 started = TRUE; 2103#endif 2104 com->obufs[1].l_tail 2105 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2106 sizeof com->obuf2); 2107 com->obufs[1].l_next = NULL; 2108 com->obufs[1].l_queued = TRUE; 2109 disable_intr(); 2110 if (com->state & CS_BUSY) { 2111 qp = com->obufq.l_next; 2112 while ((next = qp->l_next) != NULL) 2113 qp = next; 2114 qp->l_next = &com->obufs[1]; 2115 } else { 2116 com->obufq.l_head = com->obufs[1].l_head; 2117 com->obufq.l_tail = com->obufs[1].l_tail; 2118 com->obufq.l_next = &com->obufs[1]; 2119 com->state |= CS_BUSY; 2120 if (com->state >= (CS_BUSY | CS_TTGO 2121 | CS_ODEVREADY)) 2122 cd_outb(iobase, CD1400_SRER, 2123 com->intr_enable 2124 |= CD1400_SRER_TXRDY); 2125 } 2126 enable_intr(); 2127 } 2128 tp->t_state |= TS_BUSY; 2129 } 2130#ifdef CyDebug 2131 if (started) 2132 ++com->start_real; 2133#endif 2134#if 0 2135 disable_intr(); 2136 if (com->state >= (CS_BUSY | CS_TTGO)) { 2137 siointr1(com); /* fake interrupt to start output */ 2138 enable_intr(); 2139#endif
| 158 159#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 160#define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE) 161#define RS_IBUFSIZE 256 162 163#define CALLOUT_MASK 0x80 164#define CONTROL_MASK 0x60 165#define CONTROL_INIT_STATE 0x20 166#define CONTROL_LOCK_STATE 0x40 167#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 168#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 169#define MINOR_TO_UNIT(mynor) ((mynor) & ~MINOR_MAGIC_MASK) 170 171/* 172 * Input buffer watermarks. 173 * The external device is asked to stop sending when the buffer exactly reaches 174 * high water, or when the high level requests it. 175 * The high level is notified immediately (rather than at a later clock tick) 176 * when this watermark is reached. 177 * The buffer size is chosen so the watermark should almost never be reached. 178 * The low watermark is invisibly 0 since the buffer is always emptied all at 179 * once. 180 */ 181#define RS_IHIGHWATER (3 * RS_IBUFSIZE / 4) 182 183/* 184 * com state bits. 185 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 186 * than the other bits so that they can be tested as a group without masking 187 * off the low bits. 188 * 189 * The following com and tty flags correspond closely: 190 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and 191 * siostop()) 192 * CS_TTGO = ~TS_TTSTOP (maintained by comstart() and siostop()) 193 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 194 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 195 * TS_FLUSH is not used. 196 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 197 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 198 */ 199#define CS_BUSY 0x80 /* output in progress */ 200#define CS_TTGO 0x40 /* output not stopped by XOFF */ 201#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 202#define CS_CHECKMSR 1 /* check of MSR scheduled */ 203#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 204#define CS_DTR_OFF 0x10 /* DTR held off */ 205#define CS_ODONE 4 /* output completed */ 206#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 207 208static char const * const error_desc[] = { 209#define CE_OVERRUN 0 210 "silo overflow", 211#define CE_INTERRUPT_BUF_OVERFLOW 1 212 "interrupt-level buffer overflow", 213#define CE_TTY_BUF_OVERFLOW 2 214 "tty-level buffer overflow", 215}; 216 217#define CE_NTYPES 3 218#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 219 220/* types. XXX - should be elsewhere */ 221typedef u_char bool_t; /* boolean */ 222typedef u_char volatile *cy_addr; 223 224/* queue of linear buffers */ 225struct lbq { 226 u_char *l_head; /* next char to process */ 227 u_char *l_tail; /* one past the last char to process */ 228 struct lbq *l_next; /* next in queue */ 229 bool_t l_queued; /* nonzero if queued */ 230}; 231 232/* com device structure */ 233struct com_s { 234 u_char state; /* miscellaneous flag bits */ 235 bool_t active_out; /* nonzero if the callout device is open */ 236#if 0 237 u_char cfcr_image; /* copy of value written to CFCR */ 238 u_char ftl; /* current rx fifo trigger level */ 239 u_char ftl_init; /* ftl_max for next open() */ 240 u_char ftl_max; /* maximum ftl for curent open() */ 241 bool_t hasfifo; /* nonzero for 16550 UARTs */ 242 bool_t loses_outints; /* nonzero if device loses output interrupts */ 243#endif 244 u_char mcr_image; /* copy of value written to MCR */ 245#if 0 246#ifdef COM_MULTIPORT 247 bool_t multiport; /* is this unit part of a multiport device? */ 248#endif /* COM_MULTIPORT */ 249 bool_t no_irq; /* nonzero if irq is not attached */ 250 bool_t poll; /* nonzero if polling is required */ 251 bool_t poll_output; /* nonzero if polling for output is required */ 252#endif 253 int unit; /* unit number */ 254 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 255#if 0 256 u_int tx_fifo_size; 257#endif 258 u_int wopeners; /* # processes waiting for DCD in open() */ 259 260 /* 261 * The high level of the driver never reads status registers directly 262 * because there would be too many side effects to handle conveniently. 263 * Instead, it reads copies of the registers stored here by the 264 * interrupt handler. 265 */ 266 u_char last_modem_status; /* last MSR read by intr handler */ 267 u_char prev_modem_status; /* last MSR handled by high level */ 268 269 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 270 u_char *ibuf; /* start of input buffer */ 271 u_char *ibufend; /* end of input buffer */ 272 u_char *ihighwater; /* threshold in input buffer */ 273 u_char *iptr; /* next free spot in input buffer */ 274 275 struct lbq obufq; /* head of queue of output buffers */ 276 struct lbq obufs[2]; /* output buffers */ 277 278 cy_addr cy_iobase; /* base address of this port's cyclom */ 279 cy_addr iobase; /* base address of this port's cd1400 */ 280 281 struct tty *tp; /* cross reference */ 282 283 /* Initial state. */ 284 struct termios it_in; /* should be in struct tty */ 285 struct termios it_out; 286 287 /* Lock state. */ 288 struct termios lt_in; /* should be in struct tty */ 289 struct termios lt_out; 290 291 bool_t do_timestamp; 292 struct timeval timestamp; 293 294 u_long bytes_in; /* statistics */ 295 u_long bytes_out; 296 u_int delta_error_counts[CE_NTYPES]; 297 u_long error_counts[CE_NTYPES]; 298 299 u_int recv_exception; /* exception chars received */ 300 u_int mdm; /* modem signal changes */ 301#ifdef CyDebug 302 u_int start_count; /* no. of calls to comstart() */ 303 u_int start_real; /* no. of calls that did something */ 304#endif 305 u_char channel_control;/* CD1400 CCR control command shadow */ 306 u_char cor[3]; /* CD1400 COR1-3 shadows */ 307 u_char intr_enable; /* CD1400 SRER shadow */ 308 309 /* 310 * Ping-pong input buffers. The extra factor of 2 in the sizes is 311 * to allow for an error byte for each input byte. 312 */ 313#define CE_INPUT_OFFSET RS_IBUFSIZE 314 u_char ibuf1[2 * RS_IBUFSIZE]; 315 u_char ibuf2[2 * RS_IBUFSIZE]; 316 317 /* 318 * Data area for output buffers. Someday we should build the output 319 * buffer queue without copying data. 320 */ 321 u_char obuf1[256]; 322 u_char obuf2[256]; 323 324 struct kern_devconf kdc; 325}; 326 327/* 328 * XXX public functions in drivers should be declared in headers produced 329 * by `config', not here. 330 */ 331 332/* Interrupt handling entry points. */ 333void siointr __P((int unit)); 334void siointrts __P((int unit)); 335void siopoll __P((void)); 336 337/* Device switch entry points. */ 338int sioopen __P((dev_t dev, int oflags, int devtype, 339 struct proc *p)); 340int sioclose __P((dev_t dev, int fflag, int devtype, 341 struct proc *p)); 342int sioread __P((dev_t dev, struct uio *uio, int ioflag)); 343int siowrite __P((dev_t dev, struct uio *uio, int ioflag)); 344int sioioctl __P((dev_t dev, int cmd, caddr_t data, 345 int fflag, struct proc *p)); 346void siostop __P((struct tty *tp, int rw)); 347#define sioreset noreset 348struct tty *siodevtotty __P((dev_t dev)); 349#define siommap nommap 350#define siostrategy nostrategy 351 352static int sioattach __P((struct isa_device *dev)); 353static void cd1400_channel_cmd __P((cy_addr iobase, int cmd)); 354static timeout_t siodtrwakeup; 355static void comhardclose __P((struct com_s *com)); 356static void siointr1 __P((struct com_s *com)); 357static int commctl __P((struct com_s *com, int bits, int how)); 358static int comparam __P((struct tty *tp, struct termios *t)); 359static int sioprobe __P((struct isa_device *dev)); 360static void sioregisterdev __P((struct isa_device *id)); 361static void siosettimeout __P((void)); 362static int comspeed __P((speed_t speed, int *prescaler_io)); 363static void comstart __P((struct tty *tp)); 364static timeout_t comwakeup; 365static void disc_optim __P((struct tty *tp, struct termios *t, 366 struct com_s *com)); 367 368#ifdef CyDebug 369void cystatus __P((int unit)); 370#endif 371 372/* table and macro for fast conversion from a unit number to its com struct */ 373static struct com_s *p_com_addr[NSIO]; 374#define com_addr(unit) (p_com_addr[unit]) 375 376static struct timeval intr_timestamp; 377 378struct isa_driver siodriver = { 379 sioprobe, sioattach, "cy" 380}; 381 382#ifdef COMCONSOLE 383#undef COMCONSOLE 384#define COMCONSOLE 1 385#else 386#define COMCONSOLE 0 387#endif 388 389#ifndef CONUNIT 390#define CONUNIT (0) 391#endif 392 393static int comconsole = CONUNIT; 394static speed_t comdefaultrate = TTYDEF_SPEED; 395static u_int com_events; /* input chars + weighted output completions */ 396static int commajor; 397static int sio_timeout; 398static int sio_timeouts_until_log; 399#if 0 /* XXX TK2.0 */ 400static struct tty *sio_tty[NSIO]; 401#else 402static struct tty sio_tty[NSIO]; 403static int nsio_tty = NSIO; 404#endif 405 406#ifdef KGDB 407#include <machine/remote-sl.h> 408 409extern int kgdb_dev; 410extern int kgdb_rate; 411extern int kgdb_debug_init; 412#endif 413 414#ifdef CyDebug 415static u_int cd_inbs; 416static u_int cy_inbs; 417static u_int cd_outbs; 418static u_int cy_outbs; 419static u_int cy_svrr_probes; 420static u_int cy_timeouts; 421#endif 422 423static int cy_nr_cd1400s[NCY]; 424#undef RxFifoThreshold 425static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); 426 427static struct kern_devconf kdc_sio[NCY] = { { 428 0, 0, 0, /* filled in by dev_attach */ 429 "cyc", 0, { MDDT_ISA, 0, "tty" }, 430 isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, 431 &kdc_isa0, /* parent */ 432 0, /* parentdata */ 433 DC_UNCONFIGURED, /* state */ 434 "Cyclades multiport board", 435 DC_CLS_MISC /* just an ordinary device */ 436} }; 437 438static void 439sioregisterdev(id) 440 struct isa_device *id; 441{ 442 int unit; 443 444 unit = id->id_unit; 445 if (unit != 0) 446 kdc_sio[unit] = kdc_sio[0]; 447 kdc_sio[unit].kdc_unit = unit; 448 kdc_sio[unit].kdc_isa = id; 449 dev_attach(&kdc_sio[unit]); 450} 451 452static int 453sioprobe(dev) 454 struct isa_device *dev; 455{ 456 int cyu; 457 u_char firmware_version; 458 cy_addr iobase; 459 int unit; 460 461 unit = dev->id_unit; 462 if ((u_int)unit >= NCY) 463 return (0); 464 cy_nr_cd1400s[unit] = 0; 465 sioregisterdev(dev); 466 467 /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ 468 cy_inb((cy_addr)dev->id_maddr, CY16_RESET); /* XXX? */ 469 470 DELAY(500); /* wait for the board to get its act together */ 471 472 for (cyu = 0, iobase = (cy_addr)dev->id_maddr; cyu < CY_MAX_CD1400s; 473 ++cyu, iobase += CY_CD1400_MEMSIZE) { 474 int i; 475 476 /* wait for chip to become ready for new command */ 477 for (i = 0; i < 100; i += 50) { 478 DELAY(50); 479 if (!cd_inb(iobase, CD1400_CCR)) 480 break; 481 } 482 483 /* clear the GFRCR register */ 484 cd_outb(iobase, CD1400_GFRCR, 0); 485 486 /* issue a reset command */ 487 cd_outb(iobase, CD1400_CCR, 488 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 489 490 /* wait for the CD1400 to initialize itself */ 491 for (i = 0; i < 1000; i += 50) { 492 DELAY(50); 493 494 /* retrieve firmware version */ 495 firmware_version = cd_inb(iobase, CD1400_GFRCR); 496 if (firmware_version != 0) 497 break; 498 } 499 500 /* 501 * Anything in the 0x40-0x4F range is fine. 502 * If one CD1400 is bad then we don't support higher 503 * numbered good ones on this board. 504 */ 505 if ((firmware_version & 0xF0) != 0x40) 506 break; 507 ++cy_nr_cd1400s[unit]; 508 } 509 return (cy_nr_cd1400s[unit] == 0 ? 0 : -1); 510} 511 512static int 513sioattach(isdp) 514 struct isa_device *isdp; 515{ 516 int cyu; 517 cy_addr cy_iobase; 518 cy_addr iobase; 519 int ncyu; 520 int unit; 521 522 unit = isdp->id_unit; 523 if ((u_int)unit >= NCY) 524 return (0); 525 ncyu = cy_nr_cd1400s[unit]; 526 if (ncyu == 0) 527 return (0); 528 isdp->id_ri_flags |= RI_FAST; 529 530 cy_iobase = (cy_addr)isdp->id_maddr; 531 unit *= CY_MAX_PORTS; 532 for (cyu = 0, iobase = cy_iobase; cyu < ncyu; 533 ++cyu, iobase += CY_CD1400_MEMSIZE) { 534 int cdu; 535 536 /* Set up a receive timeout period of than 1+ ms. */ 537 cd_outb(iobase, CD1400_PPR, 538 howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000)); 539 540 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { 541 struct com_s *com; 542 int s; 543 544 com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT); 545 if (com == NULL) 546 break; 547 bzero(com, sizeof *com); 548 com->unit = unit; 549 com->dtr_wait = 3 * hz; 550 com->iptr = com->ibuf = com->ibuf1; 551 com->ibufend = com->ibuf1 + RS_IBUFSIZE; 552 com->ihighwater = com->ibuf1 + RS_IHIGHWATER; 553 com->obufs[0].l_head = com->obuf1; 554 com->obufs[1].l_head = com->obuf2; 555 556 com->cy_iobase = cy_iobase; 557 com->iobase = iobase; 558 559 /* 560 * We don't use all the flags from <sys/ttydefaults.h> since they 561 * are only relevant for logins. It's important to have echo off 562 * initially so that the line doesn't start blathering before the 563 * echo flag can be turned off. 564 */ 565 com->it_in.c_iflag = 0; 566 com->it_in.c_oflag = 0; 567 com->it_in.c_cflag = TTYDEF_CFLAG; 568 com->it_in.c_lflag = 0; 569 if (unit == comconsole && (COMCONSOLE || boothowto & RB_SERIAL)) { 570 com->it_in.c_iflag = TTYDEF_IFLAG; 571 com->it_in.c_oflag = TTYDEF_OFLAG; 572 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 573 com->it_in.c_lflag = TTYDEF_LFLAG; 574 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 575 } 576 termioschars(&com->it_in); 577 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 578 com->it_out = com->it_in; 579 580 com->kdc = kdc_sio[0]; 581 com->kdc.kdc_name = "cy"; 582 com->kdc.kdc_unit = unit; 583 com->kdc.kdc_isa = isdp; 584 com->kdc.kdc_parent = &kdc_sio[isdp->id_unit]; 585 com->kdc.kdc_state = DC_IDLE; 586 com->kdc.kdc_description = 587 "Serial port: Cirrus Logic CD1400"; 588 com->kdc.kdc_class = DC_CLS_SERIAL; 589 dev_attach(&com->kdc); 590 591 s = spltty(); 592 com_addr(unit) = com; 593 splx(s); 594 } 595 } 596 kdc_sio[isdp->id_unit].kdc_state = DC_BUSY; /* XXX */ 597 598 /* ensure an edge for the next interrupt */ 599 cy_outb(cy_iobase, CY_CLEAR_INTR, 0); 600 601 return (1); 602} 603 604int 605sioopen(dev, flag, mode, p) 606 dev_t dev; 607 int flag; 608 int mode; 609 struct proc *p; 610{ 611 struct com_s *com; 612 int error; 613 cy_addr iobase; 614 int mynor; 615 int s; 616 struct tty *tp; 617 int unit; 618 619 mynor = minor(dev); 620 unit = MINOR_TO_UNIT(mynor); 621 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) 622 return (ENXIO); 623 if (mynor & CONTROL_MASK) 624 return (0); 625#if 0 /* XXX TK2.0 */ 626 tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]); 627#else 628 tp = com->tp = &sio_tty[unit]; 629#endif 630 s = spltty(); 631 /* 632 * We jump to this label after all non-interrupted sleeps to pick 633 * up any changes of the device state. 634 */ 635open_top: 636 while (com->state & CS_DTR_OFF) { 637 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0); 638 if (error != 0) 639 goto out; 640 } 641 com->kdc.kdc_state = DC_BUSY; 642 if (tp->t_state & TS_ISOPEN) { 643 /* 644 * The device is open, so everything has been initialized. 645 * Handle conflicts. 646 */ 647 if (mynor & CALLOUT_MASK) { 648 if (!com->active_out) { 649 error = EBUSY; 650 goto out; 651 } 652 } else { 653 if (com->active_out) { 654 if (flag & O_NONBLOCK) { 655 error = EBUSY; 656 goto out; 657 } 658 error = tsleep(&com->active_out, 659 TTIPRI | PCATCH, "cybi", 0); 660 if (error != 0) 661 goto out; 662 goto open_top; 663 } 664 } 665 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { 666 error = EBUSY; 667 goto out; 668 } 669 } else { 670 /* 671 * The device isn't open, so there are no conflicts. 672 * Initialize it. Initialization is done twice in many 673 * cases: to preempt sleeping callin opens if we are 674 * callout, and to complete a callin open after DCD rises. 675 */ 676 tp->t_oproc = comstart; 677 tp->t_param = comparam; 678 tp->t_dev = dev; 679 tp->t_termios = mynor & CALLOUT_MASK 680 ? com->it_out : com->it_in; 681#if 0 682 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 683 com->ftl_max = com->ftl_init; 684 com->poll = com->no_irq; 685 com->poll_output = com->loses_outints; 686#endif 687 ++com->wopeners; 688 iobase = com->iobase; 689 690 /* reset this channel */ 691 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 692 cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET); 693 694 /* 695 * Resetting disables the transmitter and receiver as well as 696 * flushing the fifos so some of our cached state becomes 697 * invalid. The documentation suggests that all registers 698 * for the current channel are reset to defaults, but 699 * apparently none are. We wouldn't want DTR cleared. 700 */ 701 com->channel_control = 0; 702 703 /* Encode per-board unit in LIVR for access in intr routines. */ 704 cd_outb(iobase, CD1400_LIVR, 705 (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); 706 707 /* 708 * raise dtr and generally set things up correctly. this 709 * has the side-effect of selecting the appropriate cd1400 710 * channel, to help us with subsequent channel control stuff 711 */ 712 error = comparam(tp, &tp->t_termios); 713 --com->wopeners; 714 if (error != 0) 715 goto out; 716 /* 717 * XXX we should goto open_top if comparam() slept. 718 */ 719 ttsetwater(tp); 720#if 0 721 if (com->hasfifo) { 722 /* 723 * (Re)enable and drain fifos. 724 * 725 * Certain SMC chips cause problems if the fifos 726 * are enabled while input is ready. Turn off the 727 * fifo if necessary to clear the input. We test 728 * the input ready bit after enabling the fifos 729 * since we've already enabled them in comparam() 730 * and to handle races between enabling and fresh 731 * input. 732 */ 733 while (TRUE) { 734 outb(iobase + com_fifo, 735 FIFO_RCV_RST | FIFO_XMT_RST 736 | FIFO_ENABLE | com->ftl); 737 DELAY(100); 738 if (!(inb(com->line_status_port) & LSR_RXRDY)) 739 break; 740 outb(iobase + com_fifo, 0); 741 DELAY(100); 742 (void) inb(com->data_port); 743 } 744 } 745 746 disable_intr(); 747 (void) inb(com->line_status_port); 748 (void) inb(com->data_port); 749 com->prev_modem_status = com->last_modem_status 750 = inb(com->modem_status_port); 751 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS 752 | IER_EMSC); 753 enable_intr(); 754#else /* !0 */ 755 /* XXX raise RTS too */ 756 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 757 disable_intr(); 758 com->prev_modem_status = com->last_modem_status 759 = cd_inb(iobase, CD1400_MSVR2); 760 cd_outb(iobase, CD1400_SRER, 761 com->intr_enable 762 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 763 enable_intr(); 764#endif /* 0 */ 765 /* 766 * Handle initial DCD. Callout devices get a fake initial 767 * DCD (trapdoor DCD). If we are callout, then any sleeping 768 * callin opens get woken up and resume sleeping on "cybi" 769 * instead of "cydcd". 770 */ 771 /* 772 * XXX `mynor & CALLOUT_MASK' should be 773 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 774 * TRAPDOOR_CARRIER is the default initial state for callout 775 * devices and SOFT_CARRIER is like CLOCAL except it hides 776 * the true carrier. 777 */ 778 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 779 (*linesw[tp->t_line].l_modem)(tp, 1); 780 } 781 /* 782 * Wait for DCD if necessary. 783 */ 784 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 785 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 786 ++com->wopeners; 787 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0); 788 --com->wopeners; 789 if (error != 0) 790 goto out; 791 goto open_top; 792 } 793 error = (*linesw[tp->t_line].l_open)(dev, tp); 794 disc_optim(tp, &tp->t_termios, com); 795 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 796 com->active_out = TRUE; 797 siosettimeout(); 798out: 799 splx(s); 800 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 801 comhardclose(com); 802 return (error); 803} 804 805int 806sioclose(dev, flag, mode, p) 807 dev_t dev; 808 int flag; 809 int mode; 810 struct proc *p; 811{ 812 struct com_s *com; 813 int mynor; 814 int s; 815 struct tty *tp; 816 817 mynor = minor(dev); 818 if (mynor & CONTROL_MASK) 819 return (0); 820 com = com_addr(MINOR_TO_UNIT(mynor)); 821 tp = com->tp; 822 s = spltty(); 823 (*linesw[tp->t_line].l_close)(tp, flag); 824 disc_optim(tp, &tp->t_termios, com); 825 siostop(tp, FREAD | FWRITE); 826 comhardclose(com); 827 ttyclose(tp); 828 siosettimeout(); 829 splx(s); 830#ifdef broken /* session holds a ref to the tty; can't deallocate */ 831 ttyfree(tp); 832 com->tp = sio_tty[unit] = NULL; 833#endif 834 return (0); 835} 836 837static void 838comhardclose(com) 839 struct com_s *com; 840{ 841 cy_addr iobase; 842 int s; 843 struct tty *tp; 844 int unit; 845 846 unit = com->unit; 847 iobase = com->iobase; 848 s = spltty(); 849#if 0 850 com->poll = FALSE; 851 com->poll_output = FALSE; 852#endif 853 com->do_timestamp = 0; 854 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 855#if 0 856 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 857#endif 858 859#ifdef KGDB 860 /* do not disable interrupts or hang up if debugging */ 861 if (kgdb_dev != makedev(commajor, unit)) 862#endif 863 { 864#if 0 865 outb(iobase + com_ier, 0); 866#else 867 disable_intr(); 868 cd_outb(iobase, CD1400_SRER, com->intr_enable = 0); 869 enable_intr(); 870#endif 871 tp = com->tp; 872 if (tp->t_cflag & HUPCL 873 /* 874 * XXX we will miss any carrier drop between here and the 875 * next open. Perhaps we should watch DCD even when the 876 * port is closed; it is not sufficient to check it at 877 * the next open because it might go up and down while 878 * we're not watching. 879 */ 880 || !com->active_out 881 && !(com->prev_modem_status & MSR_DCD) 882 && !(com->it_in.c_cflag & CLOCAL) 883 || !(tp->t_state & TS_ISOPEN)) { 884 (void)commctl(com, TIOCM_DTR, DMBIC); 885 886 /* Disable receiver (leave transmitter enabled). */ 887 com->channel_control = CD1400_CCR_CMDCHANCTL 888 | CD1400_CCR_XMTEN 889 | CD1400_CCR_RCVDIS; 890 cd1400_channel_cmd(iobase, com->channel_control); 891 892 if (com->dtr_wait != 0) { 893 timeout(siodtrwakeup, com, com->dtr_wait); 894 com->state |= CS_DTR_OFF; 895 } 896 } 897 } 898 com->active_out = FALSE; 899 wakeup(&com->active_out); 900 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 901 if (!(com->state & CS_DTR_OFF) 902 && !(unit == comconsole && (COMCONSOLE || boothowto & RB_SERIAL))) 903 com->kdc.kdc_state = DC_IDLE; 904 splx(s); 905} 906 907int 908sioread(dev, uio, flag) 909 dev_t dev; 910 struct uio *uio; 911 int flag; 912{ 913 int mynor; 914 struct tty *tp; 915 916 mynor = minor(dev); 917 if (mynor & CONTROL_MASK) 918 return (ENODEV); 919 tp = com_addr(MINOR_TO_UNIT(mynor))->tp; 920 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 921} 922 923int 924siowrite(dev, uio, flag) 925 dev_t dev; 926 struct uio *uio; 927 int flag; 928{ 929 int mynor; 930 struct tty *tp; 931 int unit; 932 933 mynor = minor(dev); 934 if (mynor & CONTROL_MASK) 935 return (ENODEV); 936 937 unit = MINOR_TO_UNIT(mynor); 938 tp = com_addr(unit)->tp; 939 /* 940 * (XXX) We disallow virtual consoles if the physical console is 941 * a serial port. This is in case there is a display attached that 942 * is not the console. In that situation we don't need/want the X 943 * server taking over the console. 944 */ 945 if (constty && unit == comconsole 946 && (COMCONSOLE || boothowto & RB_SERIAL)) 947 constty = NULL; 948#ifdef Smarts 949 /* XXX duplicate ttwrite(), but without so much output processing on 950 * CR & LF chars. Hardly worth the effort, given that high-throughput 951 * sessions are raw anyhow. 952 */ 953#else 954 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 955#endif 956} 957 958static void 959siodtrwakeup(chan) 960 void *chan; 961{ 962 struct com_s *com; 963 964 com = (struct com_s *)chan; 965 com->state &= ~CS_DTR_OFF; 966 if (!(com->unit == comconsole && (COMCONSOLE || boothowto & RB_SERIAL))) 967 com->kdc.kdc_state = DC_IDLE; 968 wakeup(&com->dtr_wait); 969} 970 971/* Interrupt routine for timekeeping purposes */ 972void 973siointrts(unit) 974 int unit; 975{ 976 /* 977 * XXX microtime() reenables CPU interrupts. We can't afford to 978 * be interrupted and don't want to slow down microtime(), so lock 979 * out interrupts in another way. 980 */ 981 outb(IO_ICU1 + 1, 0xff); 982 microtime(&intr_timestamp); 983 disable_intr(); 984 outb(IO_ICU1 + 1, imen); 985 986 siointr(unit); 987} 988 989void 990siointr(unit) 991 int unit; 992{ 993 int baseu; 994 cy_addr cy_iobase; 995 int cyu; 996 cy_addr iobase; 997 u_char status; 998 999 baseu = unit * CY_MAX_PORTS; 1000 cy_iobase = com_addr(baseu)->cy_iobase; 1001 1002 /* check each CD1400 in turn */ 1003 for (cyu = 0, iobase = cy_iobase; cyu < cy_nr_cd1400s[unit]; 1004 ++cyu, iobase += CY_CD1400_MEMSIZE) { 1005 /* poll to see if it has any work */ 1006 status = cd_inb(iobase, CD1400_SVRR); 1007 if (status == 0) 1008 continue; 1009#ifdef CyDebug 1010 ++cy_svrr_probes; 1011#endif 1012 /* service requests as appropriate, giving priority to RX */ 1013 if (status & CD1400_SVRR_RXRDY) { 1014 struct com_s *com; 1015 u_int count; 1016 u_char *ioptr; 1017 u_char line_status; 1018 u_char recv_data; 1019 u_char serv_type; 1020#ifdef PollMode 1021 u_char save_car; 1022 u_char save_rir; 1023#endif 1024 1025#ifdef PollMode 1026 save_rir = cd_inb(iobase, CD1400_RIR); 1027 save_car = cd_inb(iobase, CD1400_CAR); 1028 1029 /* enter rx service */ 1030 cd_outb(iobase, CD1400_CAR, save_rir); 1031 1032 serv_type = cd_inb(iobase, CD1400_RIVR); 1033 com = com_addr(baseu 1034 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1035 & CD1400_xIVR_CHAN)); 1036#else 1037 /* ack receive service */ 1038 serv_type = cy_inb(iobase, CY8_SVCACKR); 1039 1040 com = com_addr(baseu + 1041 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1042 & CD1400_xIVR_CHAN)); 1043#endif 1044 1045 if (com->do_timestamp) 1046 /* XXX a little bloat here... */ 1047 com->timestamp = intr_timestamp; 1048 1049 if (serv_type & CD1400_RIVR_EXCEPTION) { 1050 ++com->recv_exception; 1051 line_status = cd_inb(iobase, CD1400_RDSR); 1052 /* break/unnattached error bits or real input? */ 1053 recv_data = cd_inb(iobase, CD1400_RDSR); 1054#ifndef SOFT_HOTCHAR 1055 if (line_status & CD1400_RDSR_SPECIAL 1056 && com->hotchar != 0) 1057 setsofttty(); 1058#endif 1059#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ 1060 if (line_status & (LSR_PE|LSR_FE|LSR_BI)) { 1061 /* 1062 Don't store PE if IGNPAR and BI if IGNBRK, 1063 this hack allows "raw" tty optimization 1064 works even if IGN* is set. 1065 */ 1066 if ( com->tp == NULL 1067 || !(com->tp->t_state & TS_ISOPEN) 1068 || (line_status & (LSR_PE|LSR_FE)) 1069 && (com->tp->t_iflag & IGNPAR) 1070 || (line_status & LSR_BI) 1071 && (com->tp->t_iflag & IGNBRK)) 1072 goto cont; 1073 if ( (line_status & (LSR_PE|LSR_FE)) 1074 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) 1075 && ((line_status & LSR_FE) 1076 || (line_status & LSR_PE) 1077 && (com->tp->t_iflag & INPCK))) 1078 recv_data = 0; 1079 } 1080#endif /* 1 */ 1081 ++com->bytes_in; 1082#ifdef SOFT_HOTCHAR 1083 if (com->hotchar != 0 && recv_data == com->hotchar) 1084 setsofttty(); 1085#endif 1086 ioptr = com->iptr; 1087 if (ioptr >= com->ibufend) 1088 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1089 else { 1090 ++com_events; 1091 ioptr[0] = recv_data; 1092 ioptr[CE_INPUT_OFFSET] = line_status; 1093 com->iptr = ++ioptr; 1094 if (ioptr == com->ihighwater 1095 && com->state & CS_RTS_IFLOW) 1096#if 0 1097 outb(com->modem_ctl_port, 1098 com->mcr_image &= ~MCR_RTS); 1099#else 1100 cd_outb(iobase, CD1400_MSVR1, 1101 com->mcr_image &= ~MCR_RTS); 1102#endif 1103 if (line_status & LSR_OE) 1104 CE_RECORD(com, CE_OVERRUN); 1105 } 1106 goto cont; 1107 } else { 1108 int ifree; 1109 1110 count = cd_inb(iobase, CD1400_RDCR); 1111 com->bytes_in += count; 1112 ioptr = com->iptr; 1113 ifree = com->ibufend - ioptr; 1114 if (count > ifree) { 1115 count -= ifree; 1116 com_events += ifree; 1117 while (ifree-- != 0) { 1118 recv_data = cd_inb(iobase, CD1400_RDSR); 1119#ifdef SOFT_HOTCHAR 1120 if (com->hotchar != 0 1121 && recv_data == com->hotchar) 1122 setsofttty(); 1123#endif 1124 ioptr[0] = recv_data; 1125 ioptr[CE_INPUT_OFFSET] = 0; 1126 ++ioptr; 1127 } 1128 com->delta_error_counts 1129 [CE_INTERRUPT_BUF_OVERFLOW] += count; 1130 do { 1131 recv_data = cd_inb(iobase, CD1400_RDSR); 1132#ifdef SOFT_HOTCHAR 1133 if (com->hotchar != 0 1134 && recv_data == com->hotchar) 1135 setsofttty(); 1136#endif 1137 } while (--count != 0); 1138 } else { 1139 if (ioptr <= com->ihighwater 1140 && ioptr + count > com->ihighwater 1141 && com->state & CS_RTS_IFLOW) 1142#if 0 1143 outb(com->modem_ctl_port, 1144 com->mcr_image &= ~MCR_RTS); 1145#else 1146 cd_outb(iobase, CD1400_MSVR1, 1147 com->mcr_image &= ~MCR_RTS); 1148#endif 1149 com_events += count; 1150 do { 1151 recv_data = cd_inb(iobase, CD1400_RDSR); 1152#ifdef SOFT_HOTCHAR 1153 if (com->hotchar != 0 1154 && recv_data == com->hotchar) 1155 setsofttty(); 1156#endif 1157 ioptr[0] = recv_data; 1158 ioptr[CE_INPUT_OFFSET] = 0; 1159 ++ioptr; 1160 } while (--count != 0); 1161 } 1162 com->iptr = ioptr; 1163 } 1164cont: 1165 1166 /* terminate service context */ 1167#ifdef PollMode 1168 cd_outb(iobase, CD1400_RIR, 1169 save_rir 1170 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); 1171 cd_outb(iobase, CD1400_CAR, save_car); 1172#else 1173 cd_outb(iobase, CD1400_EOSRR, 0); 1174#endif 1175 } 1176 if (status & CD1400_SVRR_MDMCH) { 1177 struct com_s *com; 1178 u_char modem_status; 1179#ifdef PollMode 1180 u_char save_car; 1181 u_char save_mir; 1182#else 1183 u_char vector; 1184#endif 1185 1186#ifdef PollMode 1187 save_mir = cd_inb(iobase, CD1400_MIR); 1188 save_car = cd_inb(iobase, CD1400_CAR); 1189 1190 /* enter modem service */ 1191 cd_outb(iobase, CD1400_CAR, save_mir); 1192 1193 com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS 1194 + (save_mir & CD1400_MIR_CHAN)); 1195#else 1196 /* ack modem service */ 1197 vector = cy_inb(iobase, CY8_SVCACKM); 1198 1199 com = com_addr(baseu 1200 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1201 & CD1400_xIVR_CHAN)); 1202#endif 1203 ++com->mdm; 1204 modem_status = cd_inb(iobase, CD1400_MSVR2); 1205 if (modem_status != com->last_modem_status) { 1206 /* 1207 * Schedule high level to handle DCD changes. Note 1208 * that we don't use the delta bits anywhere. Some 1209 * UARTs mess them up, and it's easy to remember the 1210 * previous bits and calculate the delta. 1211 */ 1212 com->last_modem_status = modem_status; 1213 if (!(com->state & CS_CHECKMSR)) { 1214 com_events += LOTS_OF_EVENTS; 1215 com->state |= CS_CHECKMSR; 1216 setsofttty(); 1217 } 1218 1219#ifdef SOFT_CTS_OFLOW 1220 /* handle CTS change immediately for crisp flow ctl */ 1221 if (com->state & CS_CTS_OFLOW) { 1222 if (modem_status & MSR_CTS) { 1223 com->state |= CS_ODEVREADY; 1224 if (com->state >= (CS_BUSY | CS_TTGO 1225 | CS_ODEVREADY) 1226 && !(com->intr_enable 1227 & CD1400_SRER_TXRDY)) 1228 cd_outb(iobase, CD1400_SRER, 1229 com->intr_enable 1230 |= CD1400_SRER_TXRDY); 1231 } else { 1232 com->state &= ~CS_ODEVREADY; 1233 if (com->intr_enable & CD1400_SRER_TXRDY) 1234 cd_outb(iobase, CD1400_SRER, 1235 com->intr_enable 1236 &= ~CD1400_SRER_TXRDY); 1237 } 1238 } 1239#endif 1240 } 1241 1242 /* terminate service context */ 1243#ifdef PollMode 1244 cd_outb(iobase, CD1400_MIR, 1245 save_mir 1246 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); 1247 cd_outb(iobase, CD1400_CAR, save_car); 1248#else 1249 cd_outb(iobase, CD1400_EOSRR, 0); 1250#endif 1251 } 1252 if (status & CD1400_SVRR_TXRDY) { 1253 struct com_s *com; 1254#ifdef PollMode 1255 u_char save_car; 1256 u_char save_tir; 1257#else 1258 u_char vector; 1259#endif 1260 1261#ifdef PollMode 1262 save_tir = cd_inb(iobase, CD1400_TIR); 1263 save_car = cd_inb(iobase, CD1400_CAR); 1264 1265 /* enter tx service */ 1266 cd_outb(iobase, CD1400_CAR, save_tir); 1267 com = com_addr(baseu 1268 + cyu * CD1400_NO_OF_CHANNELS 1269 + (save_tir & CD1400_TIR_CHAN)); 1270#else 1271 /* ack transmit service */ 1272 vector = cy_inb(iobase, CY8_SVCACKT); 1273 1274 com = com_addr(baseu 1275 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1276 & CD1400_xIVR_CHAN)); 1277#endif 1278 1279 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1280 u_char *ioptr; 1281 u_int ocount; 1282 1283 ioptr = com->obufq.l_head; 1284 ocount = com->obufq.l_tail - ioptr; 1285 if (ocount > CD1400_TX_FIFO_SIZE) 1286 ocount = CD1400_TX_FIFO_SIZE; 1287 com->bytes_out += ocount; 1288 do 1289 cd_outb(iobase, CD1400_TDR, *ioptr++); 1290 while (--ocount != 0); 1291 com->obufq.l_head = ioptr; 1292 if (ioptr >= com->obufq.l_tail) { 1293 struct lbq *qp; 1294 1295 qp = com->obufq.l_next; 1296 qp->l_queued = FALSE; 1297 qp = qp->l_next; 1298 if (qp != NULL) { 1299 com->obufq.l_head = qp->l_head; 1300 com->obufq.l_tail = qp->l_tail; 1301 com->obufq.l_next = qp; 1302 } else { 1303 /* output just completed */ 1304 com->state &= ~CS_BUSY; 1305 cd_outb(iobase, CD1400_SRER, 1306 com->intr_enable 1307 &= ~CD1400_SRER_TXRDY); 1308 } 1309 if (!(com->state & CS_ODONE)) { 1310 com_events += LOTS_OF_EVENTS; 1311 com->state |= CS_ODONE; 1312 setsofttty(); /* handle at high level ASAP */ 1313 } 1314 } 1315 } 1316 1317 /* terminate service context */ 1318#ifdef PollMode 1319 cd_outb(iobase, CD1400_TIR, 1320 save_tir 1321 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); 1322 cd_outb(iobase, CD1400_CAR, save_car); 1323#else 1324 cd_outb(iobase, CD1400_EOSRR, 0); 1325#endif 1326 } 1327 } 1328 1329 /* ensure an edge for the next interrupt */ 1330 cy_outb(cy_iobase, CY_CLEAR_INTR, 0); 1331 1332 schedsofttty(); 1333} 1334 1335static void 1336siointr1(com) 1337 struct com_s *com; 1338{ 1339} 1340 1341int 1342sioioctl(dev, cmd, data, flag, p) 1343 dev_t dev; 1344 int cmd; 1345 caddr_t data; 1346 int flag; 1347 struct proc *p; 1348{ 1349 struct com_s *com; 1350 int error; 1351 cy_addr iobase; 1352 int mynor; 1353 int s; 1354 struct tty *tp; 1355#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1356 int oldcmd; 1357 struct termios term; 1358#endif 1359 1360 mynor = minor(dev); 1361 com = com_addr(MINOR_TO_UNIT(mynor)); 1362 iobase = com->iobase; 1363 if (mynor & CONTROL_MASK) { 1364 struct termios *ct; 1365 1366 switch (mynor & CONTROL_MASK) { 1367 case CONTROL_INIT_STATE: 1368 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 1369 break; 1370 case CONTROL_LOCK_STATE: 1371 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 1372 break; 1373 default: 1374 return (ENODEV); /* /dev/nodev */ 1375 } 1376 switch (cmd) { 1377 case TIOCSETA: 1378 error = suser(p->p_ucred, &p->p_acflag); 1379 if (error != 0) 1380 return (error); 1381 *ct = *(struct termios *)data; 1382 return (0); 1383 case TIOCGETA: 1384 *(struct termios *)data = *ct; 1385 return (0); 1386 case TIOCGETD: 1387 *(int *)data = TTYDISC; 1388 return (0); 1389 case TIOCGWINSZ: 1390 bzero(data, sizeof(struct winsize)); 1391 return (0); 1392 default: 1393 return (ENOTTY); 1394 } 1395 } 1396 tp = com->tp; 1397#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1398 term = tp->t_termios; 1399 oldcmd = cmd; 1400 error = ttsetcompat(tp, &cmd, data, &term); 1401 if (error != 0) 1402 return (error); 1403 if (cmd != oldcmd) 1404 data = (caddr_t)&term; 1405#endif 1406 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1407 int cc; 1408 struct termios *dt = (struct termios *)data; 1409 struct termios *lt = mynor & CALLOUT_MASK 1410 ? &com->lt_out : &com->lt_in; 1411 1412 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1413 | (dt->c_iflag & ~lt->c_iflag); 1414 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1415 | (dt->c_oflag & ~lt->c_oflag); 1416 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1417 | (dt->c_cflag & ~lt->c_cflag); 1418 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1419 | (dt->c_lflag & ~lt->c_lflag); 1420 for (cc = 0; cc < NCCS; ++cc) 1421 if (lt->c_cc[cc] != 0) 1422 dt->c_cc[cc] = tp->t_cc[cc]; 1423 if (lt->c_ispeed != 0) 1424 dt->c_ispeed = tp->t_ispeed; 1425 if (lt->c_ospeed != 0) 1426 dt->c_ospeed = tp->t_ospeed; 1427 } 1428 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1429 if (error >= 0) 1430 return (error); 1431 s = spltty(); 1432 error = ttioctl(tp, cmd, data, flag); 1433 disc_optim(tp, &tp->t_termios, com); 1434 if (error >= 0) { 1435 splx(s); 1436 return (error); 1437 } 1438 cd_outb(iobase, CD1400_CAR, MINOR_TO_UNIT(mynor) & CD1400_CAR_CHAN); 1439 switch (cmd) { 1440#if 0 1441 case TIOCSBRK: 1442 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 1443 break; 1444 case TIOCCBRK: 1445 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1446 break; 1447#endif /* 0 */ 1448 case TIOCSDTR: 1449 (void)commctl(com, TIOCM_DTR, DMBIS); 1450 break; 1451 case TIOCCDTR: 1452 (void)commctl(com, TIOCM_DTR, DMBIC); 1453 break; 1454 case TIOCMSET: 1455 (void)commctl(com, *(int *)data, DMSET); 1456 break; 1457 case TIOCMBIS: 1458 (void)commctl(com, *(int *)data, DMBIS); 1459 break; 1460 case TIOCMBIC: 1461 (void)commctl(com, *(int *)data, DMBIC); 1462 break; 1463 case TIOCMGET: 1464 *(int *)data = commctl(com, 0, DMGET); 1465 break; 1466 case TIOCMSDTRWAIT: 1467 /* must be root since the wait applies to following logins */ 1468 error = suser(p->p_ucred, &p->p_acflag); 1469 if (error != 0) { 1470 splx(s); 1471 return (error); 1472 } 1473 com->dtr_wait = *(int *)data * hz / 100; 1474 break; 1475 case TIOCMGDTRWAIT: 1476 *(int *)data = com->dtr_wait * 100 / hz; 1477 break; 1478 case TIOCTIMESTAMP: 1479 com->do_timestamp = TRUE; 1480 *(struct timeval *)data = com->timestamp; 1481 break; 1482 default: 1483 splx(s); 1484 return (ENOTTY); 1485 } 1486 splx(s); 1487 return (0); 1488} 1489 1490void 1491siopoll() 1492{ 1493 int unit; 1494 1495#ifdef CyDebug 1496 ++cy_timeouts; 1497#endif 1498 if (com_events == 0) 1499 return; 1500repeat: 1501 for (unit = 0; unit < NSIO; ++unit) { 1502 u_char *buf; 1503 struct com_s *com; 1504 u_char *ibuf; 1505 cy_addr iobase; 1506 int incc; 1507 struct tty *tp; 1508 1509 com = com_addr(unit); 1510 if (com == NULL) 1511 continue; 1512 tp = com->tp; 1513 if (tp == NULL) { 1514 /* 1515 * XXX forget any events related to closed devices 1516 * (actually never opened devices) so that we don't 1517 * loop. 1518 */ 1519 disable_intr(); 1520 incc = com->iptr - com->ibuf; 1521 com->iptr = com->ibuf; 1522 if (com->state & CS_CHECKMSR) { 1523 incc += LOTS_OF_EVENTS; 1524 com->state &= ~CS_CHECKMSR; 1525 } 1526 com_events -= incc; 1527 enable_intr(); 1528 if (incc != 0) 1529 log(LOG_DEBUG, 1530 "sio%d: %d events for device with no tp\n", 1531 unit, incc); 1532 continue; 1533 } 1534 1535 /* switch the role of the low-level input buffers */ 1536 if (com->iptr == (ibuf = com->ibuf)) { 1537 buf = NULL; /* not used, but compiler can't tell */ 1538 incc = 0; 1539 } else { 1540 buf = ibuf; 1541 disable_intr(); 1542 incc = com->iptr - buf; 1543 com_events -= incc; 1544 if (ibuf == com->ibuf1) 1545 ibuf = com->ibuf2; 1546 else 1547 ibuf = com->ibuf1; 1548 com->ibufend = ibuf + RS_IBUFSIZE; 1549 com->ihighwater = ibuf + RS_IHIGHWATER; 1550 com->iptr = ibuf; 1551 1552 /* 1553 * There is now room for another low-level buffer full 1554 * of input, so enable RTS if it is now disabled and 1555 * there is room in the high-level buffer. 1556 */ 1557 /* 1558 * XXX this used not to look at CS_RTS_IFLOW. The 1559 * change is to allow full control of MCR_RTS via 1560 * ioctls after turning CS_RTS_IFLOW off. Check 1561 * for races. We shouldn't allow the ioctls while 1562 * CS_RTS_IFLOW is on. 1563 */ 1564 if ((com->state & CS_RTS_IFLOW) 1565 && !(com->mcr_image & MCR_RTS) 1566 && !(tp->t_state & TS_TBLOCK)) 1567#if 0 1568 outb(com->modem_ctl_port, 1569 com->mcr_image |= MCR_RTS); 1570#else 1571 iobase = com->iobase, 1572 cd_outb(iobase, CD1400_CAR, 1573 unit & CD1400_CAR_CHAN), 1574 cd_outb(iobase, CD1400_MSVR1, 1575 com->mcr_image |= MCR_RTS); 1576#endif 1577 enable_intr(); 1578 com->ibuf = ibuf; 1579 } 1580 1581 if (com->state & CS_CHECKMSR) { 1582 u_char delta_modem_status; 1583 1584 disable_intr(); 1585 delta_modem_status = com->last_modem_status 1586 ^ com->prev_modem_status; 1587 com->prev_modem_status = com->last_modem_status; 1588 com_events -= LOTS_OF_EVENTS; 1589 com->state &= ~CS_CHECKMSR; 1590 enable_intr(); 1591 if (delta_modem_status & MSR_DCD) 1592 (*linesw[tp->t_line].l_modem) 1593 (tp, com->prev_modem_status & MSR_DCD); 1594 } 1595 if (com->state & CS_ODONE) { 1596 disable_intr(); 1597 com_events -= LOTS_OF_EVENTS; 1598 com->state &= ~CS_ODONE; 1599 if (!(com->state & CS_BUSY)) 1600 com->tp->t_state &= ~TS_BUSY; 1601 enable_intr(); 1602 (*linesw[tp->t_line].l_start)(tp); 1603 } 1604 if (incc <= 0 || !(tp->t_state & TS_ISOPEN)) 1605 continue; 1606 /* 1607 * XXX only do this when we bypass ttyinput. 1608 */ 1609 if (tp->t_rawq.c_cc + incc >= RB_I_HIGH_WATER 1610 && (com->state & CS_RTS_IFLOW || tp->t_iflag & IXOFF) 1611 && !(tp->t_state & TS_TBLOCK) 1612 /* 1613 * XXX - need flow control for all line disciplines. 1614 * Only have it in standard one now. 1615 */ 1616 && linesw[tp->t_line].l_rint == ttyinput) { 1617 int putc_status = 0; 1618 1619 if ((tp->t_iflag & IXOFF 1620 && tp->t_cc[VSTOP] != _POSIX_VDISABLE 1621 && (putc_status = putc(tp->t_cc[VSTOP], 1622 &tp->t_outq)) == 0) 1623 || com->state & CS_RTS_IFLOW) { 1624 tp->t_state |= TS_TBLOCK; 1625 ttstart(tp); 1626 if (putc_status != 0) 1627 /* Try again later. */ 1628 tp->t_state &= ~TS_TBLOCK; 1629 } 1630 } 1631 /* 1632 * Avoid the grotesquely inefficient lineswitch routine 1633 * (ttyinput) in "raw" mode. It usually takes about 450 1634 * instructions (that's without canonical processing or echo!). 1635 * slinput is reasonably fast (usually 40 instructions plus 1636 * call overhead). 1637 */ 1638 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 1639 tk_nin += incc; 1640 tk_rawcc += incc; 1641 tp->t_rawcc += incc; 1642 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 1643 += b_to_q((char *)buf, incc, &tp->t_rawq); 1644 ttwakeup(tp); 1645 if (tp->t_state & TS_TTSTOP 1646 && (tp->t_iflag & IXANY 1647 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 1648 tp->t_state &= ~TS_TTSTOP; 1649 tp->t_lflag &= ~FLUSHO; 1650 ttstart(tp); 1651 } 1652 } else { 1653 do { 1654 u_char line_status; 1655 int recv_data; 1656 1657 line_status = (u_char) buf[CE_INPUT_OFFSET]; 1658 recv_data = (u_char) *buf++; 1659 if (line_status 1660 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 1661 if (line_status & LSR_BI) 1662 recv_data |= TTY_BI; 1663 if (line_status & LSR_FE) 1664 recv_data |= TTY_FE; 1665 if (line_status & LSR_OE) 1666 recv_data |= TTY_OE; 1667 if (line_status & LSR_PE) 1668 recv_data |= TTY_PE; 1669 } 1670 (*linesw[tp->t_line].l_rint)(recv_data, tp); 1671 } while (--incc > 0); 1672 } 1673 if (com_events == 0) 1674 break; 1675 } 1676 if (com_events >= LOTS_OF_EVENTS) 1677 goto repeat; 1678} 1679 1680static int 1681comparam(tp, t) 1682 struct tty *tp; 1683 struct termios *t; 1684{ 1685 int bits; 1686 int cflag; 1687 struct com_s *com; 1688 u_char cor_change; 1689 int idivisor; 1690 int iflag; 1691 cy_addr iobase; 1692 int iprescaler; 1693 int itimeout; 1694 int odivisor; 1695 int oprescaler; 1696 u_char opt; 1697 int s; 1698 int unit; 1699 1700 /* do historical conversions */ 1701 if (t->c_ispeed == 0) 1702 t->c_ispeed = t->c_ospeed; 1703 1704 /* check requested parameters */ 1705 idivisor = comspeed(t->c_ispeed, &iprescaler); 1706 if (idivisor < 0) 1707 return (EINVAL); 1708 odivisor = comspeed(t->c_ospeed, &oprescaler); 1709 if (odivisor < 0) 1710 return (EINVAL); 1711 1712 /* parameters are OK, convert them to the com struct and the device */ 1713 unit = DEV_TO_UNIT(tp->t_dev); 1714 com = com_addr(unit); 1715 iobase = com->iobase; 1716 s = spltty(); 1717 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 1718 if (odivisor == 0) 1719 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 1720 else 1721 (void)commctl(com, TIOCM_DTR, DMBIS); 1722 1723 cd_outb(iobase, CD1400_RBPR, idivisor); 1724 cd_outb(iobase, CD1400_RCOR, iprescaler); 1725 cd_outb(iobase, CD1400_TBPR, odivisor); 1726 cd_outb(iobase, CD1400_TCOR, oprescaler); 1727 1728 /* 1729 * channel control 1730 * receiver enable 1731 * transmitter enable (always set) 1732 */ 1733 cflag = t->c_cflag; 1734 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 1735 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 1736 if (opt != com->channel_control) { 1737 com->channel_control = opt; 1738 cd1400_channel_cmd(iobase, opt); 1739 } 1740 1741#ifdef Smarts 1742 /* set special chars */ 1743 /* XXX if one is _POSIX_VDISABLE, can't use some others */ 1744 if (t->c_cc[VSTOP] != _POSIX_VDISABLE) 1745 cd_outb(iobase, CD1400_SCHR1, t->c_cc[VSTOP]); 1746 if (t->c_cc[VSTART] != _POSIX_VDISABLE) 1747 cd_outb(iobase, CD1400_SCHR2, t->c_cc[VSTART]); 1748 if (t->c_cc[VINTR] != _POSIX_VDISABLE) 1749 cd_outb(iobase, CD1400_SCHR3, t->c_cc[VINTR]); 1750 if (t->c_cc[VSUSP] != _POSIX_VDISABLE) 1751 cd_outb(iobase, CD1400_SCHR4, t->c_cc[VSUSP]); 1752#endif 1753 1754 /* 1755 * set channel option register 1 - 1756 * parity mode 1757 * stop bits 1758 * char length 1759 */ 1760 opt = 0; 1761 /* parity */ 1762 if (cflag & PARENB) { 1763 if (cflag & PARODD) 1764 opt |= CD1400_COR1_PARODD; 1765 opt |= CD1400_COR1_PARNORMAL; 1766 } 1767 iflag = t->c_iflag; 1768 if (!(iflag & INPCK)) 1769 opt |= CD1400_COR1_NOINPCK; 1770 bits = 1 + 1; 1771 /* stop bits */ 1772 if (cflag & CSTOPB) { 1773 ++bits; 1774 opt |= CD1400_COR1_STOP2; 1775 } 1776 /* char length */ 1777 switch (cflag & CSIZE) { 1778 case CS5: 1779 bits += 5; 1780 opt |= CD1400_COR1_CS5; 1781 break; 1782 case CS6: 1783 bits += 6; 1784 opt |= CD1400_COR1_CS6; 1785 break; 1786 case CS7: 1787 bits += 7; 1788 opt |= CD1400_COR1_CS7; 1789 break; 1790 default: 1791 bits += 8; 1792 opt |= CD1400_COR1_CS8; 1793 break; 1794 } 1795 cor_change = 0; 1796 if (opt != com->cor[0]) { 1797 cor_change |= CD1400_CCR_COR1; 1798 cd_outb(iobase, CD1400_COR1, com->cor[0] = opt); 1799 } 1800 1801 /* 1802 * Set receive time-out period, normally to max(one char time, 5 ms). 1803 */ 1804 if (t->c_ispeed == 0) 1805 itimeout = cd_inb(iobase, CD1400_RTPR); 1806 else { 1807 itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; 1808#ifdef SOFT_HOTCHAR 1809#define MIN_RTP 1 1810#else 1811#define MIN_RTP 5 1812#endif 1813 if (itimeout < MIN_RTP) 1814 itimeout = MIN_RTP; 1815 } 1816 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 1817 && t->c_cc[VTIME] * 10 > itimeout) 1818 itimeout = t->c_cc[VTIME] * 10; 1819 if (itimeout > 255) 1820 itimeout = 255; 1821 cd_outb(iobase, CD1400_RTPR, itimeout); 1822 1823 /* 1824 * set channel option register 2 - 1825 * flow control 1826 */ 1827 opt = 0; 1828#ifdef Smarts 1829 if (iflag & IXANY) 1830 opt |= CD1400_COR2_IXANY; 1831 if (iflag & IXOFF) 1832 opt |= CD1400_COR2_IXOFF; 1833#endif 1834#ifndef SOFT_CTS_OFLOW 1835 if (cflag & CCTS_OFLOW) 1836 opt |= CD1400_COR2_CCTS_OFLOW; 1837#endif 1838 if (opt != com->cor[1]) { 1839 cor_change |= CD1400_CCR_COR2; 1840 cd_outb(iobase, CD1400_COR2, com->cor[1] = opt); 1841 } 1842 1843 /* 1844 * set channel option register 3 - 1845 * receiver FIFO interrupt threshold 1846 * flow control 1847 */ 1848 opt = RxFifoThreshold; 1849#ifdef Smarts 1850 if (t->c_lflag & ICANON) 1851 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 1852 if (iflag & IXOFF) 1853 /* detect and transparently handle START and STOP chars */ 1854 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 1855#endif 1856 if (opt != com->cor[2]) { 1857 cor_change |= CD1400_CCR_COR3; 1858 cd_outb(iobase, CD1400_COR3, com->cor[2] = opt); 1859 } 1860 1861 /* notify the CD1400 if COR1-3 have changed */ 1862 if (cor_change) 1863 cd1400_channel_cmd(iobase, CD1400_CCR_CMDCORCHG | cor_change); 1864 1865 /* 1866 * set channel option register 4 - 1867 * CR/NL processing 1868 * break processing 1869 * received exception processing 1870 */ 1871 opt = 0; 1872 if (iflag & IGNCR) 1873 opt |= CD1400_COR4_IGNCR; 1874#ifdef Smarts 1875 /* 1876 * we need a new ttyinput() for this, as we don't want to 1877 * have ICRNL && INLCR being done in both layers, or to have 1878 * synchronisation problems 1879 */ 1880 if (iflag & ICRNL) 1881 opt |= CD1400_COR4_ICRNL; 1882 if (iflag & INLCR) 1883 opt |= CD1400_COR4_INLCR; 1884#endif 1885 if (iflag & IGNBRK) 1886 opt |= CD1400_COR4_IGNBRK; 1887 if (!(iflag & BRKINT)) 1888 opt |= CD1400_COR4_NOBRKINT; 1889#if 0 1890 /* XXX using this "intelligence" breaks reporting of overruns. */ 1891 if (iflag & IGNPAR) 1892 opt |= CD1400_COR4_PFO_DISCARD; 1893 else { 1894 if (iflag & PARMRK) 1895 opt |= CD1400_COR4_PFO_ESC; 1896 else 1897 opt |= CD1400_COR4_PFO_NUL; 1898 } 1899#else 1900 opt |= CD1400_COR4_PFO_EXCEPTION; 1901#endif 1902 cd_outb(iobase, CD1400_COR4, opt); 1903 1904 /* 1905 * set channel option register 5 - 1906 */ 1907 opt = 0; 1908 if (iflag & ISTRIP) 1909 opt |= CD1400_COR5_ISTRIP; 1910 if (t->c_iflag & IEXTEN) 1911 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 1912 opt |= CD1400_COR5_LNEXT; 1913#ifdef Smarts 1914 if (t->c_oflag & ONLCR) 1915 opt |= CD1400_COR5_ONLCR; 1916 if (t->c_oflag & OCRNL) 1917 opt |= CD1400_COR5_OCRNL; 1918#endif 1919 cd_outb(iobase, CD1400_COR5, opt); 1920 1921 /* 1922 * XXX we probably alway want to track carrier changes, so that 1923 * TS_CARR_ON gives the true carrier. If we don't track them, 1924 * then we should set TS_CARR_ON when CLOCAL drops. 1925 */ 1926 /* 1927 * set modem change option register 1 1928 * generate modem interrupts on which 1 -> 0 input transitions 1929 * also controls auto-DTR output flow-control, which we don't use 1930 */ 1931 opt = cflag & CLOCAL ? 0 : CD1400_MCOR1_CDzd; 1932#ifdef SOFT_CTS_OFLOW 1933 if (cflag & CCTS_OFLOW) 1934 opt |= CD1400_MCOR1_CTSzd; 1935#endif 1936 cd_outb(iobase, CD1400_MCOR1, opt); 1937 1938 /* 1939 * set modem change option register 2 1940 * generate modem interrupts on specific 0 -> 1 input transitions 1941 */ 1942 opt = cflag & CLOCAL ? 0 : CD1400_MCOR2_CDod; 1943#ifdef SOFT_CTS_OFLOW 1944 if (cflag & CCTS_OFLOW) 1945 opt |= CD1400_MCOR2_CTSod; 1946#endif 1947 cd_outb(iobase, CD1400_MCOR2, opt); 1948 1949 /* 1950 * XXX should have done this long ago, but there is too much state 1951 * to change all atomically. 1952 */ 1953 disable_intr(); 1954 1955 com->state &= ~CS_TTGO; 1956 if (!(tp->t_state & TS_TTSTOP)) 1957 com->state |= CS_TTGO; 1958 if (cflag & CRTS_IFLOW) 1959 com->state |= CS_RTS_IFLOW; /* XXX - secondary changes? */ 1960 else 1961 com->state &= ~CS_RTS_IFLOW; 1962 1963 /* 1964 * Set up state to handle output flow control. 1965 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 1966 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 1967 */ 1968 com->state |= CS_ODEVREADY; 1969#ifdef SOFT_CTS_OFLOW 1970 com->state &= ~CS_CTS_OFLOW; 1971 if (cflag & CCTS_OFLOW) { 1972 com->state |= CS_CTS_OFLOW; 1973 if (!(com->last_modem_status & MSR_CTS)) 1974 com->state &= ~CS_ODEVREADY; 1975 } 1976#endif 1977 /* XXX shouldn't call functions while intrs are disabled. */ 1978 disc_optim(tp, t, com); 1979#if 0 1980 /* 1981 * Recover from fiddling with CS_TTGO. We used to call siointr1() 1982 * unconditionally, but that defeated the careful discarding of 1983 * stale input in sioopen(). 1984 */ 1985 if (com->state >= (CS_BUSY | CS_TTGO)) 1986 siointr1(com); 1987#endif 1988 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1989 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 1990 cd_outb(iobase, CD1400_SRER, 1991 com->intr_enable |= CD1400_SRER_TXRDY); 1992 } else { 1993 if (com->intr_enable & CD1400_SRER_TXRDY) 1994 cd_outb(iobase, CD1400_SRER, 1995 com->intr_enable &= ~CD1400_SRER_TXRDY); 1996 } 1997 1998 enable_intr(); 1999 splx(s); 2000 return (0); 2001} 2002 2003static void 2004comstart(tp) 2005 struct tty *tp; 2006{ 2007 struct com_s *com; 2008 cy_addr iobase; 2009 int s; 2010#ifdef CyDebug 2011 bool_t started; 2012#endif 2013 int unit; 2014 2015 unit = DEV_TO_UNIT(tp->t_dev); 2016 com = com_addr(unit); 2017 iobase = com->iobase; 2018 s = spltty(); 2019 2020#ifdef CyDebug 2021 ++com->start_count; 2022 started = FALSE; 2023#endif 2024 2025 disable_intr(); 2026 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 2027 if (tp->t_state & TS_TTSTOP) { 2028 com->state &= ~CS_TTGO; 2029 if (com->intr_enable & CD1400_SRER_TXRDY) 2030 cd_outb(iobase, CD1400_SRER, 2031 com->intr_enable &= ~CD1400_SRER_TXRDY); 2032 } else { 2033 com->state |= CS_TTGO; 2034 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2035 && !(com->intr_enable & CD1400_SRER_TXRDY)) 2036 cd_outb(iobase, CD1400_SRER, 2037 com->intr_enable |= CD1400_SRER_TXRDY); 2038 } 2039 if (tp->t_state & TS_TBLOCK) { 2040 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 2041#if 0 2042 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2043#else 2044 cd_outb(iobase, CD1400_MSVR1, 2045 com->mcr_image &= ~MCR_RTS); 2046#endif 2047 } else { 2048 /* 2049 * XXX don't raise MCR_RTS if CTS_RTS_IFLOW is off. Set it 2050 * appropriately in comparam() if RTS-flow is being changed. 2051 * Check for races. 2052 */ 2053 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater) 2054#if 0 2055 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2056#else 2057 cd_outb(iobase, CD1400_MSVR1, 2058 com->mcr_image |= MCR_RTS); 2059#endif 2060 } 2061 enable_intr(); 2062 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2063 splx(s); 2064 return; 2065 } 2066 if (tp->t_outq.c_cc != 0) { 2067 struct lbq *qp; 2068 struct lbq *next; 2069 2070 if (!com->obufs[0].l_queued) { 2071#ifdef CyDebug 2072 started = TRUE; 2073#endif 2074 com->obufs[0].l_tail 2075 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2076 sizeof com->obuf1); 2077 com->obufs[0].l_next = NULL; 2078 com->obufs[0].l_queued = TRUE; 2079 disable_intr(); 2080 if (com->state & CS_BUSY) { 2081 qp = com->obufq.l_next; 2082 while ((next = qp->l_next) != NULL) 2083 qp = next; 2084 qp->l_next = &com->obufs[0]; 2085 } else { 2086 com->obufq.l_head = com->obufs[0].l_head; 2087 com->obufq.l_tail = com->obufs[0].l_tail; 2088 com->obufq.l_next = &com->obufs[0]; 2089 com->state |= CS_BUSY; 2090 if (com->state >= (CS_BUSY | CS_TTGO 2091 | CS_ODEVREADY)) 2092 cd_outb(iobase, CD1400_SRER, 2093 com->intr_enable 2094 |= CD1400_SRER_TXRDY); 2095 } 2096 enable_intr(); 2097 } 2098 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2099#ifdef CyDebug 2100 started = TRUE; 2101#endif 2102 com->obufs[1].l_tail 2103 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2104 sizeof com->obuf2); 2105 com->obufs[1].l_next = NULL; 2106 com->obufs[1].l_queued = TRUE; 2107 disable_intr(); 2108 if (com->state & CS_BUSY) { 2109 qp = com->obufq.l_next; 2110 while ((next = qp->l_next) != NULL) 2111 qp = next; 2112 qp->l_next = &com->obufs[1]; 2113 } else { 2114 com->obufq.l_head = com->obufs[1].l_head; 2115 com->obufq.l_tail = com->obufs[1].l_tail; 2116 com->obufq.l_next = &com->obufs[1]; 2117 com->state |= CS_BUSY; 2118 if (com->state >= (CS_BUSY | CS_TTGO 2119 | CS_ODEVREADY)) 2120 cd_outb(iobase, CD1400_SRER, 2121 com->intr_enable 2122 |= CD1400_SRER_TXRDY); 2123 } 2124 enable_intr(); 2125 } 2126 tp->t_state |= TS_BUSY; 2127 } 2128#ifdef CyDebug 2129 if (started) 2130 ++com->start_real; 2131#endif 2132#if 0 2133 disable_intr(); 2134 if (com->state >= (CS_BUSY | CS_TTGO)) { 2135 siointr1(com); /* fake interrupt to start output */ 2136 enable_intr(); 2137#endif
|
2154 splx(s); 2155} 2156 2157void 2158siostop(tp, rw) 2159 struct tty *tp; 2160 int rw; 2161{ 2162 struct com_s *com; 2163 cy_addr iobase; 2164 int unit; 2165 2166 unit = DEV_TO_UNIT(tp->t_dev); 2167 com = com_addr(unit); 2168 iobase = com->iobase; 2169 disable_intr(); 2170 if (rw & FWRITE) { 2171 com->obufs[0].l_queued = FALSE; 2172 com->obufs[1].l_queued = FALSE; 2173 if (com->state & CS_ODONE) 2174 com_events -= LOTS_OF_EVENTS; 2175 com->state &= ~(CS_ODONE | CS_BUSY); 2176 com->tp->t_state &= ~TS_BUSY; 2177 } 2178 if (rw & FREAD) { 2179 com_events -= (com->iptr - com->ibuf); 2180 com->iptr = com->ibuf; 2181 } 2182 if (tp->t_state & TS_TTSTOP) { 2183 com->state &= ~CS_TTGO; 2184 if (com->intr_enable & CD1400_SRER_TXRDY) { 2185 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 2186 cd_outb(iobase, CD1400_SRER, 2187 com->intr_enable &= ~CD1400_SRER_TXRDY); 2188 } 2189 } else { 2190 com->state |= CS_TTGO; 2191 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2192 && !(com->intr_enable & CD1400_SRER_TXRDY)) { 2193 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 2194 cd_outb(iobase, CD1400_SRER, 2195 com->intr_enable |= CD1400_SRER_TXRDY); 2196 } 2197 } 2198 enable_intr(); 2199 2200 /* XXX should clear h/w fifos too. */ 2201} 2202 2203struct tty * 2204siodevtotty(dev) 2205 dev_t dev; 2206{ 2207 int mynor; 2208 int unit; 2209 2210 mynor = minor(dev); 2211 if (mynor & CONTROL_MASK) 2212 return (NULL); 2213 unit = MINOR_TO_UNIT(mynor); 2214 if ((u_int) unit >= NSIO) 2215 return (NULL); 2216 return (&sio_tty[unit]); 2217} 2218 2219static int 2220commctl(com, bits, how) 2221 struct com_s *com; 2222 int bits; 2223 int how; 2224{ 2225 cy_addr iobase; 2226 int mcr; 2227 int msr; 2228 2229 if (how == DMGET) { 2230 if (com->channel_control & CD1400_CCR_RCVEN) 2231 bits |= TIOCM_LE; 2232 mcr = com->mcr_image; 2233 if (mcr & MCR_DTR) 2234 bits |= TIOCM_DTR; 2235 if (mcr & MCR_RTS) 2236 /* XXX wired on for Cyclom-8Ys */ 2237 bits |= TIOCM_RTS; 2238 msr = com->prev_modem_status; 2239 if (msr & MSR_CTS) 2240 bits |= TIOCM_CTS; 2241 if (msr & MSR_DCD) 2242 bits |= TIOCM_CD; 2243 if (msr & MSR_DSR) 2244 bits |= TIOCM_DSR; 2245 if (msr & MSR_RI) 2246 /* XXX not connected except for Cyclom-16Y? */ 2247 bits |= TIOCM_RI; 2248 return (bits); 2249 } 2250 iobase = com->iobase; 2251 mcr = 0; 2252 if (bits & TIOCM_DTR) 2253 mcr |= MCR_DTR; 2254 if (bits & TIOCM_RTS) 2255 mcr |= MCR_RTS; 2256 disable_intr(); 2257 switch (how) { 2258 case DMSET: 2259 com->mcr_image = mcr; 2260 cd_outb(iobase, CD1400_MSVR1, mcr); 2261 cd_outb(iobase, CD1400_MSVR2, mcr); 2262 break; 2263 case DMBIS: 2264 com->mcr_image = mcr = com->mcr_image | mcr; 2265 cd_outb(iobase, CD1400_MSVR1, mcr); 2266 cd_outb(iobase, CD1400_MSVR2, mcr); 2267 break; 2268 case DMBIC: 2269 com->mcr_image = mcr = com->mcr_image & ~mcr; 2270 cd_outb(iobase, CD1400_MSVR1, mcr); 2271 cd_outb(iobase, CD1400_MSVR2, mcr); 2272 break; 2273 } 2274 enable_intr(); 2275 return (0); 2276} 2277 2278static void 2279siosettimeout() 2280{ 2281 struct com_s *com; 2282 bool_t someopen; 2283 int unit; 2284 2285 /* 2286 * Set our timeout period to 1 second if no polled devices are open. 2287 * Otherwise set it to max(1/200, 1/hz). 2288 * Enable timeouts iff some device is open. 2289 */ 2290 untimeout(comwakeup, (void *)NULL); 2291 sio_timeout = hz; 2292 someopen = FALSE; 2293 for (unit = 0; unit < NSIO; ++unit) { 2294 com = com_addr(unit); 2295 if (com != NULL && com->tp != NULL 2296 && com->tp->t_state & TS_ISOPEN) { 2297 someopen = TRUE; 2298#if 0 2299 if (com->poll || com->poll_output) { 2300 sio_timeout = hz > 200 ? hz / 200 : 1; 2301 break; 2302 } 2303#endif 2304 } 2305 } 2306 if (someopen) { 2307 sio_timeouts_until_log = hz / sio_timeout; 2308 timeout(comwakeup, (void *)NULL, sio_timeout); 2309 } else { 2310 /* Flush error messages, if any. */ 2311 sio_timeouts_until_log = 1; 2312 comwakeup((void *)NULL); 2313 untimeout(comwakeup, (void *)NULL); 2314 } 2315} 2316 2317static void 2318comwakeup(chan) 2319 void *chan; 2320{ 2321 struct com_s *com; 2322 int unit; 2323 2324 timeout(comwakeup, (void *)NULL, sio_timeout); 2325 2326#if 0 2327 /* 2328 * Recover from lost output interrupts. 2329 * Poll any lines that don't use interrupts. 2330 */ 2331 for (unit = 0; unit < NSIO; ++unit) { 2332 com = com_addr(unit); 2333 if (com != NULL 2334 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2335 disable_intr(); 2336 siointr1(com); 2337 enable_intr(); 2338 } 2339 } 2340#endif 2341 2342 /* 2343 * Check for and log errors, but not too often. 2344 */ 2345 if (--sio_timeouts_until_log > 0) 2346 return; 2347 sio_timeouts_until_log = hz / sio_timeout; 2348 for (unit = 0; unit < NSIO; ++unit) { 2349 int errnum; 2350 2351 com = com_addr(unit); 2352 if (com == NULL) 2353 continue; 2354 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2355 u_int delta; 2356 u_long total; 2357 2358 disable_intr(); 2359 delta = com->delta_error_counts[errnum]; 2360 com->delta_error_counts[errnum] = 0; 2361 enable_intr(); 2362 if (delta == 0) 2363 continue; 2364 total = com->error_counts[errnum] += delta; 2365 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 2366 unit, delta, error_desc[errnum], 2367 delta == 1 ? "" : "s", total); 2368#if 0 2369 /* 2370 * XXX if we resurrect this then we should move 2371 * the dropping of the ftl to somewhere with less 2372 * latency. 2373 */ 2374 if (errnum == CE_OVERRUN && com->hasfifo 2375 && com->ftl > FIFO_TRIGGER_1) { 2376 static u_char ftl_in_bytes[] = 2377 { 1, 4, 8, 14, }; 2378 2379 com->ftl_init = FIFO_TRIGGER_8; 2380#define FIFO_TRIGGER_DELTA FIFO_TRIGGER_4 2381 com->ftl_max = 2382 com->ftl -= FIFO_TRIGGER_DELTA; 2383 outb(com->iobase + com_fifo, 2384 FIFO_ENABLE | com->ftl); 2385 log(LOG_DEBUG, 2386 "sio%d: reduced fifo trigger level to %d\n", 2387 unit, 2388 ftl_in_bytes[com->ftl 2389 / FIFO_TRIGGER_DELTA]); 2390 } 2391#endif 2392 } 2393 } 2394} 2395 2396static void 2397disc_optim(tp, t, com) 2398 struct tty *tp; 2399 struct termios *t; 2400 struct com_s *com; 2401{ 2402#ifndef SOFT_HOTCHAR 2403 cy_addr iobase; 2404 u_char opt; 2405#endif 2406 2407 /* 2408 * XXX can skip a lot more cases if Smarts. Maybe 2409 * (IGNCR | ISTRIP | IXOFF | IXON) in c_iflag. But perhaps we 2410 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. 2411 */ 2412 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP 2413 | IXOFF | IXON)) 2414 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2415 && (!(t->c_iflag & PARMRK) || 2416 (t->c_iflag & (IGNPAR|IGNBRK)) == (IGNPAR|IGNBRK)) 2417 && !(t->c_lflag & (ECHO | ECHONL | ICANON | IEXTEN | ISIG 2418 | PENDIN)) 2419 && linesw[tp->t_line].l_rint == ttyinput) 2420 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2421 else 2422 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2423 /* 2424 * Prepare to reduce input latency for packet 2425 * discplines with a end of packet character. 2426 */ 2427 if (tp->t_line == SLIPDISC) 2428 com->hotchar = 0xc0; 2429 else if (tp->t_line == PPPDISC) 2430 com->hotchar = 0x7e; 2431 else 2432 com->hotchar = 0; 2433#ifndef SOFT_HOTCHAR 2434 iobase = com->iobase; 2435 cd_outb(iobase, CD1400_CAR, com->unit & CD1400_CAR_CHAN); 2436 opt = com->cor[2] & ~CD1400_COR3_SCD34; 2437 if (com->hotchar != 0) { 2438 cd_outb(iobase, CD1400_SCHR3, com->hotchar); 2439 cd_outb(iobase, CD1400_SCHR4, com->hotchar); 2440 opt |= CD1400_COR3_SCD34; 2441 } 2442 if (opt != com->cor[2]) { 2443 cd_outb(iobase, CD1400_COR3, com->cor[2] = opt); 2444 cd1400_channel_cmd(com->iobase, 2445 CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 2446 } 2447#endif 2448} 2449 2450#ifdef Smarts 2451/* standard line discipline input routine */ 2452int 2453cyinput(c, tp) 2454 int c; 2455 struct tty *tp; 2456{ 2457 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 2458 * bits, as they are done by the CD1400. Hardly worth the effort, 2459 * given that high-throughput sessions are raw anyhow. 2460 */ 2461} 2462#endif /* Smarts */ 2463 2464static int 2465comspeed(speed, prescaler_io) 2466 speed_t speed; 2467 int *prescaler_io; 2468{ 2469 int actual; 2470 int error; 2471 int divider; 2472 int prescaler; 2473 int prescaler_unit; 2474 2475 if (speed == 0) 2476 return (0); 2477 if (speed < 0 || speed > 150000) 2478 return (-1); 2479 2480 /* determine which prescaler to use */ 2481 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2482 prescaler_unit--, prescaler >>= 2) { 2483 if (CY_CLOCK / prescaler / speed > 63) 2484 break; 2485 } 2486 2487 divider = (CY_CLOCK / prescaler * 2 / speed + 1) / 2; /* round off */ 2488 if (divider > 255) 2489 divider = 255; 2490 actual = CY_CLOCK/prescaler/divider; 2491 error = ((actual - speed) * 2000 / speed + 1) / 2; /* percentage */ 2492 2493 /* 3.0% max error tolerance */ 2494 if (error < -30 || error > 30) 2495 return (-1); 2496 2497#if 0 2498 printf("prescaler = %d (%d)\n", prescaler, prescaler_unit); 2499 printf("divider = %d (%x)\n", divider, divider); 2500 printf("actual = %d\n", actual); 2501 printf("error = %d\n", error); 2502#endif 2503 2504 *prescaler_io = prescaler_unit; 2505 return (divider); 2506} 2507 2508static void 2509cd1400_channel_cmd(iobase, cmd) 2510 cy_addr iobase; 2511 int cmd; 2512{ 2513 /* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed, 2514 as the card is probed every round? Replaced delaycount with 8k. 2515 Either delaycount has to be implemented in FreeBSD or more sensible 2516 way of doing these should be implemented. DELAY isn't enough here. 2517 */ 2518 u_int maxwait = 5 * 8 * 1024; /* approx. 5 ms */ 2519 2520 /* wait for processing of previous command to complete */ 2521 while (cd_inb(iobase, CD1400_CCR) && maxwait--) 2522 ; 2523 2524 if (!maxwait) 2525 log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n", 2526 5 * 8 * 1024); 2527 2528 cd_outb(iobase, CD1400_CCR, cmd); 2529} 2530 2531#ifdef CyDebug 2532/* useful in ddb */ 2533void 2534cystatus(unit) 2535 int unit; 2536{ 2537 struct com_s *com; 2538 cy_addr iobase; 2539 u_int ocount; 2540 struct tty *tp; 2541 2542 com = com_addr(unit); 2543 printf("info for channel %d\n", unit); 2544 printf("------------------\n"); 2545 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2546 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2547 if (com == NULL) 2548 return; 2549 iobase = com->iobase; 2550 printf("\n"); 2551 printf("cd1400 base address:\\tt%p\n", iobase); 2552 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 2553 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2554 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2555 com->cor[0], com->cor[1], com->cor[2]); 2556 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2557 cd_inb(iobase, CD1400_SRER), com->intr_enable); 2558 printf("service request register:\t0x%02x\n", 2559 cd_inb(iobase, CD1400_SVRR)); 2560 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2561 cd_inb(iobase, CD1400_MSVR2), com->prev_modem_status); 2562 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2563 cd_inb(iobase, CD1400_RIR), cd_inb(iobase, CD1400_TIR), 2564 cd_inb(iobase, CD1400_MIR)); 2565 printf("\n"); 2566 printf("com state:\t\t\t0x%02x\n", com->state); 2567 printf("calls to comstart():\t\t%d (%d useful)\n", 2568 com->start_count, com->start_real); 2569 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2570 ocount = 0; 2571 if (com->obufs[0].l_queued) 2572 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2573 if (com->obufs[1].l_queued) 2574 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2575 printf("tx buffer chars:\t\t%u\n", ocount); 2576 printf("received chars:\t\t\t%d\n", com->bytes_in); 2577 printf("received exceptions:\t\t%d\n", com->recv_exception); 2578 printf("modem signal deltas:\t\t%d\n", com->mdm); 2579 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2580 printf("\n"); 2581 tp = com->tp; 2582 if (tp != NULL) { 2583 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2584 printf("upper layer queue lengths:\t%d raw, %d canon, %d output\n", 2585 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 2586 } else 2587 printf("tty state:\t\t\tclosed\n"); 2588} 2589#endif /* CyDebug */ 2590 2591#endif /* NCY > 0 */
| 2139 splx(s); 2140} 2141 2142void 2143siostop(tp, rw) 2144 struct tty *tp; 2145 int rw; 2146{ 2147 struct com_s *com; 2148 cy_addr iobase; 2149 int unit; 2150 2151 unit = DEV_TO_UNIT(tp->t_dev); 2152 com = com_addr(unit); 2153 iobase = com->iobase; 2154 disable_intr(); 2155 if (rw & FWRITE) { 2156 com->obufs[0].l_queued = FALSE; 2157 com->obufs[1].l_queued = FALSE; 2158 if (com->state & CS_ODONE) 2159 com_events -= LOTS_OF_EVENTS; 2160 com->state &= ~(CS_ODONE | CS_BUSY); 2161 com->tp->t_state &= ~TS_BUSY; 2162 } 2163 if (rw & FREAD) { 2164 com_events -= (com->iptr - com->ibuf); 2165 com->iptr = com->ibuf; 2166 } 2167 if (tp->t_state & TS_TTSTOP) { 2168 com->state &= ~CS_TTGO; 2169 if (com->intr_enable & CD1400_SRER_TXRDY) { 2170 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 2171 cd_outb(iobase, CD1400_SRER, 2172 com->intr_enable &= ~CD1400_SRER_TXRDY); 2173 } 2174 } else { 2175 com->state |= CS_TTGO; 2176 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2177 && !(com->intr_enable & CD1400_SRER_TXRDY)) { 2178 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 2179 cd_outb(iobase, CD1400_SRER, 2180 com->intr_enable |= CD1400_SRER_TXRDY); 2181 } 2182 } 2183 enable_intr(); 2184 2185 /* XXX should clear h/w fifos too. */ 2186} 2187 2188struct tty * 2189siodevtotty(dev) 2190 dev_t dev; 2191{ 2192 int mynor; 2193 int unit; 2194 2195 mynor = minor(dev); 2196 if (mynor & CONTROL_MASK) 2197 return (NULL); 2198 unit = MINOR_TO_UNIT(mynor); 2199 if ((u_int) unit >= NSIO) 2200 return (NULL); 2201 return (&sio_tty[unit]); 2202} 2203 2204static int 2205commctl(com, bits, how) 2206 struct com_s *com; 2207 int bits; 2208 int how; 2209{ 2210 cy_addr iobase; 2211 int mcr; 2212 int msr; 2213 2214 if (how == DMGET) { 2215 if (com->channel_control & CD1400_CCR_RCVEN) 2216 bits |= TIOCM_LE; 2217 mcr = com->mcr_image; 2218 if (mcr & MCR_DTR) 2219 bits |= TIOCM_DTR; 2220 if (mcr & MCR_RTS) 2221 /* XXX wired on for Cyclom-8Ys */ 2222 bits |= TIOCM_RTS; 2223 msr = com->prev_modem_status; 2224 if (msr & MSR_CTS) 2225 bits |= TIOCM_CTS; 2226 if (msr & MSR_DCD) 2227 bits |= TIOCM_CD; 2228 if (msr & MSR_DSR) 2229 bits |= TIOCM_DSR; 2230 if (msr & MSR_RI) 2231 /* XXX not connected except for Cyclom-16Y? */ 2232 bits |= TIOCM_RI; 2233 return (bits); 2234 } 2235 iobase = com->iobase; 2236 mcr = 0; 2237 if (bits & TIOCM_DTR) 2238 mcr |= MCR_DTR; 2239 if (bits & TIOCM_RTS) 2240 mcr |= MCR_RTS; 2241 disable_intr(); 2242 switch (how) { 2243 case DMSET: 2244 com->mcr_image = mcr; 2245 cd_outb(iobase, CD1400_MSVR1, mcr); 2246 cd_outb(iobase, CD1400_MSVR2, mcr); 2247 break; 2248 case DMBIS: 2249 com->mcr_image = mcr = com->mcr_image | mcr; 2250 cd_outb(iobase, CD1400_MSVR1, mcr); 2251 cd_outb(iobase, CD1400_MSVR2, mcr); 2252 break; 2253 case DMBIC: 2254 com->mcr_image = mcr = com->mcr_image & ~mcr; 2255 cd_outb(iobase, CD1400_MSVR1, mcr); 2256 cd_outb(iobase, CD1400_MSVR2, mcr); 2257 break; 2258 } 2259 enable_intr(); 2260 return (0); 2261} 2262 2263static void 2264siosettimeout() 2265{ 2266 struct com_s *com; 2267 bool_t someopen; 2268 int unit; 2269 2270 /* 2271 * Set our timeout period to 1 second if no polled devices are open. 2272 * Otherwise set it to max(1/200, 1/hz). 2273 * Enable timeouts iff some device is open. 2274 */ 2275 untimeout(comwakeup, (void *)NULL); 2276 sio_timeout = hz; 2277 someopen = FALSE; 2278 for (unit = 0; unit < NSIO; ++unit) { 2279 com = com_addr(unit); 2280 if (com != NULL && com->tp != NULL 2281 && com->tp->t_state & TS_ISOPEN) { 2282 someopen = TRUE; 2283#if 0 2284 if (com->poll || com->poll_output) { 2285 sio_timeout = hz > 200 ? hz / 200 : 1; 2286 break; 2287 } 2288#endif 2289 } 2290 } 2291 if (someopen) { 2292 sio_timeouts_until_log = hz / sio_timeout; 2293 timeout(comwakeup, (void *)NULL, sio_timeout); 2294 } else { 2295 /* Flush error messages, if any. */ 2296 sio_timeouts_until_log = 1; 2297 comwakeup((void *)NULL); 2298 untimeout(comwakeup, (void *)NULL); 2299 } 2300} 2301 2302static void 2303comwakeup(chan) 2304 void *chan; 2305{ 2306 struct com_s *com; 2307 int unit; 2308 2309 timeout(comwakeup, (void *)NULL, sio_timeout); 2310 2311#if 0 2312 /* 2313 * Recover from lost output interrupts. 2314 * Poll any lines that don't use interrupts. 2315 */ 2316 for (unit = 0; unit < NSIO; ++unit) { 2317 com = com_addr(unit); 2318 if (com != NULL 2319 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2320 disable_intr(); 2321 siointr1(com); 2322 enable_intr(); 2323 } 2324 } 2325#endif 2326 2327 /* 2328 * Check for and log errors, but not too often. 2329 */ 2330 if (--sio_timeouts_until_log > 0) 2331 return; 2332 sio_timeouts_until_log = hz / sio_timeout; 2333 for (unit = 0; unit < NSIO; ++unit) { 2334 int errnum; 2335 2336 com = com_addr(unit); 2337 if (com == NULL) 2338 continue; 2339 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2340 u_int delta; 2341 u_long total; 2342 2343 disable_intr(); 2344 delta = com->delta_error_counts[errnum]; 2345 com->delta_error_counts[errnum] = 0; 2346 enable_intr(); 2347 if (delta == 0) 2348 continue; 2349 total = com->error_counts[errnum] += delta; 2350 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 2351 unit, delta, error_desc[errnum], 2352 delta == 1 ? "" : "s", total); 2353#if 0 2354 /* 2355 * XXX if we resurrect this then we should move 2356 * the dropping of the ftl to somewhere with less 2357 * latency. 2358 */ 2359 if (errnum == CE_OVERRUN && com->hasfifo 2360 && com->ftl > FIFO_TRIGGER_1) { 2361 static u_char ftl_in_bytes[] = 2362 { 1, 4, 8, 14, }; 2363 2364 com->ftl_init = FIFO_TRIGGER_8; 2365#define FIFO_TRIGGER_DELTA FIFO_TRIGGER_4 2366 com->ftl_max = 2367 com->ftl -= FIFO_TRIGGER_DELTA; 2368 outb(com->iobase + com_fifo, 2369 FIFO_ENABLE | com->ftl); 2370 log(LOG_DEBUG, 2371 "sio%d: reduced fifo trigger level to %d\n", 2372 unit, 2373 ftl_in_bytes[com->ftl 2374 / FIFO_TRIGGER_DELTA]); 2375 } 2376#endif 2377 } 2378 } 2379} 2380 2381static void 2382disc_optim(tp, t, com) 2383 struct tty *tp; 2384 struct termios *t; 2385 struct com_s *com; 2386{ 2387#ifndef SOFT_HOTCHAR 2388 cy_addr iobase; 2389 u_char opt; 2390#endif 2391 2392 /* 2393 * XXX can skip a lot more cases if Smarts. Maybe 2394 * (IGNCR | ISTRIP | IXOFF | IXON) in c_iflag. But perhaps we 2395 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. 2396 */ 2397 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP 2398 | IXOFF | IXON)) 2399 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2400 && (!(t->c_iflag & PARMRK) || 2401 (t->c_iflag & (IGNPAR|IGNBRK)) == (IGNPAR|IGNBRK)) 2402 && !(t->c_lflag & (ECHO | ECHONL | ICANON | IEXTEN | ISIG 2403 | PENDIN)) 2404 && linesw[tp->t_line].l_rint == ttyinput) 2405 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2406 else 2407 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2408 /* 2409 * Prepare to reduce input latency for packet 2410 * discplines with a end of packet character. 2411 */ 2412 if (tp->t_line == SLIPDISC) 2413 com->hotchar = 0xc0; 2414 else if (tp->t_line == PPPDISC) 2415 com->hotchar = 0x7e; 2416 else 2417 com->hotchar = 0; 2418#ifndef SOFT_HOTCHAR 2419 iobase = com->iobase; 2420 cd_outb(iobase, CD1400_CAR, com->unit & CD1400_CAR_CHAN); 2421 opt = com->cor[2] & ~CD1400_COR3_SCD34; 2422 if (com->hotchar != 0) { 2423 cd_outb(iobase, CD1400_SCHR3, com->hotchar); 2424 cd_outb(iobase, CD1400_SCHR4, com->hotchar); 2425 opt |= CD1400_COR3_SCD34; 2426 } 2427 if (opt != com->cor[2]) { 2428 cd_outb(iobase, CD1400_COR3, com->cor[2] = opt); 2429 cd1400_channel_cmd(com->iobase, 2430 CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 2431 } 2432#endif 2433} 2434 2435#ifdef Smarts 2436/* standard line discipline input routine */ 2437int 2438cyinput(c, tp) 2439 int c; 2440 struct tty *tp; 2441{ 2442 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 2443 * bits, as they are done by the CD1400. Hardly worth the effort, 2444 * given that high-throughput sessions are raw anyhow. 2445 */ 2446} 2447#endif /* Smarts */ 2448 2449static int 2450comspeed(speed, prescaler_io) 2451 speed_t speed; 2452 int *prescaler_io; 2453{ 2454 int actual; 2455 int error; 2456 int divider; 2457 int prescaler; 2458 int prescaler_unit; 2459 2460 if (speed == 0) 2461 return (0); 2462 if (speed < 0 || speed > 150000) 2463 return (-1); 2464 2465 /* determine which prescaler to use */ 2466 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2467 prescaler_unit--, prescaler >>= 2) { 2468 if (CY_CLOCK / prescaler / speed > 63) 2469 break; 2470 } 2471 2472 divider = (CY_CLOCK / prescaler * 2 / speed + 1) / 2; /* round off */ 2473 if (divider > 255) 2474 divider = 255; 2475 actual = CY_CLOCK/prescaler/divider; 2476 error = ((actual - speed) * 2000 / speed + 1) / 2; /* percentage */ 2477 2478 /* 3.0% max error tolerance */ 2479 if (error < -30 || error > 30) 2480 return (-1); 2481 2482#if 0 2483 printf("prescaler = %d (%d)\n", prescaler, prescaler_unit); 2484 printf("divider = %d (%x)\n", divider, divider); 2485 printf("actual = %d\n", actual); 2486 printf("error = %d\n", error); 2487#endif 2488 2489 *prescaler_io = prescaler_unit; 2490 return (divider); 2491} 2492 2493static void 2494cd1400_channel_cmd(iobase, cmd) 2495 cy_addr iobase; 2496 int cmd; 2497{ 2498 /* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed, 2499 as the card is probed every round? Replaced delaycount with 8k. 2500 Either delaycount has to be implemented in FreeBSD or more sensible 2501 way of doing these should be implemented. DELAY isn't enough here. 2502 */ 2503 u_int maxwait = 5 * 8 * 1024; /* approx. 5 ms */ 2504 2505 /* wait for processing of previous command to complete */ 2506 while (cd_inb(iobase, CD1400_CCR) && maxwait--) 2507 ; 2508 2509 if (!maxwait) 2510 log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n", 2511 5 * 8 * 1024); 2512 2513 cd_outb(iobase, CD1400_CCR, cmd); 2514} 2515 2516#ifdef CyDebug 2517/* useful in ddb */ 2518void 2519cystatus(unit) 2520 int unit; 2521{ 2522 struct com_s *com; 2523 cy_addr iobase; 2524 u_int ocount; 2525 struct tty *tp; 2526 2527 com = com_addr(unit); 2528 printf("info for channel %d\n", unit); 2529 printf("------------------\n"); 2530 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2531 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2532 if (com == NULL) 2533 return; 2534 iobase = com->iobase; 2535 printf("\n"); 2536 printf("cd1400 base address:\\tt%p\n", iobase); 2537 cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); 2538 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2539 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2540 com->cor[0], com->cor[1], com->cor[2]); 2541 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2542 cd_inb(iobase, CD1400_SRER), com->intr_enable); 2543 printf("service request register:\t0x%02x\n", 2544 cd_inb(iobase, CD1400_SVRR)); 2545 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2546 cd_inb(iobase, CD1400_MSVR2), com->prev_modem_status); 2547 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2548 cd_inb(iobase, CD1400_RIR), cd_inb(iobase, CD1400_TIR), 2549 cd_inb(iobase, CD1400_MIR)); 2550 printf("\n"); 2551 printf("com state:\t\t\t0x%02x\n", com->state); 2552 printf("calls to comstart():\t\t%d (%d useful)\n", 2553 com->start_count, com->start_real); 2554 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2555 ocount = 0; 2556 if (com->obufs[0].l_queued) 2557 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2558 if (com->obufs[1].l_queued) 2559 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2560 printf("tx buffer chars:\t\t%u\n", ocount); 2561 printf("received chars:\t\t\t%d\n", com->bytes_in); 2562 printf("received exceptions:\t\t%d\n", com->recv_exception); 2563 printf("modem signal deltas:\t\t%d\n", com->mdm); 2564 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2565 printf("\n"); 2566 tp = com->tp; 2567 if (tp != NULL) { 2568 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2569 printf("upper layer queue lengths:\t%d raw, %d canon, %d output\n", 2570 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 2571 } else 2572 printf("tty state:\t\t\tclosed\n"); 2573} 2574#endif /* CyDebug */ 2575 2576#endif /* NCY > 0 */
|