33#include "opt_compat.h" 34#include "cy.h" 35 36/* 37 * TODO: 38 * Atomic COR change. 39 * Consoles. 40 */ 41 42/* 43 * Temporary compile-time configuration options. 44 */ 45#define RxFifoThreshold (CD1400_RX_FIFO_SIZE / 2) 46 /* Number of chars in the receiver FIFO before an 47 * an interrupt is generated. Should depend on 48 * line speed. Needs to be about 6 on a 486DX33 49 * for 4 active ports at 115200 bps. Why doesn't 50 * 10 work? 51 */ 52#define PollMode /* Use polling-based irq service routine, not the 53 * hardware svcack lines. Must be defined for 54 * Cyclom-16Y boards. Less efficient for Cyclom-8Ys, 55 * and stops 4 * 115200 bps from working. 56 */ 57#undef Smarts /* Enable slightly more CD1400 intelligence. Mainly 58 * the output CR/LF processing, plus we can avoid a 59 * few checks usually done in ttyinput(). 60 * 61 * XXX not fully implemented, and not particularly 62 * worthwhile. 63 */ 64#undef CyDebug /* Include debugging code (not very expensive). */ 65 66/* These will go away. */ 67#undef SOFT_CTS_OFLOW 68#define SOFT_HOTCHAR 69 70#include <sys/param.h> 71#include <sys/systm.h> 72#include <sys/bus.h> 73#include <sys/conf.h> 74#include <sys/fcntl.h> 75#include <sys/interrupt.h> 76#include <sys/kernel.h> 77#include <sys/lock.h> 78#include <sys/malloc.h> 79#include <sys/mutex.h> 80#include <sys/syslog.h> 81#include <sys/tty.h> 82 83#include <machine/psl.h> 84 85#include <i386/isa/isa_device.h> 86#include <i386/isa/cyreg.h> 87#include <i386/isa/ic/cd1400.h> 88 89#ifndef COMPAT_OLDISA 90#error "The cy device requires the old isa compatibility shims" 91#endif 92 93#ifdef SMP 94 95#include <machine/smptests.h> /** xxx_LOCK */ 96 97#ifdef USE_COMLOCK 98#define COM_LOCK() mtx_lock_spin(&com_mtx) 99#define COM_UNLOCK() mtx_unlock_spin(&com_mtx) 100#else 101#define COM_LOCK() 102#define COM_UNLOCK() 103#endif /* USE_COMLOCK */ 104 105#else /* SMP */ 106 107#define COM_LOCK() 108#define COM_UNLOCK() 109 110#endif /* SMP */ 111 112extern struct mtx com_mtx; 113 114/* 115 * Dictionary so that I can name everything *sio* or *com* to compare with 116 * sio.c. There is also lots of ugly formatting and unnecessary ifdefs to 117 * simplify the comparision. These will go away. 118 */ 119#define LSR_BI CD1400_RDSR_BREAK 120#define LSR_FE CD1400_RDSR_FE 121#define LSR_OE CD1400_RDSR_OE 122#define LSR_PE CD1400_RDSR_PE 123#define MCR_DTR CD1400_MSVR2_DTR 124#define MCR_RTS CD1400_MSVR1_RTS 125#define MSR_CTS CD1400_MSVR2_CTS 126#define MSR_DCD CD1400_MSVR2_CD 127#define MSR_DSR CD1400_MSVR2_DSR 128#define MSR_RI CD1400_MSVR2_RI 129#define NSIO (NCY * CY_MAX_PORTS) 130#define comconsole cyconsole 131#define comdefaultrate cydefaultrate 132#define com_events cy_events 133#define comhardclose cyhardclose 134#define commctl cymctl 135#define comparam cyparam 136#define comspeed cyspeed 137#define comstart cystart 138#define comwakeup cywakeup 139#define p_com_addr p_cy_addr 140#define sioattach cyattach 141#define sioclose cyclose 142#define siodriver cydriver 143#define siodtrwakeup cydtrwakeup 144#define sioinput cyinput 145#define siointr cyintr 146#define siointr1 cyintr1 147#define sioioctl cyioctl 148#define sioopen cyopen 149#define siopoll cypoll 150#define sioprobe cyprobe 151#define siosettimeout cysettimeout 152#define siosetwater cysetwater 153#define comstop cystop 154#define siowrite cywrite 155#define sio_ih cy_ih 156#define sio_irec cy_irec 157#define sio_timeout cy_timeout 158#define sio_timeout_handle cy_timeout_handle 159#define sio_timeouts_until_log cy_timeouts_until_log 160 161#define CY_MAX_PORTS (CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s) 162 163/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ 164#define CD1400_xIVR_CHAN_SHIFT 3 165#define CD1400_xIVR_CHAN 0x1F 166 167/* 168 * ETC states. com->etc may also contain a hardware ETC command value, 169 * meaning that execution of that command is pending. 170 */ 171#define ETC_NONE 0 /* we depend on bzero() setting this */ 172#define ETC_BREAK_STARTING 1 173#define ETC_BREAK_STARTED 2 174#define ETC_BREAK_ENDING 3 175#define ETC_BREAK_ENDED 4 176 177#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 178 179#define CALLOUT_MASK 0x80 180#define CONTROL_MASK 0x60 181#define CONTROL_INIT_STATE 0x20 182#define CONTROL_LOCK_STATE 0x40 183#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 184#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 185/* 186 * Not all of the magic is parametrized in the following macros. 16 and 187 * 0xff are related to the bitfields in a udev_t. CY_MAX_PORTS must be 188 * ((0xff & ~MINOR_MAGIC_MASK) + 1) for things to work. 189 */ 190#define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS \ 191 | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK)) 192#define UNIT_TO_MINOR(unit) (((unit) / CY_MAX_PORTS) << 16 \ 193 | (((unit) & 0xff) & ~MINOR_MAGIC_MASK)) 194 195/* 196 * com state bits. 197 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 198 * than the other bits so that they can be tested as a group without masking 199 * off the low bits. 200 * 201 * The following com and tty flags correspond closely: 202 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and 203 * comstop()) 204 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) 205 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 206 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 207 * TS_FLUSH is not used. 208 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 209 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 210 */ 211#define CS_BUSY 0x80 /* output in progress */ 212#define CS_TTGO 0x40 /* output not stopped by XOFF */ 213#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 214#define CS_CHECKMSR 1 /* check of MSR scheduled */ 215#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 216#define CS_DTR_OFF 0x10 /* DTR held off */ 217#define CS_ODONE 4 /* output completed */ 218#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 219#define CSE_ODONE 1 /* output transmitted */ 220 221static char const * const error_desc[] = { 222#define CE_OVERRUN 0 223 "silo overflow", 224#define CE_INTERRUPT_BUF_OVERFLOW 1 225 "interrupt-level buffer overflow", 226#define CE_TTY_BUF_OVERFLOW 2 227 "tty-level buffer overflow", 228}; 229 230#define CE_NTYPES 3 231#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 232 233/* types. XXX - should be elsewhere */ 234typedef u_char bool_t; /* boolean */ 235typedef u_char volatile *cy_addr; 236 237/* queue of linear buffers */ 238struct lbq { 239 u_char *l_head; /* next char to process */ 240 u_char *l_tail; /* one past the last char to process */ 241 struct lbq *l_next; /* next in queue */ 242 bool_t l_queued; /* nonzero if queued */ 243}; 244 245/* com device structure */ 246struct com_s { 247 u_char state; /* miscellaneous flag bits */ 248 bool_t active_out; /* nonzero if the callout device is open */ 249#if 0 250 u_char cfcr_image; /* copy of value written to CFCR */ 251#endif 252 u_char etc; /* pending Embedded Transmit Command */ 253 u_char extra_state; /* more flag bits, separate for order trick */ 254#if 0 255 u_char fifo_image; /* copy of value written to FIFO */ 256#endif 257 u_char gfrcr_image; /* copy of value read from GFRCR */ 258#if 0 259 bool_t hasfifo; /* nonzero for 16550 UARTs */ 260 bool_t loses_outints; /* nonzero if device loses output interrupts */ 261#endif 262 u_char mcr_dtr; /* MCR bit that is wired to DTR */ 263 u_char mcr_image; /* copy of value written to MCR */ 264 u_char mcr_rts; /* MCR bit that is wired to RTS */ 265#if 0 266#ifdef COM_MULTIPORT 267 bool_t multiport; /* is this unit part of a multiport device? */ 268#endif /* COM_MULTIPORT */ 269 bool_t no_irq; /* nonzero if irq is not attached */ 270 bool_t poll; /* nonzero if polling is required */ 271 bool_t poll_output; /* nonzero if polling for output is required */ 272#endif 273 int unit; /* unit number */ 274 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 275#if 0 276 u_int tx_fifo_size; 277#endif 278 u_int wopeners; /* # processes waiting for DCD in open() */ 279 280 /* 281 * The high level of the driver never reads status registers directly 282 * because there would be too many side effects to handle conveniently. 283 * Instead, it reads copies of the registers stored here by the 284 * interrupt handler. 285 */ 286 u_char last_modem_status; /* last MSR read by intr handler */ 287 u_char prev_modem_status; /* last MSR handled by high level */ 288 289 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 290 u_char *ibuf; /* start of input buffer */ 291 u_char *ibufend; /* end of input buffer */ 292 u_char *ibufold; /* old input buffer, to be freed */ 293 u_char *ihighwater; /* threshold in input buffer */ 294 u_char *iptr; /* next free spot in input buffer */ 295 int ibufsize; /* size of ibuf (not include error bytes) */ 296 int ierroff; /* offset of error bytes in ibuf */ 297 298 struct lbq obufq; /* head of queue of output buffers */ 299 struct lbq obufs[2]; /* output buffers */ 300 301 int cy_align; /* index for register alignment */ 302 cy_addr cy_iobase; /* base address of this port's cyclom */ 303 cy_addr iobase; /* base address of this port's cd1400 */ 304 int mcr_rts_reg; /* cd1400 reg number of reg holding mcr_rts */ 305 306 struct tty *tp; /* cross reference */ 307 308 /* Initial state. */ 309 struct termios it_in; /* should be in struct tty */ 310 struct termios it_out; 311 312 /* Lock state. */ 313 struct termios lt_in; /* should be in struct tty */ 314 struct termios lt_out; 315 316 bool_t do_timestamp; 317 bool_t do_dcd_timestamp; 318 struct timeval timestamp; 319 struct timeval dcd_timestamp; 320 321 u_long bytes_in; /* statistics */ 322 u_long bytes_out; 323 u_int delta_error_counts[CE_NTYPES]; 324 u_long error_counts[CE_NTYPES]; 325 326 u_int recv_exception; /* exception chars received */ 327 u_int mdm; /* modem signal changes */ 328#ifdef CyDebug 329 u_int start_count; /* no. of calls to comstart() */ 330 u_int start_real; /* no. of calls that did something */ 331#endif 332 u_char car; /* CD1400 CAR shadow (if first unit in cd) */ 333 u_char channel_control;/* CD1400 CCR control command shadow */ 334 u_char cor[3]; /* CD1400 COR1-3 shadows */ 335 u_char intr_enable; /* CD1400 SRER shadow */ 336 337 /* 338 * Data area for output buffers. Someday we should build the output 339 * buffer queue without copying data. 340 */ 341 u_char obuf1[256]; 342 u_char obuf2[256]; 343}; 344 345/* PCI driver entry point. */ 346int cyattach_common(cy_addr cy_iobase, int cy_align); 347ointhand2_t siointr; 348 349static int cy_units(cy_addr cy_iobase, int cy_align); 350static int sioattach(struct isa_device *dev); 351static void cd1400_channel_cmd(struct com_s *com, int cmd); 352static void cd1400_channel_cmd_wait(struct com_s *com); 353static void cd_etc(struct com_s *com, int etc); 354static int cd_getreg(struct com_s *com, int reg); 355static void cd_setreg(struct com_s *com, int reg, int val); 356static timeout_t siodtrwakeup; 357static void comhardclose(struct com_s *com); 358static void sioinput(struct com_s *com); 359#if 0 360static void siointr1(struct com_s *com); 361#endif 362static int commctl(struct com_s *com, int bits, int how); 363static int comparam(struct tty *tp, struct termios *t); 364static void siopoll(void *arg); 365static int sioprobe(struct isa_device *dev); 366static void siosettimeout(void); 367static int siosetwater(struct com_s *com, speed_t speed); 368static int comspeed(speed_t speed, u_long cy_clock, int *prescaler_io); 369static void comstart(struct tty *tp); 370static void comstop(struct tty *tp, int rw); 371static timeout_t comwakeup; 372static void disc_optim(struct tty *tp, struct termios *t, 373 struct com_s *com); 374 375#ifdef CyDebug 376void cystatus(int unit); 377#endif 378 379static char driver_name[] = "cy"; 380 381/* table and macro for fast conversion from a unit number to its com struct */ 382static struct com_s *p_com_addr[NSIO]; 383#define com_addr(unit) (p_com_addr[unit]) 384 385struct isa_driver siodriver = { 386 INTR_TYPE_TTY | INTR_FAST, 387 sioprobe, 388 sioattach, 389 driver_name 390}; 391COMPAT_ISA_DRIVER(cy, cydriver); /* XXX */ 392 393static d_open_t sioopen; 394static d_close_t sioclose; 395static d_write_t siowrite; 396static d_ioctl_t sioioctl; 397 398#define CDEV_MAJOR 48 399static struct cdevsw sio_cdevsw = { 400 .d_open = sioopen, 401 .d_close = sioclose, 402 .d_read = ttyread, 403 .d_write = siowrite, 404 .d_ioctl = sioioctl, 405 .d_poll = ttypoll, 406 .d_name = driver_name, 407 .d_maj = CDEV_MAJOR, 408 .d_flags = D_TTY, 409 .d_kqfilter = ttykqfilter, 410}; 411 412static int comconsole = -1; 413static speed_t comdefaultrate = TTYDEF_SPEED; 414static u_int com_events; /* input chars + weighted output completions */ 415static void *sio_ih; 416static int sio_timeout; 417static int sio_timeouts_until_log; 418static struct callout_handle sio_timeout_handle 419 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 420 421#ifdef CyDebug 422static u_int cd_inbs; 423static u_int cy_inbs; 424static u_int cd_outbs; 425static u_int cy_outbs; 426static u_int cy_svrr_probes; 427static u_int cy_timeouts; 428#endif 429 430static int cy_chip_offset[] = { 431 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00, 432}; 433static int cy_nr_cd1400s[NCY]; 434static int cy_total_devices; 435#undef RxFifoThreshold 436static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); 437 438static int 439sioprobe(dev) 440 struct isa_device *dev; 441{ 442 cy_addr iobase; 443 444 iobase = (cy_addr)dev->id_maddr; 445 446 /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ 447 cy_inb(iobase, CY16_RESET, 0); /* XXX? */ 448 DELAY(500); /* wait for the board to get its act together */ 449 450 /* this is needed to get the board out of reset */ 451 cy_outb(iobase, CY_CLEAR_INTR, 0, 0); 452 DELAY(500); 453 454 return (cy_units(iobase, 0) == 0 ? 0 : -1); 455} 456 457static int 458cy_units(cy_iobase, cy_align) 459 cy_addr cy_iobase; 460 int cy_align; 461{ 462 int cyu; 463 u_char firmware_version; 464 int i; 465 cy_addr iobase; 466 467 for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { 468 iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align); 469 470 /* wait for chip to become ready for new command */ 471 for (i = 0; i < 10; i++) { 472 DELAY(50); 473 if (!cd_inb(iobase, CD1400_CCR, cy_align)) 474 break; 475 } 476 477 /* clear the GFRCR register */ 478 cd_outb(iobase, CD1400_GFRCR, cy_align, 0); 479 480 /* issue a reset command */ 481 cd_outb(iobase, CD1400_CCR, cy_align, 482 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 483 484 /* XXX bogus initialization to avoid a gcc bug/warning. */ 485 firmware_version = 0; 486 487 /* wait for the CD1400 to initialize itself */ 488 for (i = 0; i < 200; i++) { 489 DELAY(50); 490 491 /* retrieve firmware version */ 492 firmware_version = cd_inb(iobase, CD1400_GFRCR, 493 cy_align); 494 if ((firmware_version & 0xf0) == 0x40) 495 break; 496 } 497 498 /* 499 * Anything in the 0x40-0x4F range is fine. 500 * If one CD1400 is bad then we don't support higher 501 * numbered good ones on this board. 502 */ 503 if ((firmware_version & 0xf0) != 0x40) 504 break; 505 } 506 return (cyu); 507} 508 509static int 510sioattach(isdp) 511 struct isa_device *isdp; 512{ 513 int adapter; 514 515 adapter = cyattach_common((cy_addr) isdp->id_maddr, 0); 516 if (adapter < 0) 517 return (0); 518 519 /* 520 * XXX 521 * This kludge is to allow ISA/PCI device specifications in the 522 * kernel config file to be in any order. 523 */ 524 if (isdp->id_unit != adapter) { 525 printf("cy%d: attached as cy%d\n", isdp->id_unit, adapter); 526 isdp->id_unit = adapter; /* XXX */ 527 } 528 isdp->id_ointr = siointr; 529 /* isdp->id_ri_flags |= RI_FAST; XXX unimplemented - use newbus! */ 530 return (1); 531} 532 533int 534cyattach_common(cy_iobase, cy_align) 535 cy_addr cy_iobase; 536 int cy_align; 537{ 538 int adapter; 539 int cyu; 540 u_char firmware_version; 541 cy_addr iobase; 542 int minorbase; 543 int ncyu; 544 int unit; 545 546 adapter = cy_total_devices; 547 if ((u_int)adapter >= NCY) { 548 printf( 549 "cy%d: can't attach adapter: insufficient cy devices configured\n", 550 adapter); 551 return (-1); 552 } 553 ncyu = cy_units(cy_iobase, cy_align); 554 if (ncyu == 0) 555 return (-1); 556 cy_nr_cd1400s[adapter] = ncyu; 557 cy_total_devices++; 558 559 unit = adapter * CY_MAX_PORTS; 560 for (cyu = 0; cyu < ncyu; ++cyu) { 561 int cdu; 562 563 iobase = (cy_addr) (cy_iobase 564 + (cy_chip_offset[cyu] << cy_align)); 565 firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); 566 567 /* Set up a receive timeout period of than 1+ ms. */ 568 cd_outb(iobase, CD1400_PPR, cy_align, 569 howmany(CY_CLOCK(firmware_version) 570 / CD1400_PPR_PRESCALER, 1000)); 571 572 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { 573 struct com_s *com; 574 int s; 575 576 com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT | M_ZERO); 577 if (com == NULL) 578 break; 579 com->unit = unit; 580 com->gfrcr_image = firmware_version; 581 if (CY_RTS_DTR_SWAPPED(firmware_version)) { 582 com->mcr_dtr = MCR_RTS; 583 com->mcr_rts = MCR_DTR; 584 com->mcr_rts_reg = CD1400_MSVR2; 585 } else { 586 com->mcr_dtr = MCR_DTR; 587 com->mcr_rts = MCR_RTS; 588 com->mcr_rts_reg = CD1400_MSVR1; 589 } 590 com->dtr_wait = 3 * hz; 591 com->obufs[0].l_head = com->obuf1; 592 com->obufs[1].l_head = com->obuf2; 593 594 com->cy_align = cy_align; 595 com->cy_iobase = cy_iobase; 596 com->iobase = iobase; 597 com->car = ~CD1400_CAR_CHAN; 598 599 /* 600 * We don't use all the flags from <sys/ttydefaults.h> since they 601 * are only relevant for logins. It's important to have echo off 602 * initially so that the line doesn't start blathering before the 603 * echo flag can be turned off. 604 */ 605 com->it_in.c_iflag = 0; 606 com->it_in.c_oflag = 0; 607 com->it_in.c_cflag = TTYDEF_CFLAG; 608 com->it_in.c_lflag = 0; 609 if (unit == comconsole) { 610 com->it_in.c_iflag = TTYDEF_IFLAG; 611 com->it_in.c_oflag = TTYDEF_OFLAG; 612 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 613 com->it_in.c_lflag = TTYDEF_LFLAG; 614 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 615 } 616 if (siosetwater(com, com->it_in.c_ispeed) != 0) { 617 free(com, M_DEVBUF); 618 return (0); 619 } 620 termioschars(&com->it_in); 621 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 622 com->it_out = com->it_in; 623 624 s = spltty(); 625 com_addr(unit) = com; 626 splx(s); 627 628 if (sio_ih == NULL) { 629 swi_add(&tty_ithd, "tty:cy", siopoll, NULL, SWI_TTY, 0, 630 &sio_ih); 631 } 632 minorbase = UNIT_TO_MINOR(unit); 633 make_dev(&sio_cdevsw, minorbase, 634 UID_ROOT, GID_WHEEL, 0600, "ttyc%r%r", adapter, 635 unit % CY_MAX_PORTS); 636 make_dev(&sio_cdevsw, minorbase | CONTROL_INIT_STATE, 637 UID_ROOT, GID_WHEEL, 0600, "ttyic%r%r", adapter, 638 unit % CY_MAX_PORTS); 639 make_dev(&sio_cdevsw, minorbase | CONTROL_LOCK_STATE, 640 UID_ROOT, GID_WHEEL, 0600, "ttylc%r%r", adapter, 641 unit % CY_MAX_PORTS); 642 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK, 643 UID_UUCP, GID_DIALER, 0660, "cuac%r%r", adapter, 644 unit % CY_MAX_PORTS); 645 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK | CONTROL_INIT_STATE, 646 UID_UUCP, GID_DIALER, 0660, "cuaic%r%r", adapter, 647 unit % CY_MAX_PORTS); 648 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK | CONTROL_LOCK_STATE, 649 UID_UUCP, GID_DIALER, 0660, "cualc%r%r", adapter, 650 unit % CY_MAX_PORTS); 651 } 652 } 653 654 /* ensure an edge for the next interrupt */ 655 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 656 657 return (adapter); 658} 659 660static int 661sioopen(dev, flag, mode, td) 662 dev_t dev; 663 int flag; 664 int mode; 665 struct thread *td; 666{ 667 struct com_s *com; 668 int error; 669 int mynor; 670 int s; 671 struct tty *tp; 672 int unit; 673 674 mynor = minor(dev); 675 unit = MINOR_TO_UNIT(mynor); 676 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) 677 return (ENXIO); 678 if (mynor & CONTROL_MASK) 679 return (0); 680 tp = dev->si_tty = com->tp = ttymalloc(com->tp); 681 s = spltty(); 682 /* 683 * We jump to this label after all non-interrupted sleeps to pick 684 * up any changes of the device state. 685 */ 686open_top: 687 while (com->state & CS_DTR_OFF) { 688 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0); 689 if (error != 0) 690 goto out; 691 } 692 if (tp->t_state & TS_ISOPEN) { 693 /* 694 * The device is open, so everything has been initialized. 695 * Handle conflicts. 696 */ 697 if (mynor & CALLOUT_MASK) { 698 if (!com->active_out) { 699 error = EBUSY; 700 goto out; 701 } 702 } else { 703 if (com->active_out) { 704 if (flag & O_NONBLOCK) { 705 error = EBUSY; 706 goto out; 707 } 708 error = tsleep(&com->active_out, 709 TTIPRI | PCATCH, "cybi", 0); 710 if (error != 0) 711 goto out; 712 goto open_top; 713 } 714 } 715 if (tp->t_state & TS_XCLUDE && 716 suser(td)) { 717 error = EBUSY; 718 goto out; 719 } 720 } else { 721 /* 722 * The device isn't open, so there are no conflicts. 723 * Initialize it. Initialization is done twice in many 724 * cases: to preempt sleeping callin opens if we are 725 * callout, and to complete a callin open after DCD rises. 726 */ 727 tp->t_oproc = comstart; 728 tp->t_stop = comstop; 729 tp->t_param = comparam; 730 tp->t_dev = dev; 731 tp->t_termios = mynor & CALLOUT_MASK 732 ? com->it_out : com->it_in; 733 734 /* Encode per-board unit in LIVR for access in intr routines. */ 735 cd_setreg(com, CD1400_LIVR, 736 (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); 737 738 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 739#if 0 740 com->poll = com->no_irq; 741 com->poll_output = com->loses_outints; 742#endif 743 ++com->wopeners; 744 error = comparam(tp, &tp->t_termios); 745 --com->wopeners; 746 if (error != 0) 747 goto out; 748#if 0 749 if (com->hasfifo) { 750 /* 751 * (Re)enable and flush fifos. 752 * 753 * Certain SMC chips cause problems if the fifos 754 * are enabled while input is ready. Turn off the 755 * fifo if necessary to clear the input. We test 756 * the input ready bit after enabling the fifos 757 * since we've already enabled them in comparam() 758 * and to handle races between enabling and fresh 759 * input. 760 */ 761 while (TRUE) { 762 outb(iobase + com_fifo, 763 FIFO_RCV_RST | FIFO_XMT_RST 764 | com->fifo_image); 765 DELAY(100); 766 if (!(inb(com->line_status_port) & LSR_RXRDY)) 767 break; 768 outb(iobase + com_fifo, 0); 769 DELAY(100); 770 (void) inb(com->data_port); 771 } 772 } 773 774 critical_enter(); 775 COM_LOCK(); 776 (void) inb(com->line_status_port); 777 (void) inb(com->data_port); 778 com->prev_modem_status = com->last_modem_status 779 = inb(com->modem_status_port); 780 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS 781 | IER_EMSC); 782 COM_UNLOCK(); 783 critical_exit(); 784#else /* !0 */ 785 /* 786 * Flush fifos. This requires a full channel reset which 787 * also disables the transmitter and receiver. Recover 788 * from this. 789 */ 790 cd1400_channel_cmd(com, 791 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); 792 cd1400_channel_cmd(com, com->channel_control); 793 794 critical_enter(); 795 COM_LOCK(); 796 com->prev_modem_status = com->last_modem_status 797 = cd_getreg(com, CD1400_MSVR2); 798 cd_setreg(com, CD1400_SRER, 799 com->intr_enable 800 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 801 COM_UNLOCK(); 802 critical_exit(); 803#endif /* 0 */ 804 /* 805 * Handle initial DCD. Callout devices get a fake initial 806 * DCD (trapdoor DCD). If we are callout, then any sleeping 807 * callin opens get woken up and resume sleeping on "cybi" 808 * instead of "cydcd". 809 */ 810 /* 811 * XXX `mynor & CALLOUT_MASK' should be 812 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 813 * TRAPDOOR_CARRIER is the default initial state for callout 814 * devices and SOFT_CARRIER is like CLOCAL except it hides 815 * the true carrier. 816 */ 817 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 818 (*linesw[tp->t_line].l_modem)(tp, 1); 819 } 820 /* 821 * Wait for DCD if necessary. 822 */ 823 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 824 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 825 ++com->wopeners; 826 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0); 827 --com->wopeners; 828 if (error != 0) 829 goto out; 830 goto open_top; 831 } 832 error = (*linesw[tp->t_line].l_open)(dev, tp); 833 disc_optim(tp, &tp->t_termios, com); 834 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 835 com->active_out = TRUE; 836 siosettimeout(); 837out: 838 splx(s); 839 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 840 comhardclose(com); 841 return (error); 842} 843 844static int 845sioclose(dev, flag, mode, td) 846 dev_t dev; 847 int flag; 848 int mode; 849 struct thread *td; 850{ 851 struct com_s *com; 852 int mynor; 853 int s; 854 struct tty *tp; 855 856 mynor = minor(dev); 857 if (mynor & CONTROL_MASK) 858 return (0); 859 com = com_addr(MINOR_TO_UNIT(mynor)); 860 tp = com->tp; 861 s = spltty(); 862 cd_etc(com, CD1400_ETC_STOPBREAK); 863 (*linesw[tp->t_line].l_close)(tp, flag); 864 disc_optim(tp, &tp->t_termios, com); 865 comstop(tp, FREAD | FWRITE); 866 comhardclose(com); 867 ttyclose(tp); 868 siosettimeout(); 869 splx(s); 870#ifdef broken /* session holds a ref to the tty; can't deallocate */ 871 ttyfree(tp); 872 com->tp = NULL; 873#endif 874 return (0); 875} 876 877static void 878comhardclose(com) 879 struct com_s *com; 880{ 881 cy_addr iobase; 882 int s; 883 struct tty *tp; 884 int unit; 885 886 unit = com->unit; 887 iobase = com->iobase; 888 s = spltty(); 889#if 0 890 com->poll = FALSE; 891 com->poll_output = FALSE; 892#endif 893 com->do_timestamp = 0; 894#if 0 895 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 896#else 897 /* XXX */ 898 critical_enter(); 899 COM_LOCK(); 900 com->etc = ETC_NONE; 901 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); 902 COM_UNLOCK(); 903 critical_exit(); 904 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 905#endif 906 907 { 908#if 0 909 outb(iobase + com_ier, 0); 910#else 911 critical_enter(); 912 COM_LOCK(); 913 cd_setreg(com, CD1400_SRER, com->intr_enable = 0); 914 COM_UNLOCK(); 915 critical_exit(); 916#endif 917 tp = com->tp; 918 if ((tp->t_cflag & HUPCL) 919 /* 920 * XXX we will miss any carrier drop between here and the 921 * next open. Perhaps we should watch DCD even when the 922 * port is closed; it is not sufficient to check it at 923 * the next open because it might go up and down while 924 * we're not watching. 925 */ 926 || (!com->active_out 927 && !(com->prev_modem_status & MSR_DCD) 928 && !(com->it_in.c_cflag & CLOCAL)) 929 || !(tp->t_state & TS_ISOPEN)) { 930 (void)commctl(com, TIOCM_DTR, DMBIC); 931 932 /* Disable receiver (leave transmitter enabled). */ 933 com->channel_control = CD1400_CCR_CMDCHANCTL 934 | CD1400_CCR_XMTEN 935 | CD1400_CCR_RCVDIS; 936 cd1400_channel_cmd(com, com->channel_control); 937 938 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 939 timeout(siodtrwakeup, com, com->dtr_wait); 940 com->state |= CS_DTR_OFF; 941 } 942 } 943 } 944#if 0 945 if (com->hasfifo) { 946 /* 947 * Disable fifos so that they are off after controlled 948 * reboots. Some BIOSes fail to detect 16550s when the 949 * fifos are enabled. 950 */ 951 outb(iobase + com_fifo, 0); 952 } 953#endif 954 com->active_out = FALSE; 955 wakeup(&com->active_out); 956 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 957 splx(s); 958} 959 960static int 961siowrite(dev, uio, flag) 962 dev_t dev; 963 struct uio *uio; 964 int flag; 965{ 966 int mynor; 967 struct tty *tp; 968 int unit; 969 970 mynor = minor(dev); 971 if (mynor & CONTROL_MASK) 972 return (ENODEV); 973 974 unit = MINOR_TO_UNIT(mynor); 975 tp = com_addr(unit)->tp; 976 /* 977 * (XXX) We disallow virtual consoles if the physical console is 978 * a serial port. This is in case there is a display attached that 979 * is not the console. In that situation we don't need/want the X 980 * server taking over the console. 981 */ 982 if (constty != NULL && unit == comconsole) 983 constty = NULL; 984#ifdef Smarts 985 /* XXX duplicate ttwrite(), but without so much output processing on 986 * CR & LF chars. Hardly worth the effort, given that high-throughput 987 * sessions are raw anyhow. 988 */ 989#else 990 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 991#endif 992} 993 994static void 995siodtrwakeup(chan) 996 void *chan; 997{ 998 struct com_s *com; 999 1000 com = (struct com_s *)chan; 1001 com->state &= ~CS_DTR_OFF; 1002 wakeup(&com->dtr_wait); 1003} 1004 1005/* 1006 * This function: 1007 * a) needs to be called with COM_LOCK() held, and 1008 * b) needs to return with COM_LOCK() held. 1009 */ 1010static void 1011sioinput(com) 1012 struct com_s *com; 1013{ 1014 u_char *buf; 1015 int incc; 1016 u_char line_status; 1017 int recv_data; 1018 struct tty *tp; 1019 1020 buf = com->ibuf; 1021 tp = com->tp; 1022 if (!(tp->t_state & TS_ISOPEN)) { 1023 com_events -= (com->iptr - com->ibuf); 1024 com->iptr = com->ibuf; 1025 return; 1026 } 1027 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 1028 /* 1029 * Avoid the grotesquely inefficient lineswitch routine 1030 * (ttyinput) in "raw" mode. It usually takes about 450 1031 * instructions (that's without canonical processing or echo!). 1032 * slinput is reasonably fast (usually 40 instructions plus 1033 * call overhead). 1034 */ 1035 1036 do { 1037 /* 1038 * This may look odd, but it is using save-and-enable 1039 * semantics instead of the save-and-disable semantics 1040 * that are used everywhere else. 1041 */ 1042 COM_UNLOCK(); 1043 critical_exit(); 1044 incc = com->iptr - buf; 1045 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 1046 && (com->state & CS_RTS_IFLOW 1047 || tp->t_iflag & IXOFF) 1048 && !(tp->t_state & TS_TBLOCK)) 1049 ttyblock(tp); 1050 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 1051 += b_to_q((char *)buf, incc, &tp->t_rawq); 1052 buf += incc; 1053 tk_nin += incc; 1054 tk_rawcc += incc; 1055 tp->t_rawcc += incc; 1056 ttwakeup(tp); 1057 if (tp->t_state & TS_TTSTOP 1058 && (tp->t_iflag & IXANY 1059 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 1060 tp->t_state &= ~TS_TTSTOP; 1061 tp->t_lflag &= ~FLUSHO; 1062 comstart(tp); 1063 } 1064 critical_enter(); 1065 COM_LOCK(); 1066 } while (buf < com->iptr); 1067 } else { 1068 do { 1069 /* 1070 * This may look odd, but it is using save-and-enable 1071 * semantics instead of the save-and-disable semantics 1072 * that are used everywhere else. 1073 */ 1074 COM_UNLOCK(); 1075 critical_exit(); 1076 line_status = buf[com->ierroff]; 1077 recv_data = *buf++; 1078 if (line_status 1079 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 1080 if (line_status & LSR_BI) 1081 recv_data |= TTY_BI; 1082 if (line_status & LSR_FE) 1083 recv_data |= TTY_FE; 1084 if (line_status & LSR_OE) 1085 recv_data |= TTY_OE; 1086 if (line_status & LSR_PE) 1087 recv_data |= TTY_PE; 1088 } 1089 (*linesw[tp->t_line].l_rint)(recv_data, tp); 1090 critical_enter(); 1091 COM_LOCK(); 1092 } while (buf < com->iptr); 1093 } 1094 com_events -= (com->iptr - com->ibuf); 1095 com->iptr = com->ibuf; 1096 1097 /* 1098 * There is now room for another low-level buffer full of input, 1099 * so enable RTS if it is now disabled and there is room in the 1100 * high-level buffer. 1101 */ 1102 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) && 1103 !(tp->t_state & TS_TBLOCK)) 1104#if 0 1105 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 1106#else 1107 cd_setreg(com, com->mcr_rts_reg, 1108 com->mcr_image |= com->mcr_rts); 1109#endif 1110} 1111 1112void 1113siointr(unit) 1114 int unit; 1115{ 1116 int baseu; 1117 int cy_align; 1118 cy_addr cy_iobase; 1119 int cyu; 1120 cy_addr iobase; 1121 u_char status; 1122 1123 COM_LOCK(); /* XXX could this be placed down lower in the loop? */ 1124 1125 baseu = unit * CY_MAX_PORTS; 1126 cy_align = com_addr(baseu)->cy_align; 1127 cy_iobase = com_addr(baseu)->cy_iobase; 1128 1129 /* check each CD1400 in turn */ 1130 for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { 1131 iobase = (cy_addr) (cy_iobase 1132 + (cy_chip_offset[cyu] << cy_align)); 1133 /* poll to see if it has any work */ 1134 status = cd_inb(iobase, CD1400_SVRR, cy_align); 1135 if (status == 0) 1136 continue; 1137#ifdef CyDebug 1138 ++cy_svrr_probes; 1139#endif 1140 /* service requests as appropriate, giving priority to RX */ 1141 if (status & CD1400_SVRR_RXRDY) { 1142 struct com_s *com; 1143 u_int count; 1144 u_char *ioptr; 1145 u_char line_status; 1146 u_char recv_data; 1147 u_char serv_type; 1148#ifdef PollMode 1149 u_char save_rir; 1150#endif 1151 1152#ifdef PollMode 1153 save_rir = cd_inb(iobase, CD1400_RIR, cy_align); 1154 1155 /* enter rx service */ 1156 cd_outb(iobase, CD1400_CAR, cy_align, save_rir); 1157 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1158 = save_rir & CD1400_CAR_CHAN; 1159 1160 serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); 1161 com = com_addr(baseu 1162 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1163 & CD1400_xIVR_CHAN)); 1164#else 1165 /* ack receive service */ 1166 serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); 1167 1168 com = com_addr(baseu + 1169 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1170 & CD1400_xIVR_CHAN)); 1171#endif 1172 1173 if (serv_type & CD1400_RIVR_EXCEPTION) { 1174 ++com->recv_exception; 1175 line_status = cd_inb(iobase, CD1400_RDSR, cy_align); 1176 /* break/unnattached error bits or real input? */ 1177 recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); 1178#ifndef SOFT_HOTCHAR 1179 if (line_status & CD1400_RDSR_SPECIAL 1180 && com->hotchar != 0) 1181 swi_sched(sio_ih, 0); 1182 1183#endif 1184#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ 1185 if (line_status & (LSR_PE|LSR_FE|LSR_BI)) { 1186 /* 1187 Don't store PE if IGNPAR and BI if IGNBRK, 1188 this hack allows "raw" tty optimization 1189 works even if IGN* is set. 1190 */ 1191 if ( com->tp == NULL 1192 || !(com->tp->t_state & TS_ISOPEN) 1193 || ((line_status & (LSR_PE|LSR_FE)) 1194 && (com->tp->t_iflag & IGNPAR)) 1195 || ((line_status & LSR_BI) 1196 && (com->tp->t_iflag & IGNBRK))) 1197 goto cont; 1198 if ( (line_status & (LSR_PE|LSR_FE)) 1199 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) 1200 && ((line_status & LSR_FE) 1201 || ((line_status & LSR_PE) 1202 && (com->tp->t_iflag & INPCK)))) 1203 recv_data = 0; 1204 } 1205#endif /* 1 */ 1206 ++com->bytes_in; 1207#ifdef SOFT_HOTCHAR 1208 if (com->hotchar != 0 && recv_data == com->hotchar) 1209 swi_sched(sio_ih, 0); 1210#endif 1211 ioptr = com->iptr; 1212 if (ioptr >= com->ibufend) 1213 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1214 else { 1215 if (com->do_timestamp) 1216 microtime(&com->timestamp); 1217 ++com_events; 1218 ioptr[0] = recv_data; 1219 ioptr[com->ierroff] = line_status; 1220 com->iptr = ++ioptr; 1221 if (ioptr == com->ihighwater 1222 && com->state & CS_RTS_IFLOW) 1223#if 0 1224 outb(com->modem_ctl_port, 1225 com->mcr_image &= ~MCR_RTS); 1226#else 1227 cd_outb(iobase, com->mcr_rts_reg, 1228 cy_align, 1229 com->mcr_image &= 1230 ~com->mcr_rts); 1231#endif 1232 if (line_status & LSR_OE) 1233 CE_RECORD(com, CE_OVERRUN); 1234 } 1235 goto cont; 1236 } else { 1237 int ifree; 1238 1239 count = cd_inb(iobase, CD1400_RDCR, cy_align); 1240 if (!count) 1241 goto cont; 1242 com->bytes_in += count; 1243 ioptr = com->iptr; 1244 ifree = com->ibufend - ioptr; 1245 if (count > ifree) { 1246 count -= ifree; 1247 com_events += ifree; 1248 if (ifree != 0) { 1249 if (com->do_timestamp) 1250 microtime(&com->timestamp); 1251 do { 1252 recv_data = cd_inb(iobase, 1253 CD1400_RDSR, 1254 cy_align); 1255#ifdef SOFT_HOTCHAR 1256 if (com->hotchar != 0 1257 && recv_data 1258 == com->hotchar) 1259 swi_sched(sio_ih, 0); 1260#endif 1261 ioptr[0] = recv_data; 1262 ioptr[com->ierroff] = 0; 1263 ++ioptr; 1264 } while (--ifree != 0); 1265 } 1266 com->delta_error_counts 1267 [CE_INTERRUPT_BUF_OVERFLOW] += count; 1268 do { 1269 recv_data = cd_inb(iobase, CD1400_RDSR, 1270 cy_align); 1271#ifdef SOFT_HOTCHAR 1272 if (com->hotchar != 0 1273 && recv_data == com->hotchar) 1274 swi_sched(sio_ih, 0); 1275#endif 1276 } while (--count != 0); 1277 } else { 1278 if (com->do_timestamp) 1279 microtime(&com->timestamp); 1280 if (ioptr <= com->ihighwater 1281 && ioptr + count > com->ihighwater 1282 && com->state & CS_RTS_IFLOW) 1283#if 0 1284 outb(com->modem_ctl_port, 1285 com->mcr_image &= ~MCR_RTS); 1286#else 1287 cd_outb(iobase, com->mcr_rts_reg, 1288 cy_align, 1289 com->mcr_image 1290 &= ~com->mcr_rts); 1291#endif 1292 com_events += count; 1293 do { 1294 recv_data = cd_inb(iobase, CD1400_RDSR, 1295 cy_align); 1296#ifdef SOFT_HOTCHAR 1297 if (com->hotchar != 0 1298 && recv_data == com->hotchar) 1299 swi_sched(sio_ih, 0); 1300#endif 1301 ioptr[0] = recv_data; 1302 ioptr[com->ierroff] = 0; 1303 ++ioptr; 1304 } while (--count != 0); 1305 } 1306 com->iptr = ioptr; 1307 } 1308cont: 1309 1310 /* terminate service context */ 1311#ifdef PollMode 1312 cd_outb(iobase, CD1400_RIR, cy_align, 1313 save_rir 1314 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); 1315#else 1316 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1317#endif 1318 } 1319 if (status & CD1400_SVRR_MDMCH) { 1320 struct com_s *com; 1321 u_char modem_status; 1322#ifdef PollMode 1323 u_char save_mir; 1324#else 1325 u_char vector; 1326#endif 1327 1328#ifdef PollMode 1329 save_mir = cd_inb(iobase, CD1400_MIR, cy_align); 1330 1331 /* enter modem service */ 1332 cd_outb(iobase, CD1400_CAR, cy_align, save_mir); 1333 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1334 = save_mir & CD1400_CAR_CHAN; 1335 1336 com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS 1337 + (save_mir & CD1400_MIR_CHAN)); 1338#else 1339 /* ack modem service */ 1340 vector = cy_inb(iobase, CY8_SVCACKM, cy_align); 1341 1342 com = com_addr(baseu 1343 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1344 & CD1400_xIVR_CHAN)); 1345#endif 1346 ++com->mdm; 1347 modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align); 1348 if (modem_status != com->last_modem_status) { 1349 if (com->do_dcd_timestamp 1350 && !(com->last_modem_status & MSR_DCD) 1351 && modem_status & MSR_DCD) 1352 microtime(&com->dcd_timestamp); 1353 1354 /* 1355 * Schedule high level to handle DCD changes. Note 1356 * that we don't use the delta bits anywhere. Some 1357 * UARTs mess them up, and it's easy to remember the 1358 * previous bits and calculate the delta. 1359 */ 1360 com->last_modem_status = modem_status; 1361 if (!(com->state & CS_CHECKMSR)) { 1362 com_events += LOTS_OF_EVENTS; 1363 com->state |= CS_CHECKMSR; 1364 swi_sched(sio_ih, 0); 1365 } 1366 1367#ifdef SOFT_CTS_OFLOW 1368 /* handle CTS change immediately for crisp flow ctl */ 1369 if (com->state & CS_CTS_OFLOW) { 1370 if (modem_status & MSR_CTS) { 1371 com->state |= CS_ODEVREADY; 1372 if (com->state >= (CS_BUSY | CS_TTGO 1373 | CS_ODEVREADY) 1374 && !(com->intr_enable 1375 & CD1400_SRER_TXRDY)) 1376 cd_outb(iobase, CD1400_SRER, 1377 cy_align, 1378 com->intr_enable 1379 = com->intr_enable 1380 & ~CD1400_SRER_TXMPTY 1381 | CD1400_SRER_TXRDY); 1382 } else { 1383 com->state &= ~CS_ODEVREADY; 1384 if (com->intr_enable 1385 & CD1400_SRER_TXRDY) 1386 cd_outb(iobase, CD1400_SRER, 1387 cy_align, 1388 com->intr_enable 1389 = com->intr_enable 1390 & ~CD1400_SRER_TXRDY 1391 | CD1400_SRER_TXMPTY); 1392 } 1393 } 1394#endif 1395 } 1396 1397 /* terminate service context */ 1398#ifdef PollMode 1399 cd_outb(iobase, CD1400_MIR, cy_align, 1400 save_mir 1401 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); 1402#else 1403 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1404#endif 1405 } 1406 if (status & CD1400_SVRR_TXRDY) { 1407 struct com_s *com; 1408#ifdef PollMode 1409 u_char save_tir; 1410#else 1411 u_char vector; 1412#endif 1413 1414#ifdef PollMode 1415 save_tir = cd_inb(iobase, CD1400_TIR, cy_align); 1416 1417 /* enter tx service */ 1418 cd_outb(iobase, CD1400_CAR, cy_align, save_tir); 1419 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1420 = save_tir & CD1400_CAR_CHAN; 1421 1422 com = com_addr(baseu 1423 + cyu * CD1400_NO_OF_CHANNELS 1424 + (save_tir & CD1400_TIR_CHAN)); 1425#else 1426 /* ack transmit service */ 1427 vector = cy_inb(iobase, CY8_SVCACKT, cy_align); 1428 1429 com = com_addr(baseu 1430 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1431 & CD1400_xIVR_CHAN)); 1432#endif 1433 1434 if (com->etc != ETC_NONE) { 1435 if (com->intr_enable & CD1400_SRER_TXRDY) { 1436 /* 1437 * Here due to sloppy SRER_TXRDY 1438 * enabling. Ignore. Come back when 1439 * tx is empty. 1440 */ 1441 cd_outb(iobase, CD1400_SRER, cy_align, 1442 com->intr_enable 1443 = (com->intr_enable 1444 & ~CD1400_SRER_TXRDY) 1445 | CD1400_SRER_TXMPTY); 1446 goto terminate_tx_service; 1447 } 1448 switch (com->etc) { 1449 case CD1400_ETC_SENDBREAK: 1450 case CD1400_ETC_STOPBREAK: 1451 /* 1452 * Start the command. Come back on 1453 * next tx empty interrupt, hopefully 1454 * after command has been executed. 1455 */ 1456 cd_outb(iobase, CD1400_COR2, cy_align, 1457 com->cor[1] |= CD1400_COR2_ETC); 1458 cd_outb(iobase, CD1400_TDR, cy_align, 1459 CD1400_ETC_CMD); 1460 cd_outb(iobase, CD1400_TDR, cy_align, 1461 com->etc); 1462 if (com->etc == CD1400_ETC_SENDBREAK) 1463 com->etc = ETC_BREAK_STARTING; 1464 else 1465 com->etc = ETC_BREAK_ENDING; 1466 goto terminate_tx_service; 1467 case ETC_BREAK_STARTING: 1468 /* 1469 * BREAK is now on. Continue with 1470 * SRER_TXMPTY processing, hopefully 1471 * don't come back. 1472 */ 1473 com->etc = ETC_BREAK_STARTED; 1474 break; 1475 case ETC_BREAK_STARTED: 1476 /* 1477 * Came back due to sloppy SRER_TXMPTY 1478 * enabling. Hope again. 1479 */ 1480 break; 1481 case ETC_BREAK_ENDING: 1482 /* 1483 * BREAK is now off. Continue with 1484 * SRER_TXMPTY processing and don't 1485 * come back. The SWI handler will 1486 * restart tx interrupts if necessary. 1487 */ 1488 cd_outb(iobase, CD1400_COR2, cy_align, 1489 com->cor[1] 1490 &= ~CD1400_COR2_ETC); 1491 com->etc = ETC_BREAK_ENDED; 1492 if (!(com->state & CS_ODONE)) { 1493 com_events += LOTS_OF_EVENTS; 1494 com->state |= CS_ODONE; 1495 swi_sched(sio_ih, 0); 1496 } 1497 break; 1498 case ETC_BREAK_ENDED: 1499 /* 1500 * Shouldn't get here. Hope again. 1501 */ 1502 break; 1503 } 1504 } 1505 if (com->intr_enable & CD1400_SRER_TXMPTY) { 1506 if (!(com->extra_state & CSE_ODONE)) { 1507 com_events += LOTS_OF_EVENTS; 1508 com->extra_state |= CSE_ODONE; 1509 swi_sched(sio_ih, 0); 1510 } 1511 cd_outb(iobase, CD1400_SRER, cy_align, 1512 com->intr_enable 1513 &= ~CD1400_SRER_TXMPTY); 1514 goto terminate_tx_service; 1515 } 1516 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1517 u_char *ioptr; 1518 u_int ocount; 1519 1520 ioptr = com->obufq.l_head; 1521 ocount = com->obufq.l_tail - ioptr; 1522 if (ocount > CD1400_TX_FIFO_SIZE) 1523 ocount = CD1400_TX_FIFO_SIZE; 1524 com->bytes_out += ocount; 1525 do 1526 cd_outb(iobase, CD1400_TDR, cy_align, 1527 *ioptr++); 1528 while (--ocount != 0); 1529 com->obufq.l_head = ioptr; 1530 if (ioptr >= com->obufq.l_tail) { 1531 struct lbq *qp; 1532 1533 qp = com->obufq.l_next; 1534 qp->l_queued = FALSE; 1535 qp = qp->l_next; 1536 if (qp != NULL) { 1537 com->obufq.l_head = qp->l_head; 1538 com->obufq.l_tail = qp->l_tail; 1539 com->obufq.l_next = qp; 1540 } else { 1541 /* output just completed */ 1542 com->state &= ~CS_BUSY; 1543 1544 /* 1545 * The setting of CSE_ODONE may be 1546 * stale here. We currently only 1547 * use it when CS_BUSY is set, and 1548 * fixing it when we clear CS_BUSY 1549 * is easiest. 1550 */ 1551 if (com->extra_state & CSE_ODONE) { 1552 com_events -= LOTS_OF_EVENTS; 1553 com->extra_state &= ~CSE_ODONE; 1554 } 1555 1556 cd_outb(iobase, CD1400_SRER, cy_align, 1557 com->intr_enable 1558 = (com->intr_enable 1559 & ~CD1400_SRER_TXRDY) 1560 | CD1400_SRER_TXMPTY); 1561 } 1562 if (!(com->state & CS_ODONE)) { 1563 com_events += LOTS_OF_EVENTS; 1564 com->state |= CS_ODONE; 1565 1566 /* handle at high level ASAP */ 1567 swi_sched(sio_ih, 0); 1568 } 1569 } 1570 } 1571 1572 /* terminate service context */ 1573terminate_tx_service: 1574#ifdef PollMode 1575 cd_outb(iobase, CD1400_TIR, cy_align, 1576 save_tir 1577 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); 1578#else 1579 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1580#endif 1581 } 1582 } 1583 1584 /* ensure an edge for the next interrupt */ 1585 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 1586 1587 swi_sched(sio_ih, 0); 1588 1589 COM_UNLOCK(); 1590} 1591 1592#if 0 1593static void 1594siointr1(com) 1595 struct com_s *com; 1596{ 1597} 1598#endif 1599 1600static int 1601sioioctl(dev, cmd, data, flag, td) 1602 dev_t dev; 1603 u_long cmd; 1604 caddr_t data; 1605 int flag; 1606 struct thread *td; 1607{ 1608 struct com_s *com; 1609 int error; 1610 int mynor; 1611 int s; 1612 struct tty *tp; 1613#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1614 int oldcmd; 1615 struct termios term; 1616#endif 1617 1618 mynor = minor(dev); 1619 com = com_addr(MINOR_TO_UNIT(mynor)); 1620 if (mynor & CONTROL_MASK) { 1621 struct termios *ct; 1622 1623 switch (mynor & CONTROL_MASK) { 1624 case CONTROL_INIT_STATE: 1625 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 1626 break; 1627 case CONTROL_LOCK_STATE: 1628 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 1629 break; 1630 default: 1631 return (ENODEV); /* /dev/nodev */ 1632 } 1633 switch (cmd) { 1634 case TIOCSETA: 1635 error = suser(td); 1636 if (error != 0) 1637 return (error); 1638 *ct = *(struct termios *)data; 1639 return (0); 1640 case TIOCGETA: 1641 *(struct termios *)data = *ct; 1642 return (0); 1643 case TIOCGETD: 1644 *(int *)data = TTYDISC; 1645 return (0); 1646 case TIOCGWINSZ: 1647 bzero(data, sizeof(struct winsize)); 1648 return (0); 1649 default: 1650 return (ENOTTY); 1651 } 1652 } 1653 tp = com->tp; 1654#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1655 term = tp->t_termios; 1656 oldcmd = cmd; 1657 error = ttsetcompat(tp, &cmd, data, &term); 1658 if (error != 0) 1659 return (error); 1660 if (cmd != oldcmd) 1661 data = (caddr_t)&term; 1662#endif 1663 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1664 int cc; 1665 struct termios *dt = (struct termios *)data; 1666 struct termios *lt = mynor & CALLOUT_MASK 1667 ? &com->lt_out : &com->lt_in; 1668 1669 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1670 | (dt->c_iflag & ~lt->c_iflag); 1671 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1672 | (dt->c_oflag & ~lt->c_oflag); 1673 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1674 | (dt->c_cflag & ~lt->c_cflag); 1675 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1676 | (dt->c_lflag & ~lt->c_lflag); 1677 for (cc = 0; cc < NCCS; ++cc) 1678 if (lt->c_cc[cc] != 0) 1679 dt->c_cc[cc] = tp->t_cc[cc]; 1680 if (lt->c_ispeed != 0) 1681 dt->c_ispeed = tp->t_ispeed; 1682 if (lt->c_ospeed != 0) 1683 dt->c_ospeed = tp->t_ospeed; 1684 } 1685 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); 1686 if (error != ENOIOCTL) 1687 return (error); 1688 s = spltty(); 1689 error = ttioctl(tp, cmd, data, flag); 1690 disc_optim(tp, &tp->t_termios, com); 1691 if (error != ENOIOCTL) { 1692 splx(s); 1693 return (error); 1694 } 1695 switch (cmd) { 1696 case TIOCSBRK: 1697#if 0 1698 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 1699#else 1700 cd_etc(com, CD1400_ETC_SENDBREAK); 1701#endif 1702 break; 1703 case TIOCCBRK: 1704#if 0 1705 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1706#else 1707 cd_etc(com, CD1400_ETC_STOPBREAK); 1708#endif 1709 break; 1710 case TIOCSDTR: 1711 (void)commctl(com, TIOCM_DTR, DMBIS); 1712 break; 1713 case TIOCCDTR: 1714 (void)commctl(com, TIOCM_DTR, DMBIC); 1715 break; 1716 /* 1717 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 1718 * changes get undone on the next call to comparam(). 1719 */ 1720 case TIOCMSET: 1721 (void)commctl(com, *(int *)data, DMSET); 1722 break; 1723 case TIOCMBIS: 1724 (void)commctl(com, *(int *)data, DMBIS); 1725 break; 1726 case TIOCMBIC: 1727 (void)commctl(com, *(int *)data, DMBIC); 1728 break; 1729 case TIOCMGET: 1730 *(int *)data = commctl(com, 0, DMGET); 1731 break; 1732 case TIOCMSDTRWAIT: 1733 /* must be root since the wait applies to following logins */ 1734 error = suser(td); 1735 if (error != 0) { 1736 splx(s); 1737 return (error); 1738 } 1739 com->dtr_wait = *(int *)data * hz / 100; 1740 break; 1741 case TIOCMGDTRWAIT: 1742 *(int *)data = com->dtr_wait * 100 / hz; 1743 break; 1744 case TIOCTIMESTAMP: 1745 com->do_timestamp = TRUE; 1746 *(struct timeval *)data = com->timestamp; 1747 break; 1748 case TIOCDCDTIMESTAMP: 1749 com->do_dcd_timestamp = TRUE; 1750 *(struct timeval *)data = com->dcd_timestamp; 1751 break; 1752 default: 1753 splx(s); 1754 return (ENOTTY); 1755 } 1756 splx(s); 1757 return (0); 1758} 1759 1760static void 1761siopoll(void *arg) 1762{ 1763 int unit; 1764 1765#ifdef CyDebug 1766 ++cy_timeouts; 1767#endif 1768 if (com_events == 0) 1769 return; 1770repeat: 1771 for (unit = 0; unit < NSIO; ++unit) { 1772 struct com_s *com; 1773 int incc; 1774 struct tty *tp; 1775 1776 com = com_addr(unit); 1777 if (com == NULL) 1778 continue; 1779 tp = com->tp; 1780 if (tp == NULL) { 1781 /* 1782 * XXX forget any events related to closed devices 1783 * (actually never opened devices) so that we don't 1784 * loop. 1785 */ 1786 critical_enter(); 1787 COM_LOCK(); 1788 incc = com->iptr - com->ibuf; 1789 com->iptr = com->ibuf; 1790 if (com->state & CS_CHECKMSR) { 1791 incc += LOTS_OF_EVENTS; 1792 com->state &= ~CS_CHECKMSR; 1793 } 1794 com_events -= incc; 1795 COM_UNLOCK(); 1796 critical_exit(); 1797 if (incc != 0) 1798 log(LOG_DEBUG, 1799 "sio%d: %d events for device with no tp\n", 1800 unit, incc); 1801 continue; 1802 } 1803 if (com->iptr != com->ibuf) { 1804 critical_enter(); 1805 COM_LOCK(); 1806 sioinput(com); 1807 COM_UNLOCK(); 1808 critical_exit(); 1809 } 1810 if (com->state & CS_CHECKMSR) { 1811 u_char delta_modem_status; 1812 1813 critical_enter(); 1814 COM_LOCK(); 1815 sioinput(com); 1816 delta_modem_status = com->last_modem_status 1817 ^ com->prev_modem_status; 1818 com->prev_modem_status = com->last_modem_status; 1819 com_events -= LOTS_OF_EVENTS; 1820 com->state &= ~CS_CHECKMSR; 1821 COM_UNLOCK(); 1822 critical_exit(); 1823 if (delta_modem_status & MSR_DCD) 1824 (*linesw[tp->t_line].l_modem) 1825 (tp, com->prev_modem_status & MSR_DCD); 1826 } 1827 if (com->extra_state & CSE_ODONE) { 1828 critical_enter(); 1829 COM_LOCK(); 1830 com_events -= LOTS_OF_EVENTS; 1831 com->extra_state &= ~CSE_ODONE; 1832 COM_UNLOCK(); 1833 critical_exit(); 1834 if (!(com->state & CS_BUSY)) { 1835 tp->t_state &= ~TS_BUSY; 1836 ttwwakeup(com->tp); 1837 } 1838 if (com->etc != ETC_NONE) { 1839 if (com->etc == ETC_BREAK_ENDED) 1840 com->etc = ETC_NONE; 1841 wakeup(&com->etc); 1842 } 1843 } 1844 if (com->state & CS_ODONE) { 1845 critical_enter(); 1846 COM_LOCK(); 1847 com_events -= LOTS_OF_EVENTS; 1848 com->state &= ~CS_ODONE; 1849 COM_UNLOCK(); 1850 critical_exit(); 1851 (*linesw[tp->t_line].l_start)(tp); 1852 } 1853 if (com_events == 0) 1854 break; 1855 } 1856 if (com_events >= LOTS_OF_EVENTS) 1857 goto repeat; 1858} 1859 1860static int 1861comparam(tp, t) 1862 struct tty *tp; 1863 struct termios *t; 1864{ 1865 int bits; 1866 int cflag; 1867 struct com_s *com; 1868 u_char cor_change; 1869 u_long cy_clock; 1870 int idivisor; 1871 int iflag; 1872 int iprescaler; 1873 int itimeout; 1874 int odivisor; 1875 int oprescaler; 1876 u_char opt; 1877 int s; 1878 int unit; 1879 1880 /* do historical conversions */ 1881 if (t->c_ispeed == 0) 1882 t->c_ispeed = t->c_ospeed; 1883 1884 unit = DEV_TO_UNIT(tp->t_dev); 1885 com = com_addr(unit); 1886 1887 /* check requested parameters */ 1888 cy_clock = CY_CLOCK(com->gfrcr_image); 1889 idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler); 1890 if (idivisor < 0) 1891 return (EINVAL); 1892 odivisor = comspeed(t->c_ospeed, cy_clock, &oprescaler); 1893 if (odivisor < 0) 1894 return (EINVAL); 1895 1896 /* parameters are OK, convert them to the com struct and the device */ 1897 s = spltty(); 1898 if (odivisor == 0) 1899 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 1900 else 1901 (void)commctl(com, TIOCM_DTR, DMBIS); 1902 1903 (void) siosetwater(com, t->c_ispeed); 1904 1905 /* XXX we don't actually change the speed atomically. */ 1906 1907 if (idivisor != 0) { 1908 cd_setreg(com, CD1400_RBPR, idivisor); 1909 cd_setreg(com, CD1400_RCOR, iprescaler); 1910 } 1911 if (odivisor != 0) { 1912 cd_setreg(com, CD1400_TBPR, odivisor); 1913 cd_setreg(com, CD1400_TCOR, oprescaler); 1914 } 1915 1916 /* 1917 * channel control 1918 * receiver enable 1919 * transmitter enable (always set) 1920 */ 1921 cflag = t->c_cflag; 1922 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 1923 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 1924 if (opt != com->channel_control) { 1925 com->channel_control = opt; 1926 cd1400_channel_cmd(com, opt); 1927 } 1928 1929#ifdef Smarts 1930 /* set special chars */ 1931 /* XXX if one is _POSIX_VDISABLE, can't use some others */ 1932 if (t->c_cc[VSTOP] != _POSIX_VDISABLE) 1933 cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); 1934 if (t->c_cc[VSTART] != _POSIX_VDISABLE) 1935 cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); 1936 if (t->c_cc[VINTR] != _POSIX_VDISABLE) 1937 cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); 1938 if (t->c_cc[VSUSP] != _POSIX_VDISABLE) 1939 cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); 1940#endif 1941 1942 /* 1943 * set channel option register 1 - 1944 * parity mode 1945 * stop bits 1946 * char length 1947 */ 1948 opt = 0; 1949 /* parity */ 1950 if (cflag & PARENB) { 1951 if (cflag & PARODD) 1952 opt |= CD1400_COR1_PARODD; 1953 opt |= CD1400_COR1_PARNORMAL; 1954 } 1955 iflag = t->c_iflag; 1956 if (!(iflag & INPCK)) 1957 opt |= CD1400_COR1_NOINPCK; 1958 bits = 1 + 1; 1959 /* stop bits */ 1960 if (cflag & CSTOPB) { 1961 ++bits; 1962 opt |= CD1400_COR1_STOP2; 1963 } 1964 /* char length */ 1965 switch (cflag & CSIZE) { 1966 case CS5: 1967 bits += 5; 1968 opt |= CD1400_COR1_CS5; 1969 break; 1970 case CS6: 1971 bits += 6; 1972 opt |= CD1400_COR1_CS6; 1973 break; 1974 case CS7: 1975 bits += 7; 1976 opt |= CD1400_COR1_CS7; 1977 break; 1978 default: 1979 bits += 8; 1980 opt |= CD1400_COR1_CS8; 1981 break; 1982 } 1983 cor_change = 0; 1984 if (opt != com->cor[0]) { 1985 cor_change |= CD1400_CCR_COR1; 1986 cd_setreg(com, CD1400_COR1, com->cor[0] = opt); 1987 } 1988 1989 /* 1990 * Set receive time-out period, normally to max(one char time, 5 ms). 1991 */ 1992 if (t->c_ispeed == 0) 1993 itimeout = cd_getreg(com, CD1400_RTPR); 1994 else { 1995 itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; 1996#ifdef SOFT_HOTCHAR 1997#define MIN_RTP 1 1998#else 1999#define MIN_RTP 5 2000#endif 2001 if (itimeout < MIN_RTP) 2002 itimeout = MIN_RTP; 2003 } 2004 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 2005 && t->c_cc[VTIME] * 10 > itimeout) 2006 itimeout = t->c_cc[VTIME] * 10; 2007 if (itimeout > 255) 2008 itimeout = 255; 2009 cd_setreg(com, CD1400_RTPR, itimeout); 2010 2011 /* 2012 * set channel option register 2 - 2013 * flow control 2014 */ 2015 opt = 0; 2016#ifdef Smarts 2017 if (iflag & IXANY) 2018 opt |= CD1400_COR2_IXANY; 2019 if (iflag & IXOFF) 2020 opt |= CD1400_COR2_IXOFF; 2021#endif 2022#ifndef SOFT_CTS_OFLOW 2023 if (cflag & CCTS_OFLOW) 2024 opt |= CD1400_COR2_CCTS_OFLOW; 2025#endif 2026 critical_enter(); 2027 COM_LOCK(); 2028 if (opt != com->cor[1]) { 2029 cor_change |= CD1400_CCR_COR2; 2030 cd_setreg(com, CD1400_COR2, com->cor[1] = opt); 2031 } 2032 COM_UNLOCK(); 2033 critical_exit(); 2034 2035 /* 2036 * set channel option register 3 - 2037 * receiver FIFO interrupt threshold 2038 * flow control 2039 */ 2040 opt = RxFifoThreshold; 2041#ifdef Smarts 2042 if (t->c_lflag & ICANON) 2043 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 2044 if (iflag & IXOFF) 2045 /* detect and transparently handle START and STOP chars */ 2046 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 2047#endif 2048 if (opt != com->cor[2]) { 2049 cor_change |= CD1400_CCR_COR3; 2050 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2051 } 2052 2053 /* notify the CD1400 if COR1-3 have changed */ 2054 if (cor_change) 2055 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); 2056 2057 /* 2058 * set channel option register 4 - 2059 * CR/NL processing 2060 * break processing 2061 * received exception processing 2062 */ 2063 opt = 0; 2064 if (iflag & IGNCR) 2065 opt |= CD1400_COR4_IGNCR; 2066#ifdef Smarts 2067 /* 2068 * we need a new ttyinput() for this, as we don't want to 2069 * have ICRNL && INLCR being done in both layers, or to have 2070 * synchronisation problems 2071 */ 2072 if (iflag & ICRNL) 2073 opt |= CD1400_COR4_ICRNL; 2074 if (iflag & INLCR) 2075 opt |= CD1400_COR4_INLCR; 2076#endif 2077 if (iflag & IGNBRK) 2078 opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; 2079 /* 2080 * The `-ignbrk -brkint parmrk' case is not handled by the hardware, 2081 * so only tell the hardware about -brkint if -parmrk. 2082 */ 2083 if (!(iflag & (BRKINT | PARMRK))) 2084 opt |= CD1400_COR4_NOBRKINT; 2085#if 0 2086 /* XXX using this "intelligence" breaks reporting of overruns. */ 2087 if (iflag & IGNPAR) 2088 opt |= CD1400_COR4_PFO_DISCARD; 2089 else { 2090 if (iflag & PARMRK) 2091 opt |= CD1400_COR4_PFO_ESC; 2092 else 2093 opt |= CD1400_COR4_PFO_NUL; 2094 } 2095#else 2096 opt |= CD1400_COR4_PFO_EXCEPTION; 2097#endif 2098 cd_setreg(com, CD1400_COR4, opt); 2099 2100 /* 2101 * set channel option register 5 - 2102 */ 2103 opt = 0; 2104 if (iflag & ISTRIP) 2105 opt |= CD1400_COR5_ISTRIP; 2106 if (t->c_iflag & IEXTEN) 2107 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 2108 opt |= CD1400_COR5_LNEXT; 2109#ifdef Smarts 2110 if (t->c_oflag & ONLCR) 2111 opt |= CD1400_COR5_ONLCR; 2112 if (t->c_oflag & OCRNL) 2113 opt |= CD1400_COR5_OCRNL; 2114#endif 2115 cd_setreg(com, CD1400_COR5, opt); 2116 2117 /* 2118 * We always generate modem status change interrupts for CD changes. 2119 * Among other things, this is necessary to track TS_CARR_ON for 2120 * pstat to print even when the driver doesn't care. CD changes 2121 * should be rare so interrupts for them are not worth extra code to 2122 * avoid. We avoid interrupts for other modem status changes (except 2123 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is 2124 * simplest and best. 2125 */ 2126 2127 /* 2128 * set modem change option register 1 2129 * generate modem interrupts on which 1 -> 0 input transitions 2130 * also controls auto-DTR output flow-control, which we don't use 2131 */ 2132 opt = CD1400_MCOR1_CDzd; 2133#ifdef SOFT_CTS_OFLOW 2134 if (cflag & CCTS_OFLOW) 2135 opt |= CD1400_MCOR1_CTSzd; 2136#endif 2137 cd_setreg(com, CD1400_MCOR1, opt); 2138 2139 /* 2140 * set modem change option register 2 2141 * generate modem interrupts on specific 0 -> 1 input transitions 2142 */ 2143 opt = CD1400_MCOR2_CDod; 2144#ifdef SOFT_CTS_OFLOW 2145 if (cflag & CCTS_OFLOW) 2146 opt |= CD1400_MCOR2_CTSod; 2147#endif 2148 cd_setreg(com, CD1400_MCOR2, opt); 2149 2150 /* 2151 * XXX should have done this long ago, but there is too much state 2152 * to change all atomically. 2153 */ 2154 critical_enter(); 2155 COM_LOCK(); 2156 2157 com->state &= ~CS_TTGO; 2158 if (!(tp->t_state & TS_TTSTOP)) 2159 com->state |= CS_TTGO; 2160 if (cflag & CRTS_IFLOW) { 2161 com->state |= CS_RTS_IFLOW; 2162 /* 2163 * If CS_RTS_IFLOW just changed from off to on, the change 2164 * needs to be propagated to MCR_RTS. This isn't urgent, 2165 * so do it later by calling comstart() instead of repeating 2166 * a lot of code from comstart() here. 2167 */ 2168 } else if (com->state & CS_RTS_IFLOW) { 2169 com->state &= ~CS_RTS_IFLOW; 2170 /* 2171 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2172 * on here, since comstart() won't do it later. 2173 */ 2174#if 0 2175 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2176#else 2177 cd_setreg(com, com->mcr_rts_reg, 2178 com->mcr_image |= com->mcr_rts); 2179#endif 2180 } 2181 2182 /* 2183 * Set up state to handle output flow control. 2184 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2185 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2186 */ 2187 com->state |= CS_ODEVREADY; 2188#ifdef SOFT_CTS_OFLOW 2189 com->state &= ~CS_CTS_OFLOW; 2190 if (cflag & CCTS_OFLOW) { 2191 com->state |= CS_CTS_OFLOW; 2192 if (!(com->last_modem_status & MSR_CTS)) 2193 com->state &= ~CS_ODEVREADY; 2194 } 2195#endif 2196 /* XXX shouldn't call functions while intrs are disabled. */ 2197 disc_optim(tp, t, com); 2198#if 0 2199 /* 2200 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2201 * unconditionally, but that defeated the careful discarding of 2202 * stale input in sioopen(). 2203 */ 2204 if (com->state >= (CS_BUSY | CS_TTGO)) 2205 siointr1(com); 2206#endif 2207 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2208 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 2209 cd_setreg(com, CD1400_SRER, 2210 com->intr_enable 2211 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2212 | CD1400_SRER_TXRDY); 2213 } else { 2214 if (com->intr_enable & CD1400_SRER_TXRDY) 2215 cd_setreg(com, CD1400_SRER, 2216 com->intr_enable 2217 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2218 | CD1400_SRER_TXMPTY); 2219 } 2220 2221 COM_UNLOCK(); 2222 critical_exit(); 2223 splx(s); 2224 comstart(tp); 2225 if (com->ibufold != NULL) { 2226 free(com->ibufold, M_DEVBUF); 2227 com->ibufold = NULL; 2228 } 2229 return (0); 2230} 2231 2232static int 2233siosetwater(com, speed) 2234 struct com_s *com; 2235 speed_t speed; 2236{ 2237 int cp4ticks; 2238 u_char *ibuf; 2239 int ibufsize; 2240 struct tty *tp; 2241 2242 /* 2243 * Make the buffer size large enough to handle a softtty interrupt 2244 * latency of about 2 ticks without loss of throughput or data 2245 * (about 3 ticks if input flow control is not used or not honoured, 2246 * but a bit less for CS5-CS7 modes). 2247 */ 2248 cp4ticks = speed / 10 / hz * 4; 2249 for (ibufsize = 128; ibufsize < cp4ticks;) 2250 ibufsize <<= 1; 2251 if (ibufsize == com->ibufsize) { 2252 return (0); 2253 } 2254 2255 /* 2256 * Allocate input buffer. The extra factor of 2 in the size is 2257 * to allow for an error byte for each input byte. 2258 */ 2259 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 2260 if (ibuf == NULL) { 2261 return (ENOMEM); 2262 } 2263 2264 /* Initialize non-critical variables. */ 2265 com->ibufold = com->ibuf; 2266 com->ibufsize = ibufsize; 2267 tp = com->tp; 2268 if (tp != NULL) { 2269 tp->t_ififosize = 2 * ibufsize; 2270 tp->t_ispeedwat = (speed_t)-1; 2271 tp->t_ospeedwat = (speed_t)-1; 2272 } 2273 2274 /* 2275 * Read current input buffer, if any. Continue with interrupts 2276 * disabled. 2277 */ 2278 critical_enter(); 2279 COM_LOCK(); 2280 if (com->iptr != com->ibuf) 2281 sioinput(com); 2282 2283 /*- 2284 * Initialize critical variables, including input buffer watermarks. 2285 * The external device is asked to stop sending when the buffer 2286 * exactly reaches high water, or when the high level requests it. 2287 * The high level is notified immediately (rather than at a later 2288 * clock tick) when this watermark is reached. 2289 * The buffer size is chosen so the watermark should almost never 2290 * be reached. 2291 * The low watermark is invisibly 0 since the buffer is always 2292 * emptied all at once. 2293 */ 2294 com->iptr = com->ibuf = ibuf; 2295 com->ibufend = ibuf + ibufsize; 2296 com->ierroff = ibufsize; 2297 com->ihighwater = ibuf + 3 * ibufsize / 4; 2298 2299 COM_UNLOCK(); 2300 critical_exit(); 2301 return (0); 2302} 2303 2304static void 2305comstart(tp) 2306 struct tty *tp; 2307{ 2308 struct com_s *com; 2309 int s; 2310#ifdef CyDebug 2311 bool_t started; 2312#endif 2313 int unit; 2314 2315 unit = DEV_TO_UNIT(tp->t_dev); 2316 com = com_addr(unit); 2317 s = spltty(); 2318 2319#ifdef CyDebug 2320 ++com->start_count; 2321 started = FALSE; 2322#endif 2323 2324 critical_enter(); 2325 COM_LOCK(); 2326 if (tp->t_state & TS_TTSTOP) { 2327 com->state &= ~CS_TTGO; 2328 if (com->intr_enable & CD1400_SRER_TXRDY) 2329 cd_setreg(com, CD1400_SRER, 2330 com->intr_enable 2331 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2332 | CD1400_SRER_TXMPTY); 2333 } else { 2334 com->state |= CS_TTGO; 2335 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2336 && !(com->intr_enable & CD1400_SRER_TXRDY)) 2337 cd_setreg(com, CD1400_SRER, 2338 com->intr_enable 2339 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2340 | CD1400_SRER_TXRDY); 2341 } 2342 if (tp->t_state & TS_TBLOCK) { 2343 if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) 2344#if 0 2345 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2346#else 2347 cd_setreg(com, com->mcr_rts_reg, 2348 com->mcr_image &= ~com->mcr_rts); 2349#endif 2350 } else { 2351 if (!(com->mcr_image & com->mcr_rts) 2352 && com->iptr < com->ihighwater 2353 && com->state & CS_RTS_IFLOW) 2354#if 0 2355 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2356#else 2357 cd_setreg(com, com->mcr_rts_reg, 2358 com->mcr_image |= com->mcr_rts); 2359#endif 2360 } 2361 COM_UNLOCK(); 2362 critical_exit(); 2363 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2364 ttwwakeup(tp); 2365 splx(s); 2366 return; 2367 } 2368 if (tp->t_outq.c_cc != 0) { 2369 struct lbq *qp; 2370 struct lbq *next; 2371 2372 if (!com->obufs[0].l_queued) { 2373#ifdef CyDebug 2374 started = TRUE; 2375#endif 2376 com->obufs[0].l_tail 2377 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2378 sizeof com->obuf1); 2379 com->obufs[0].l_next = NULL; 2380 com->obufs[0].l_queued = TRUE; 2381 critical_enter(); 2382 COM_LOCK(); 2383 if (com->state & CS_BUSY) { 2384 qp = com->obufq.l_next; 2385 while ((next = qp->l_next) != NULL) 2386 qp = next; 2387 qp->l_next = &com->obufs[0]; 2388 } else { 2389 com->obufq.l_head = com->obufs[0].l_head; 2390 com->obufq.l_tail = com->obufs[0].l_tail; 2391 com->obufq.l_next = &com->obufs[0]; 2392 com->state |= CS_BUSY; 2393 if (com->state >= (CS_BUSY | CS_TTGO 2394 | CS_ODEVREADY)) 2395 cd_setreg(com, CD1400_SRER, 2396 com->intr_enable 2397 = (com->intr_enable 2398 & ~CD1400_SRER_TXMPTY) 2399 | CD1400_SRER_TXRDY); 2400 } 2401 COM_UNLOCK(); 2402 critical_exit(); 2403 } 2404 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2405#ifdef CyDebug 2406 started = TRUE; 2407#endif 2408 com->obufs[1].l_tail 2409 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2410 sizeof com->obuf2); 2411 com->obufs[1].l_next = NULL; 2412 com->obufs[1].l_queued = TRUE; 2413 critical_enter(); 2414 COM_LOCK(); 2415 if (com->state & CS_BUSY) { 2416 qp = com->obufq.l_next; 2417 while ((next = qp->l_next) != NULL) 2418 qp = next; 2419 qp->l_next = &com->obufs[1]; 2420 } else { 2421 com->obufq.l_head = com->obufs[1].l_head; 2422 com->obufq.l_tail = com->obufs[1].l_tail; 2423 com->obufq.l_next = &com->obufs[1]; 2424 com->state |= CS_BUSY; 2425 if (com->state >= (CS_BUSY | CS_TTGO 2426 | CS_ODEVREADY)) 2427 cd_setreg(com, CD1400_SRER, 2428 com->intr_enable 2429 = (com->intr_enable 2430 & ~CD1400_SRER_TXMPTY) 2431 | CD1400_SRER_TXRDY); 2432 } 2433 COM_UNLOCK(); 2434 critical_exit(); 2435 } 2436 tp->t_state |= TS_BUSY; 2437 } 2438#ifdef CyDebug 2439 if (started) 2440 ++com->start_real; 2441#endif 2442#if 0 2443 critical_enter(); 2444 COM_LOCK(); 2445 if (com->state >= (CS_BUSY | CS_TTGO)) 2446 siointr1(com); /* fake interrupt to start output */ 2447 COM_UNLOCK(); 2448 critical_exit(); 2449#endif 2450 ttwwakeup(tp); 2451 splx(s); 2452} 2453 2454static void 2455comstop(tp, rw) 2456 struct tty *tp; 2457 int rw; 2458{ 2459 struct com_s *com; 2460 bool_t wakeup_etc; 2461 2462 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2463 wakeup_etc = FALSE; 2464 critical_enter(); 2465 COM_LOCK(); 2466 if (rw & FWRITE) { 2467 com->obufs[0].l_queued = FALSE; 2468 com->obufs[1].l_queued = FALSE; 2469 if (com->extra_state & CSE_ODONE) { 2470 com_events -= LOTS_OF_EVENTS; 2471 com->extra_state &= ~CSE_ODONE; 2472 if (com->etc != ETC_NONE) { 2473 if (com->etc == ETC_BREAK_ENDED) 2474 com->etc = ETC_NONE; 2475 wakeup_etc = TRUE; 2476 } 2477 } 2478 com->tp->t_state &= ~TS_BUSY; 2479 if (com->state & CS_ODONE) 2480 com_events -= LOTS_OF_EVENTS; 2481 com->state &= ~(CS_ODONE | CS_BUSY); 2482 } 2483 if (rw & FREAD) { 2484 /* XXX no way to reset only input fifo. */ 2485 com_events -= (com->iptr - com->ibuf); 2486 com->iptr = com->ibuf; 2487 } 2488 COM_UNLOCK(); 2489 critical_exit(); 2490 if (wakeup_etc) 2491 wakeup(&com->etc); 2492 if (rw & FWRITE && com->etc == ETC_NONE) 2493 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 2494 comstart(tp); 2495} 2496 2497static int 2498commctl(com, bits, how) 2499 struct com_s *com; 2500 int bits; 2501 int how; 2502{ 2503 int mcr; 2504 int msr; 2505 2506 if (how == DMGET) { 2507 if (com->channel_control & CD1400_CCR_RCVEN) 2508 bits |= TIOCM_LE; 2509 mcr = com->mcr_image; 2510 if (mcr & com->mcr_dtr) 2511 bits |= TIOCM_DTR; 2512 if (mcr & com->mcr_rts) 2513 /* XXX wired on for Cyclom-8Ys */ 2514 bits |= TIOCM_RTS; 2515 2516 /* 2517 * We must read the modem status from the hardware because 2518 * we don't generate modem status change interrupts for all 2519 * changes, so com->prev_modem_status is not guaranteed to 2520 * be up to date. This is safe, unlike for sio, because 2521 * reading the status register doesn't clear pending modem 2522 * status change interrupts. 2523 */ 2524 msr = cd_getreg(com, CD1400_MSVR2); 2525 2526 if (msr & MSR_CTS) 2527 bits |= TIOCM_CTS; 2528 if (msr & MSR_DCD) 2529 bits |= TIOCM_CD; 2530 if (msr & MSR_DSR) 2531 bits |= TIOCM_DSR; 2532 if (msr & MSR_RI) 2533 /* XXX not connected except for Cyclom-16Y? */ 2534 bits |= TIOCM_RI; 2535 return (bits); 2536 } 2537 mcr = 0; 2538 if (bits & TIOCM_DTR) 2539 mcr |= com->mcr_dtr; 2540 if (bits & TIOCM_RTS) 2541 mcr |= com->mcr_rts; 2542 critical_enter(); 2543 COM_LOCK(); 2544 switch (how) { 2545 case DMSET: 2546 com->mcr_image = mcr; 2547 cd_setreg(com, CD1400_MSVR1, mcr); 2548 cd_setreg(com, CD1400_MSVR2, mcr); 2549 break; 2550 case DMBIS: 2551 com->mcr_image = mcr = com->mcr_image | mcr; 2552 cd_setreg(com, CD1400_MSVR1, mcr); 2553 cd_setreg(com, CD1400_MSVR2, mcr); 2554 break; 2555 case DMBIC: 2556 com->mcr_image = mcr = com->mcr_image & ~mcr; 2557 cd_setreg(com, CD1400_MSVR1, mcr); 2558 cd_setreg(com, CD1400_MSVR2, mcr); 2559 break; 2560 } 2561 COM_UNLOCK(); 2562 critical_exit(); 2563 return (0); 2564} 2565 2566static void 2567siosettimeout() 2568{ 2569 struct com_s *com; 2570 bool_t someopen; 2571 int unit; 2572 2573 /* 2574 * Set our timeout period to 1 second if no polled devices are open. 2575 * Otherwise set it to max(1/200, 1/hz). 2576 * Enable timeouts iff some device is open. 2577 */ 2578 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2579 sio_timeout = hz; 2580 someopen = FALSE; 2581 for (unit = 0; unit < NSIO; ++unit) { 2582 com = com_addr(unit); 2583 if (com != NULL && com->tp != NULL 2584 && com->tp->t_state & TS_ISOPEN) { 2585 someopen = TRUE; 2586#if 0 2587 if (com->poll || com->poll_output) { 2588 sio_timeout = hz > 200 ? hz / 200 : 1; 2589 break; 2590 } 2591#endif 2592 } 2593 } 2594 if (someopen) { 2595 sio_timeouts_until_log = hz / sio_timeout; 2596 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 2597 sio_timeout); 2598 } else { 2599 /* Flush error messages, if any. */ 2600 sio_timeouts_until_log = 1; 2601 comwakeup((void *)NULL); 2602 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2603 } 2604} 2605 2606static void 2607comwakeup(chan) 2608 void *chan; 2609{ 2610 struct com_s *com; 2611 int unit; 2612 2613 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 2614 2615#if 0 2616 /* 2617 * Recover from lost output interrupts. 2618 * Poll any lines that don't use interrupts. 2619 */ 2620 for (unit = 0; unit < NSIO; ++unit) { 2621 com = com_addr(unit); 2622 if (com != NULL 2623 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2624 critical_enter(); 2625 COM_LOCK(); 2626 siointr1(com); 2627 COM_UNLOCK(); 2628 critical_exit(); 2629 } 2630 } 2631#endif 2632 2633 /* 2634 * Check for and log errors, but not too often. 2635 */ 2636 if (--sio_timeouts_until_log > 0) 2637 return; 2638 sio_timeouts_until_log = hz / sio_timeout; 2639 for (unit = 0; unit < NSIO; ++unit) { 2640 int errnum; 2641 2642 com = com_addr(unit); 2643 if (com == NULL) 2644 continue; 2645 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2646 u_int delta; 2647 u_long total; 2648 2649 critical_enter(); 2650 COM_LOCK(); 2651 delta = com->delta_error_counts[errnum]; 2652 com->delta_error_counts[errnum] = 0; 2653 COM_UNLOCK(); 2654 critical_exit(); 2655 if (delta == 0) 2656 continue; 2657 total = com->error_counts[errnum] += delta; 2658 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 2659 unit, delta, error_desc[errnum], 2660 delta == 1 ? "" : "s", total); 2661 } 2662 } 2663} 2664 2665static void 2666disc_optim(tp, t, com) 2667 struct tty *tp; 2668 struct termios *t; 2669 struct com_s *com; 2670{ 2671#ifndef SOFT_HOTCHAR 2672 u_char opt; 2673#endif 2674 2675 /* 2676 * XXX can skip a lot more cases if Smarts. Maybe 2677 * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we 2678 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. 2679 */ 2680 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 2681 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2682 && (!(t->c_iflag & PARMRK) 2683 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 2684 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 2685 && linesw[tp->t_line].l_rint == ttyinput) 2686 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2687 else 2688 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2689 com->hotchar = linesw[tp->t_line].l_hotchar; 2690#ifndef SOFT_HOTCHAR 2691 opt = com->cor[2] & ~CD1400_COR3_SCD34; 2692 if (com->hotchar != 0) { 2693 cd_setreg(com, CD1400_SCHR3, com->hotchar); 2694 cd_setreg(com, CD1400_SCHR4, com->hotchar); 2695 opt |= CD1400_COR3_SCD34; 2696 } 2697 if (opt != com->cor[2]) { 2698 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2699 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 2700 } 2701#endif 2702} 2703 2704#ifdef Smarts 2705/* standard line discipline input routine */ 2706int 2707cyinput(c, tp) 2708 int c; 2709 struct tty *tp; 2710{ 2711 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 2712 * bits, as they are done by the CD1400. Hardly worth the effort, 2713 * given that high-throughput sessions are raw anyhow. 2714 */ 2715} 2716#endif /* Smarts */ 2717 2718static int 2719comspeed(speed, cy_clock, prescaler_io) 2720 speed_t speed; 2721 u_long cy_clock; 2722 int *prescaler_io; 2723{ 2724 int actual; 2725 int error; 2726 int divider; 2727 int prescaler; 2728 int prescaler_unit; 2729 2730 if (speed == 0) 2731 return (0); 2732 if (speed < 0 || speed > 150000) 2733 return (-1); 2734 2735 /* determine which prescaler to use */ 2736 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2737 prescaler_unit--, prescaler >>= 2) { 2738 if (cy_clock / prescaler / speed > 63) 2739 break; 2740 } 2741 2742 divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ 2743 if (divider > 255) 2744 divider = 255; 2745 actual = cy_clock/prescaler/divider; 2746 2747 /* 10 times error in percent: */ 2748 error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; 2749 2750 /* 3.0% max error tolerance */ 2751 if (error < -30 || error > 30) 2752 return (-1); 2753 2754#if 0 2755 printf("prescaler = %d (%d)\n", prescaler, prescaler_unit); 2756 printf("divider = %d (%x)\n", divider, divider); 2757 printf("actual = %d\n", actual); 2758 printf("error = %d\n", error); 2759#endif 2760 2761 *prescaler_io = prescaler_unit; 2762 return (divider); 2763} 2764 2765static void 2766cd1400_channel_cmd(com, cmd) 2767 struct com_s *com; 2768 int cmd; 2769{ 2770 cd1400_channel_cmd_wait(com); 2771 cd_setreg(com, CD1400_CCR, cmd); 2772 cd1400_channel_cmd_wait(com); 2773} 2774 2775static void 2776cd1400_channel_cmd_wait(com) 2777 struct com_s *com; 2778{ 2779 struct timeval start; 2780 struct timeval tv; 2781 long usec; 2782 2783 if (cd_getreg(com, CD1400_CCR) == 0) 2784 return; 2785 microtime(&start); 2786 for (;;) { 2787 if (cd_getreg(com, CD1400_CCR) == 0) 2788 return; 2789 microtime(&tv); 2790 usec = 1000000 * (tv.tv_sec - start.tv_sec) + 2791 tv.tv_usec - start.tv_usec; 2792 if (usec >= 5000) { 2793 log(LOG_ERR, 2794 "cy%d: channel command timeout (%ld usec)\n", 2795 com->unit, usec); 2796 return; 2797 } 2798 } 2799} 2800 2801static void 2802cd_etc(com, etc) 2803 struct com_s *com; 2804 int etc; 2805{ 2806 2807 /* 2808 * We can't change the hardware's ETC state while there are any 2809 * characters in the tx fifo, since those characters would be 2810 * interpreted as commands! Unputting characters from the fifo 2811 * is difficult, so we wait up to 12 character times for the fifo 2812 * to drain. The command will be delayed for up to 2 character 2813 * times for the tx to become empty. Unputting characters from 2814 * the tx holding and shift registers is impossible, so we wait 2815 * for the tx to become empty so that the command is sure to be 2816 * executed soon after we issue it. 2817 */ 2818 critical_enter(); 2819 COM_LOCK(); 2820 if (com->etc == etc) 2821 goto wait; 2822 if ((etc == CD1400_ETC_SENDBREAK 2823 && (com->etc == ETC_BREAK_STARTING 2824 || com->etc == ETC_BREAK_STARTED)) 2825 || (etc == CD1400_ETC_STOPBREAK 2826 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED 2827 || com->etc == ETC_NONE))) { 2828 COM_UNLOCK(); 2829 critical_exit(); 2830 return; 2831 } 2832 com->etc = etc; 2833 cd_setreg(com, CD1400_SRER, 2834 com->intr_enable 2835 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); 2836wait: 2837 COM_UNLOCK(); 2838 critical_exit(); 2839 while (com->etc == etc 2840 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) 2841 continue; 2842} 2843 2844static int 2845cd_getreg(com, reg) 2846 struct com_s *com; 2847 int reg; 2848{ 2849 struct com_s *basecom; 2850 u_char car; 2851 int cy_align; 2852 register_t eflags; 2853 cy_addr iobase; 2854 int val; 2855 2856 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2857 car = com->unit & CD1400_CAR_CHAN; 2858 cy_align = com->cy_align; 2859 iobase = com->iobase; 2860 eflags = read_eflags(); 2861 critical_enter(); 2862 if (eflags & PSL_I) 2863 COM_LOCK(); 2864 if (basecom->car != car) 2865 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2866 val = cd_inb(iobase, reg, cy_align); 2867 if (eflags & PSL_I) 2868 COM_UNLOCK(); 2869 critical_exit(); 2870 return (val); 2871} 2872 2873static void 2874cd_setreg(com, reg, val) 2875 struct com_s *com; 2876 int reg; 2877 int val; 2878{ 2879 struct com_s *basecom; 2880 u_char car; 2881 int cy_align; 2882 register_t eflags; 2883 cy_addr iobase; 2884 2885 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2886 car = com->unit & CD1400_CAR_CHAN; 2887 cy_align = com->cy_align; 2888 iobase = com->iobase; 2889 eflags = read_eflags(); 2890 critical_enter(); 2891 if (eflags & PSL_I) 2892 COM_LOCK(); 2893 if (basecom->car != car) 2894 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2895 cd_outb(iobase, reg, cy_align, val); 2896 if (eflags & PSL_I) 2897 COM_UNLOCK(); 2898 critical_exit(); 2899} 2900 2901#ifdef CyDebug 2902/* useful in ddb */ 2903void 2904cystatus(unit) 2905 int unit; 2906{ 2907 struct com_s *com; 2908 cy_addr iobase; 2909 u_int ocount; 2910 struct tty *tp; 2911 2912 com = com_addr(unit); 2913 printf("info for channel %d\n", unit); 2914 printf("------------------\n"); 2915 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2916 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2917 if (com == NULL) 2918 return; 2919 iobase = com->iobase; 2920 printf("\n"); 2921 printf("cd1400 base address:\\tt%p\n", iobase); 2922 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2923 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2924 com->cor[0], com->cor[1], com->cor[2]); 2925 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2926 cd_getreg(com, CD1400_SRER), com->intr_enable); 2927 printf("service request register:\t0x%02x\n", 2928 cd_inb(iobase, CD1400_SVRR, com->cy_align)); 2929 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2930 cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); 2931 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2932 cd_inb(iobase, CD1400_RIR, com->cy_align), 2933 cd_inb(iobase, CD1400_TIR, com->cy_align), 2934 cd_inb(iobase, CD1400_MIR, com->cy_align)); 2935 printf("\n"); 2936 printf("com state:\t\t\t0x%02x\n", com->state); 2937 printf("calls to comstart():\t\t%d (%d useful)\n", 2938 com->start_count, com->start_real); 2939 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2940 ocount = 0; 2941 if (com->obufs[0].l_queued) 2942 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2943 if (com->obufs[1].l_queued) 2944 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2945 printf("tx buffer chars:\t\t%u\n", ocount); 2946 printf("received chars:\t\t\t%d\n", com->bytes_in); 2947 printf("received exceptions:\t\t%d\n", com->recv_exception); 2948 printf("modem signal deltas:\t\t%d\n", com->mdm); 2949 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2950 printf("\n"); 2951 tp = com->tp; 2952 if (tp != NULL) { 2953 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2954 printf( 2955 "upper layer queue lengths:\t%d raw, %d canon, %d output\n", 2956 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 2957 } else 2958 printf("tty state:\t\t\tclosed\n"); 2959} 2960#endif /* CyDebug */
| 34#include "opt_compat.h" 35#include "cy.h" 36 37/* 38 * TODO: 39 * Atomic COR change. 40 * Consoles. 41 */ 42 43/* 44 * Temporary compile-time configuration options. 45 */ 46#define RxFifoThreshold (CD1400_RX_FIFO_SIZE / 2) 47 /* Number of chars in the receiver FIFO before an 48 * an interrupt is generated. Should depend on 49 * line speed. Needs to be about 6 on a 486DX33 50 * for 4 active ports at 115200 bps. Why doesn't 51 * 10 work? 52 */ 53#define PollMode /* Use polling-based irq service routine, not the 54 * hardware svcack lines. Must be defined for 55 * Cyclom-16Y boards. Less efficient for Cyclom-8Ys, 56 * and stops 4 * 115200 bps from working. 57 */ 58#undef Smarts /* Enable slightly more CD1400 intelligence. Mainly 59 * the output CR/LF processing, plus we can avoid a 60 * few checks usually done in ttyinput(). 61 * 62 * XXX not fully implemented, and not particularly 63 * worthwhile. 64 */ 65#undef CyDebug /* Include debugging code (not very expensive). */ 66 67/* These will go away. */ 68#undef SOFT_CTS_OFLOW 69#define SOFT_HOTCHAR 70 71#include <sys/param.h> 72#include <sys/systm.h> 73#include <sys/bus.h> 74#include <sys/conf.h> 75#include <sys/fcntl.h> 76#include <sys/interrupt.h> 77#include <sys/kernel.h> 78#include <sys/lock.h> 79#include <sys/malloc.h> 80#include <sys/mutex.h> 81#include <sys/syslog.h> 82#include <sys/tty.h> 83 84#include <machine/psl.h> 85 86#include <i386/isa/isa_device.h> 87#include <i386/isa/cyreg.h> 88#include <i386/isa/ic/cd1400.h> 89 90#ifndef COMPAT_OLDISA 91#error "The cy device requires the old isa compatibility shims" 92#endif 93 94#ifdef SMP 95 96#include <machine/smptests.h> /** xxx_LOCK */ 97 98#ifdef USE_COMLOCK 99#define COM_LOCK() mtx_lock_spin(&com_mtx) 100#define COM_UNLOCK() mtx_unlock_spin(&com_mtx) 101#else 102#define COM_LOCK() 103#define COM_UNLOCK() 104#endif /* USE_COMLOCK */ 105 106#else /* SMP */ 107 108#define COM_LOCK() 109#define COM_UNLOCK() 110 111#endif /* SMP */ 112 113extern struct mtx com_mtx; 114 115/* 116 * Dictionary so that I can name everything *sio* or *com* to compare with 117 * sio.c. There is also lots of ugly formatting and unnecessary ifdefs to 118 * simplify the comparision. These will go away. 119 */ 120#define LSR_BI CD1400_RDSR_BREAK 121#define LSR_FE CD1400_RDSR_FE 122#define LSR_OE CD1400_RDSR_OE 123#define LSR_PE CD1400_RDSR_PE 124#define MCR_DTR CD1400_MSVR2_DTR 125#define MCR_RTS CD1400_MSVR1_RTS 126#define MSR_CTS CD1400_MSVR2_CTS 127#define MSR_DCD CD1400_MSVR2_CD 128#define MSR_DSR CD1400_MSVR2_DSR 129#define MSR_RI CD1400_MSVR2_RI 130#define NSIO (NCY * CY_MAX_PORTS) 131#define comconsole cyconsole 132#define comdefaultrate cydefaultrate 133#define com_events cy_events 134#define comhardclose cyhardclose 135#define commctl cymctl 136#define comparam cyparam 137#define comspeed cyspeed 138#define comstart cystart 139#define comwakeup cywakeup 140#define p_com_addr p_cy_addr 141#define sioattach cyattach 142#define sioclose cyclose 143#define siodriver cydriver 144#define siodtrwakeup cydtrwakeup 145#define sioinput cyinput 146#define siointr cyintr 147#define siointr1 cyintr1 148#define sioioctl cyioctl 149#define sioopen cyopen 150#define siopoll cypoll 151#define sioprobe cyprobe 152#define siosettimeout cysettimeout 153#define siosetwater cysetwater 154#define comstop cystop 155#define siowrite cywrite 156#define sio_ih cy_ih 157#define sio_irec cy_irec 158#define sio_timeout cy_timeout 159#define sio_timeout_handle cy_timeout_handle 160#define sio_timeouts_until_log cy_timeouts_until_log 161 162#define CY_MAX_PORTS (CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s) 163 164/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ 165#define CD1400_xIVR_CHAN_SHIFT 3 166#define CD1400_xIVR_CHAN 0x1F 167 168/* 169 * ETC states. com->etc may also contain a hardware ETC command value, 170 * meaning that execution of that command is pending. 171 */ 172#define ETC_NONE 0 /* we depend on bzero() setting this */ 173#define ETC_BREAK_STARTING 1 174#define ETC_BREAK_STARTED 2 175#define ETC_BREAK_ENDING 3 176#define ETC_BREAK_ENDED 4 177 178#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 179 180#define CALLOUT_MASK 0x80 181#define CONTROL_MASK 0x60 182#define CONTROL_INIT_STATE 0x20 183#define CONTROL_LOCK_STATE 0x40 184#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 185#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 186/* 187 * Not all of the magic is parametrized in the following macros. 16 and 188 * 0xff are related to the bitfields in a udev_t. CY_MAX_PORTS must be 189 * ((0xff & ~MINOR_MAGIC_MASK) + 1) for things to work. 190 */ 191#define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS \ 192 | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK)) 193#define UNIT_TO_MINOR(unit) (((unit) / CY_MAX_PORTS) << 16 \ 194 | (((unit) & 0xff) & ~MINOR_MAGIC_MASK)) 195 196/* 197 * com state bits. 198 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 199 * than the other bits so that they can be tested as a group without masking 200 * off the low bits. 201 * 202 * The following com and tty flags correspond closely: 203 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and 204 * comstop()) 205 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) 206 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 207 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 208 * TS_FLUSH is not used. 209 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 210 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 211 */ 212#define CS_BUSY 0x80 /* output in progress */ 213#define CS_TTGO 0x40 /* output not stopped by XOFF */ 214#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 215#define CS_CHECKMSR 1 /* check of MSR scheduled */ 216#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 217#define CS_DTR_OFF 0x10 /* DTR held off */ 218#define CS_ODONE 4 /* output completed */ 219#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 220#define CSE_ODONE 1 /* output transmitted */ 221 222static char const * const error_desc[] = { 223#define CE_OVERRUN 0 224 "silo overflow", 225#define CE_INTERRUPT_BUF_OVERFLOW 1 226 "interrupt-level buffer overflow", 227#define CE_TTY_BUF_OVERFLOW 2 228 "tty-level buffer overflow", 229}; 230 231#define CE_NTYPES 3 232#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 233 234/* types. XXX - should be elsewhere */ 235typedef u_char bool_t; /* boolean */ 236typedef u_char volatile *cy_addr; 237 238/* queue of linear buffers */ 239struct lbq { 240 u_char *l_head; /* next char to process */ 241 u_char *l_tail; /* one past the last char to process */ 242 struct lbq *l_next; /* next in queue */ 243 bool_t l_queued; /* nonzero if queued */ 244}; 245 246/* com device structure */ 247struct com_s { 248 u_char state; /* miscellaneous flag bits */ 249 bool_t active_out; /* nonzero if the callout device is open */ 250#if 0 251 u_char cfcr_image; /* copy of value written to CFCR */ 252#endif 253 u_char etc; /* pending Embedded Transmit Command */ 254 u_char extra_state; /* more flag bits, separate for order trick */ 255#if 0 256 u_char fifo_image; /* copy of value written to FIFO */ 257#endif 258 u_char gfrcr_image; /* copy of value read from GFRCR */ 259#if 0 260 bool_t hasfifo; /* nonzero for 16550 UARTs */ 261 bool_t loses_outints; /* nonzero if device loses output interrupts */ 262#endif 263 u_char mcr_dtr; /* MCR bit that is wired to DTR */ 264 u_char mcr_image; /* copy of value written to MCR */ 265 u_char mcr_rts; /* MCR bit that is wired to RTS */ 266#if 0 267#ifdef COM_MULTIPORT 268 bool_t multiport; /* is this unit part of a multiport device? */ 269#endif /* COM_MULTIPORT */ 270 bool_t no_irq; /* nonzero if irq is not attached */ 271 bool_t poll; /* nonzero if polling is required */ 272 bool_t poll_output; /* nonzero if polling for output is required */ 273#endif 274 int unit; /* unit number */ 275 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 276#if 0 277 u_int tx_fifo_size; 278#endif 279 u_int wopeners; /* # processes waiting for DCD in open() */ 280 281 /* 282 * The high level of the driver never reads status registers directly 283 * because there would be too many side effects to handle conveniently. 284 * Instead, it reads copies of the registers stored here by the 285 * interrupt handler. 286 */ 287 u_char last_modem_status; /* last MSR read by intr handler */ 288 u_char prev_modem_status; /* last MSR handled by high level */ 289 290 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 291 u_char *ibuf; /* start of input buffer */ 292 u_char *ibufend; /* end of input buffer */ 293 u_char *ibufold; /* old input buffer, to be freed */ 294 u_char *ihighwater; /* threshold in input buffer */ 295 u_char *iptr; /* next free spot in input buffer */ 296 int ibufsize; /* size of ibuf (not include error bytes) */ 297 int ierroff; /* offset of error bytes in ibuf */ 298 299 struct lbq obufq; /* head of queue of output buffers */ 300 struct lbq obufs[2]; /* output buffers */ 301 302 int cy_align; /* index for register alignment */ 303 cy_addr cy_iobase; /* base address of this port's cyclom */ 304 cy_addr iobase; /* base address of this port's cd1400 */ 305 int mcr_rts_reg; /* cd1400 reg number of reg holding mcr_rts */ 306 307 struct tty *tp; /* cross reference */ 308 309 /* Initial state. */ 310 struct termios it_in; /* should be in struct tty */ 311 struct termios it_out; 312 313 /* Lock state. */ 314 struct termios lt_in; /* should be in struct tty */ 315 struct termios lt_out; 316 317 bool_t do_timestamp; 318 bool_t do_dcd_timestamp; 319 struct timeval timestamp; 320 struct timeval dcd_timestamp; 321 322 u_long bytes_in; /* statistics */ 323 u_long bytes_out; 324 u_int delta_error_counts[CE_NTYPES]; 325 u_long error_counts[CE_NTYPES]; 326 327 u_int recv_exception; /* exception chars received */ 328 u_int mdm; /* modem signal changes */ 329#ifdef CyDebug 330 u_int start_count; /* no. of calls to comstart() */ 331 u_int start_real; /* no. of calls that did something */ 332#endif 333 u_char car; /* CD1400 CAR shadow (if first unit in cd) */ 334 u_char channel_control;/* CD1400 CCR control command shadow */ 335 u_char cor[3]; /* CD1400 COR1-3 shadows */ 336 u_char intr_enable; /* CD1400 SRER shadow */ 337 338 /* 339 * Data area for output buffers. Someday we should build the output 340 * buffer queue without copying data. 341 */ 342 u_char obuf1[256]; 343 u_char obuf2[256]; 344}; 345 346/* PCI driver entry point. */ 347int cyattach_common(cy_addr cy_iobase, int cy_align); 348ointhand2_t siointr; 349 350static int cy_units(cy_addr cy_iobase, int cy_align); 351static int sioattach(struct isa_device *dev); 352static void cd1400_channel_cmd(struct com_s *com, int cmd); 353static void cd1400_channel_cmd_wait(struct com_s *com); 354static void cd_etc(struct com_s *com, int etc); 355static int cd_getreg(struct com_s *com, int reg); 356static void cd_setreg(struct com_s *com, int reg, int val); 357static timeout_t siodtrwakeup; 358static void comhardclose(struct com_s *com); 359static void sioinput(struct com_s *com); 360#if 0 361static void siointr1(struct com_s *com); 362#endif 363static int commctl(struct com_s *com, int bits, int how); 364static int comparam(struct tty *tp, struct termios *t); 365static void siopoll(void *arg); 366static int sioprobe(struct isa_device *dev); 367static void siosettimeout(void); 368static int siosetwater(struct com_s *com, speed_t speed); 369static int comspeed(speed_t speed, u_long cy_clock, int *prescaler_io); 370static void comstart(struct tty *tp); 371static void comstop(struct tty *tp, int rw); 372static timeout_t comwakeup; 373static void disc_optim(struct tty *tp, struct termios *t, 374 struct com_s *com); 375 376#ifdef CyDebug 377void cystatus(int unit); 378#endif 379 380static char driver_name[] = "cy"; 381 382/* table and macro for fast conversion from a unit number to its com struct */ 383static struct com_s *p_com_addr[NSIO]; 384#define com_addr(unit) (p_com_addr[unit]) 385 386struct isa_driver siodriver = { 387 INTR_TYPE_TTY | INTR_FAST, 388 sioprobe, 389 sioattach, 390 driver_name 391}; 392COMPAT_ISA_DRIVER(cy, cydriver); /* XXX */ 393 394static d_open_t sioopen; 395static d_close_t sioclose; 396static d_write_t siowrite; 397static d_ioctl_t sioioctl; 398 399#define CDEV_MAJOR 48 400static struct cdevsw sio_cdevsw = { 401 .d_open = sioopen, 402 .d_close = sioclose, 403 .d_read = ttyread, 404 .d_write = siowrite, 405 .d_ioctl = sioioctl, 406 .d_poll = ttypoll, 407 .d_name = driver_name, 408 .d_maj = CDEV_MAJOR, 409 .d_flags = D_TTY, 410 .d_kqfilter = ttykqfilter, 411}; 412 413static int comconsole = -1; 414static speed_t comdefaultrate = TTYDEF_SPEED; 415static u_int com_events; /* input chars + weighted output completions */ 416static void *sio_ih; 417static int sio_timeout; 418static int sio_timeouts_until_log; 419static struct callout_handle sio_timeout_handle 420 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 421 422#ifdef CyDebug 423static u_int cd_inbs; 424static u_int cy_inbs; 425static u_int cd_outbs; 426static u_int cy_outbs; 427static u_int cy_svrr_probes; 428static u_int cy_timeouts; 429#endif 430 431static int cy_chip_offset[] = { 432 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00, 433}; 434static int cy_nr_cd1400s[NCY]; 435static int cy_total_devices; 436#undef RxFifoThreshold 437static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); 438 439static int 440sioprobe(dev) 441 struct isa_device *dev; 442{ 443 cy_addr iobase; 444 445 iobase = (cy_addr)dev->id_maddr; 446 447 /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ 448 cy_inb(iobase, CY16_RESET, 0); /* XXX? */ 449 DELAY(500); /* wait for the board to get its act together */ 450 451 /* this is needed to get the board out of reset */ 452 cy_outb(iobase, CY_CLEAR_INTR, 0, 0); 453 DELAY(500); 454 455 return (cy_units(iobase, 0) == 0 ? 0 : -1); 456} 457 458static int 459cy_units(cy_iobase, cy_align) 460 cy_addr cy_iobase; 461 int cy_align; 462{ 463 int cyu; 464 u_char firmware_version; 465 int i; 466 cy_addr iobase; 467 468 for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { 469 iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align); 470 471 /* wait for chip to become ready for new command */ 472 for (i = 0; i < 10; i++) { 473 DELAY(50); 474 if (!cd_inb(iobase, CD1400_CCR, cy_align)) 475 break; 476 } 477 478 /* clear the GFRCR register */ 479 cd_outb(iobase, CD1400_GFRCR, cy_align, 0); 480 481 /* issue a reset command */ 482 cd_outb(iobase, CD1400_CCR, cy_align, 483 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 484 485 /* XXX bogus initialization to avoid a gcc bug/warning. */ 486 firmware_version = 0; 487 488 /* wait for the CD1400 to initialize itself */ 489 for (i = 0; i < 200; i++) { 490 DELAY(50); 491 492 /* retrieve firmware version */ 493 firmware_version = cd_inb(iobase, CD1400_GFRCR, 494 cy_align); 495 if ((firmware_version & 0xf0) == 0x40) 496 break; 497 } 498 499 /* 500 * Anything in the 0x40-0x4F range is fine. 501 * If one CD1400 is bad then we don't support higher 502 * numbered good ones on this board. 503 */ 504 if ((firmware_version & 0xf0) != 0x40) 505 break; 506 } 507 return (cyu); 508} 509 510static int 511sioattach(isdp) 512 struct isa_device *isdp; 513{ 514 int adapter; 515 516 adapter = cyattach_common((cy_addr) isdp->id_maddr, 0); 517 if (adapter < 0) 518 return (0); 519 520 /* 521 * XXX 522 * This kludge is to allow ISA/PCI device specifications in the 523 * kernel config file to be in any order. 524 */ 525 if (isdp->id_unit != adapter) { 526 printf("cy%d: attached as cy%d\n", isdp->id_unit, adapter); 527 isdp->id_unit = adapter; /* XXX */ 528 } 529 isdp->id_ointr = siointr; 530 /* isdp->id_ri_flags |= RI_FAST; XXX unimplemented - use newbus! */ 531 return (1); 532} 533 534int 535cyattach_common(cy_iobase, cy_align) 536 cy_addr cy_iobase; 537 int cy_align; 538{ 539 int adapter; 540 int cyu; 541 u_char firmware_version; 542 cy_addr iobase; 543 int minorbase; 544 int ncyu; 545 int unit; 546 547 adapter = cy_total_devices; 548 if ((u_int)adapter >= NCY) { 549 printf( 550 "cy%d: can't attach adapter: insufficient cy devices configured\n", 551 adapter); 552 return (-1); 553 } 554 ncyu = cy_units(cy_iobase, cy_align); 555 if (ncyu == 0) 556 return (-1); 557 cy_nr_cd1400s[adapter] = ncyu; 558 cy_total_devices++; 559 560 unit = adapter * CY_MAX_PORTS; 561 for (cyu = 0; cyu < ncyu; ++cyu) { 562 int cdu; 563 564 iobase = (cy_addr) (cy_iobase 565 + (cy_chip_offset[cyu] << cy_align)); 566 firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); 567 568 /* Set up a receive timeout period of than 1+ ms. */ 569 cd_outb(iobase, CD1400_PPR, cy_align, 570 howmany(CY_CLOCK(firmware_version) 571 / CD1400_PPR_PRESCALER, 1000)); 572 573 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { 574 struct com_s *com; 575 int s; 576 577 com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT | M_ZERO); 578 if (com == NULL) 579 break; 580 com->unit = unit; 581 com->gfrcr_image = firmware_version; 582 if (CY_RTS_DTR_SWAPPED(firmware_version)) { 583 com->mcr_dtr = MCR_RTS; 584 com->mcr_rts = MCR_DTR; 585 com->mcr_rts_reg = CD1400_MSVR2; 586 } else { 587 com->mcr_dtr = MCR_DTR; 588 com->mcr_rts = MCR_RTS; 589 com->mcr_rts_reg = CD1400_MSVR1; 590 } 591 com->dtr_wait = 3 * hz; 592 com->obufs[0].l_head = com->obuf1; 593 com->obufs[1].l_head = com->obuf2; 594 595 com->cy_align = cy_align; 596 com->cy_iobase = cy_iobase; 597 com->iobase = iobase; 598 com->car = ~CD1400_CAR_CHAN; 599 600 /* 601 * We don't use all the flags from <sys/ttydefaults.h> since they 602 * are only relevant for logins. It's important to have echo off 603 * initially so that the line doesn't start blathering before the 604 * echo flag can be turned off. 605 */ 606 com->it_in.c_iflag = 0; 607 com->it_in.c_oflag = 0; 608 com->it_in.c_cflag = TTYDEF_CFLAG; 609 com->it_in.c_lflag = 0; 610 if (unit == comconsole) { 611 com->it_in.c_iflag = TTYDEF_IFLAG; 612 com->it_in.c_oflag = TTYDEF_OFLAG; 613 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 614 com->it_in.c_lflag = TTYDEF_LFLAG; 615 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 616 } 617 if (siosetwater(com, com->it_in.c_ispeed) != 0) { 618 free(com, M_DEVBUF); 619 return (0); 620 } 621 termioschars(&com->it_in); 622 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 623 com->it_out = com->it_in; 624 625 s = spltty(); 626 com_addr(unit) = com; 627 splx(s); 628 629 if (sio_ih == NULL) { 630 swi_add(&tty_ithd, "tty:cy", siopoll, NULL, SWI_TTY, 0, 631 &sio_ih); 632 } 633 minorbase = UNIT_TO_MINOR(unit); 634 make_dev(&sio_cdevsw, minorbase, 635 UID_ROOT, GID_WHEEL, 0600, "ttyc%r%r", adapter, 636 unit % CY_MAX_PORTS); 637 make_dev(&sio_cdevsw, minorbase | CONTROL_INIT_STATE, 638 UID_ROOT, GID_WHEEL, 0600, "ttyic%r%r", adapter, 639 unit % CY_MAX_PORTS); 640 make_dev(&sio_cdevsw, minorbase | CONTROL_LOCK_STATE, 641 UID_ROOT, GID_WHEEL, 0600, "ttylc%r%r", adapter, 642 unit % CY_MAX_PORTS); 643 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK, 644 UID_UUCP, GID_DIALER, 0660, "cuac%r%r", adapter, 645 unit % CY_MAX_PORTS); 646 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK | CONTROL_INIT_STATE, 647 UID_UUCP, GID_DIALER, 0660, "cuaic%r%r", adapter, 648 unit % CY_MAX_PORTS); 649 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK | CONTROL_LOCK_STATE, 650 UID_UUCP, GID_DIALER, 0660, "cualc%r%r", adapter, 651 unit % CY_MAX_PORTS); 652 } 653 } 654 655 /* ensure an edge for the next interrupt */ 656 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 657 658 return (adapter); 659} 660 661static int 662sioopen(dev, flag, mode, td) 663 dev_t dev; 664 int flag; 665 int mode; 666 struct thread *td; 667{ 668 struct com_s *com; 669 int error; 670 int mynor; 671 int s; 672 struct tty *tp; 673 int unit; 674 675 mynor = minor(dev); 676 unit = MINOR_TO_UNIT(mynor); 677 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) 678 return (ENXIO); 679 if (mynor & CONTROL_MASK) 680 return (0); 681 tp = dev->si_tty = com->tp = ttymalloc(com->tp); 682 s = spltty(); 683 /* 684 * We jump to this label after all non-interrupted sleeps to pick 685 * up any changes of the device state. 686 */ 687open_top: 688 while (com->state & CS_DTR_OFF) { 689 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0); 690 if (error != 0) 691 goto out; 692 } 693 if (tp->t_state & TS_ISOPEN) { 694 /* 695 * The device is open, so everything has been initialized. 696 * Handle conflicts. 697 */ 698 if (mynor & CALLOUT_MASK) { 699 if (!com->active_out) { 700 error = EBUSY; 701 goto out; 702 } 703 } else { 704 if (com->active_out) { 705 if (flag & O_NONBLOCK) { 706 error = EBUSY; 707 goto out; 708 } 709 error = tsleep(&com->active_out, 710 TTIPRI | PCATCH, "cybi", 0); 711 if (error != 0) 712 goto out; 713 goto open_top; 714 } 715 } 716 if (tp->t_state & TS_XCLUDE && 717 suser(td)) { 718 error = EBUSY; 719 goto out; 720 } 721 } else { 722 /* 723 * The device isn't open, so there are no conflicts. 724 * Initialize it. Initialization is done twice in many 725 * cases: to preempt sleeping callin opens if we are 726 * callout, and to complete a callin open after DCD rises. 727 */ 728 tp->t_oproc = comstart; 729 tp->t_stop = comstop; 730 tp->t_param = comparam; 731 tp->t_dev = dev; 732 tp->t_termios = mynor & CALLOUT_MASK 733 ? com->it_out : com->it_in; 734 735 /* Encode per-board unit in LIVR for access in intr routines. */ 736 cd_setreg(com, CD1400_LIVR, 737 (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); 738 739 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 740#if 0 741 com->poll = com->no_irq; 742 com->poll_output = com->loses_outints; 743#endif 744 ++com->wopeners; 745 error = comparam(tp, &tp->t_termios); 746 --com->wopeners; 747 if (error != 0) 748 goto out; 749#if 0 750 if (com->hasfifo) { 751 /* 752 * (Re)enable and flush fifos. 753 * 754 * Certain SMC chips cause problems if the fifos 755 * are enabled while input is ready. Turn off the 756 * fifo if necessary to clear the input. We test 757 * the input ready bit after enabling the fifos 758 * since we've already enabled them in comparam() 759 * and to handle races between enabling and fresh 760 * input. 761 */ 762 while (TRUE) { 763 outb(iobase + com_fifo, 764 FIFO_RCV_RST | FIFO_XMT_RST 765 | com->fifo_image); 766 DELAY(100); 767 if (!(inb(com->line_status_port) & LSR_RXRDY)) 768 break; 769 outb(iobase + com_fifo, 0); 770 DELAY(100); 771 (void) inb(com->data_port); 772 } 773 } 774 775 critical_enter(); 776 COM_LOCK(); 777 (void) inb(com->line_status_port); 778 (void) inb(com->data_port); 779 com->prev_modem_status = com->last_modem_status 780 = inb(com->modem_status_port); 781 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS 782 | IER_EMSC); 783 COM_UNLOCK(); 784 critical_exit(); 785#else /* !0 */ 786 /* 787 * Flush fifos. This requires a full channel reset which 788 * also disables the transmitter and receiver. Recover 789 * from this. 790 */ 791 cd1400_channel_cmd(com, 792 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); 793 cd1400_channel_cmd(com, com->channel_control); 794 795 critical_enter(); 796 COM_LOCK(); 797 com->prev_modem_status = com->last_modem_status 798 = cd_getreg(com, CD1400_MSVR2); 799 cd_setreg(com, CD1400_SRER, 800 com->intr_enable 801 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 802 COM_UNLOCK(); 803 critical_exit(); 804#endif /* 0 */ 805 /* 806 * Handle initial DCD. Callout devices get a fake initial 807 * DCD (trapdoor DCD). If we are callout, then any sleeping 808 * callin opens get woken up and resume sleeping on "cybi" 809 * instead of "cydcd". 810 */ 811 /* 812 * XXX `mynor & CALLOUT_MASK' should be 813 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 814 * TRAPDOOR_CARRIER is the default initial state for callout 815 * devices and SOFT_CARRIER is like CLOCAL except it hides 816 * the true carrier. 817 */ 818 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 819 (*linesw[tp->t_line].l_modem)(tp, 1); 820 } 821 /* 822 * Wait for DCD if necessary. 823 */ 824 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 825 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 826 ++com->wopeners; 827 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0); 828 --com->wopeners; 829 if (error != 0) 830 goto out; 831 goto open_top; 832 } 833 error = (*linesw[tp->t_line].l_open)(dev, tp); 834 disc_optim(tp, &tp->t_termios, com); 835 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 836 com->active_out = TRUE; 837 siosettimeout(); 838out: 839 splx(s); 840 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 841 comhardclose(com); 842 return (error); 843} 844 845static int 846sioclose(dev, flag, mode, td) 847 dev_t dev; 848 int flag; 849 int mode; 850 struct thread *td; 851{ 852 struct com_s *com; 853 int mynor; 854 int s; 855 struct tty *tp; 856 857 mynor = minor(dev); 858 if (mynor & CONTROL_MASK) 859 return (0); 860 com = com_addr(MINOR_TO_UNIT(mynor)); 861 tp = com->tp; 862 s = spltty(); 863 cd_etc(com, CD1400_ETC_STOPBREAK); 864 (*linesw[tp->t_line].l_close)(tp, flag); 865 disc_optim(tp, &tp->t_termios, com); 866 comstop(tp, FREAD | FWRITE); 867 comhardclose(com); 868 ttyclose(tp); 869 siosettimeout(); 870 splx(s); 871#ifdef broken /* session holds a ref to the tty; can't deallocate */ 872 ttyfree(tp); 873 com->tp = NULL; 874#endif 875 return (0); 876} 877 878static void 879comhardclose(com) 880 struct com_s *com; 881{ 882 cy_addr iobase; 883 int s; 884 struct tty *tp; 885 int unit; 886 887 unit = com->unit; 888 iobase = com->iobase; 889 s = spltty(); 890#if 0 891 com->poll = FALSE; 892 com->poll_output = FALSE; 893#endif 894 com->do_timestamp = 0; 895#if 0 896 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 897#else 898 /* XXX */ 899 critical_enter(); 900 COM_LOCK(); 901 com->etc = ETC_NONE; 902 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); 903 COM_UNLOCK(); 904 critical_exit(); 905 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 906#endif 907 908 { 909#if 0 910 outb(iobase + com_ier, 0); 911#else 912 critical_enter(); 913 COM_LOCK(); 914 cd_setreg(com, CD1400_SRER, com->intr_enable = 0); 915 COM_UNLOCK(); 916 critical_exit(); 917#endif 918 tp = com->tp; 919 if ((tp->t_cflag & HUPCL) 920 /* 921 * XXX we will miss any carrier drop between here and the 922 * next open. Perhaps we should watch DCD even when the 923 * port is closed; it is not sufficient to check it at 924 * the next open because it might go up and down while 925 * we're not watching. 926 */ 927 || (!com->active_out 928 && !(com->prev_modem_status & MSR_DCD) 929 && !(com->it_in.c_cflag & CLOCAL)) 930 || !(tp->t_state & TS_ISOPEN)) { 931 (void)commctl(com, TIOCM_DTR, DMBIC); 932 933 /* Disable receiver (leave transmitter enabled). */ 934 com->channel_control = CD1400_CCR_CMDCHANCTL 935 | CD1400_CCR_XMTEN 936 | CD1400_CCR_RCVDIS; 937 cd1400_channel_cmd(com, com->channel_control); 938 939 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 940 timeout(siodtrwakeup, com, com->dtr_wait); 941 com->state |= CS_DTR_OFF; 942 } 943 } 944 } 945#if 0 946 if (com->hasfifo) { 947 /* 948 * Disable fifos so that they are off after controlled 949 * reboots. Some BIOSes fail to detect 16550s when the 950 * fifos are enabled. 951 */ 952 outb(iobase + com_fifo, 0); 953 } 954#endif 955 com->active_out = FALSE; 956 wakeup(&com->active_out); 957 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 958 splx(s); 959} 960 961static int 962siowrite(dev, uio, flag) 963 dev_t dev; 964 struct uio *uio; 965 int flag; 966{ 967 int mynor; 968 struct tty *tp; 969 int unit; 970 971 mynor = minor(dev); 972 if (mynor & CONTROL_MASK) 973 return (ENODEV); 974 975 unit = MINOR_TO_UNIT(mynor); 976 tp = com_addr(unit)->tp; 977 /* 978 * (XXX) We disallow virtual consoles if the physical console is 979 * a serial port. This is in case there is a display attached that 980 * is not the console. In that situation we don't need/want the X 981 * server taking over the console. 982 */ 983 if (constty != NULL && unit == comconsole) 984 constty = NULL; 985#ifdef Smarts 986 /* XXX duplicate ttwrite(), but without so much output processing on 987 * CR & LF chars. Hardly worth the effort, given that high-throughput 988 * sessions are raw anyhow. 989 */ 990#else 991 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 992#endif 993} 994 995static void 996siodtrwakeup(chan) 997 void *chan; 998{ 999 struct com_s *com; 1000 1001 com = (struct com_s *)chan; 1002 com->state &= ~CS_DTR_OFF; 1003 wakeup(&com->dtr_wait); 1004} 1005 1006/* 1007 * This function: 1008 * a) needs to be called with COM_LOCK() held, and 1009 * b) needs to return with COM_LOCK() held. 1010 */ 1011static void 1012sioinput(com) 1013 struct com_s *com; 1014{ 1015 u_char *buf; 1016 int incc; 1017 u_char line_status; 1018 int recv_data; 1019 struct tty *tp; 1020 1021 buf = com->ibuf; 1022 tp = com->tp; 1023 if (!(tp->t_state & TS_ISOPEN)) { 1024 com_events -= (com->iptr - com->ibuf); 1025 com->iptr = com->ibuf; 1026 return; 1027 } 1028 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 1029 /* 1030 * Avoid the grotesquely inefficient lineswitch routine 1031 * (ttyinput) in "raw" mode. It usually takes about 450 1032 * instructions (that's without canonical processing or echo!). 1033 * slinput is reasonably fast (usually 40 instructions plus 1034 * call overhead). 1035 */ 1036 1037 do { 1038 /* 1039 * This may look odd, but it is using save-and-enable 1040 * semantics instead of the save-and-disable semantics 1041 * that are used everywhere else. 1042 */ 1043 COM_UNLOCK(); 1044 critical_exit(); 1045 incc = com->iptr - buf; 1046 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 1047 && (com->state & CS_RTS_IFLOW 1048 || tp->t_iflag & IXOFF) 1049 && !(tp->t_state & TS_TBLOCK)) 1050 ttyblock(tp); 1051 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 1052 += b_to_q((char *)buf, incc, &tp->t_rawq); 1053 buf += incc; 1054 tk_nin += incc; 1055 tk_rawcc += incc; 1056 tp->t_rawcc += incc; 1057 ttwakeup(tp); 1058 if (tp->t_state & TS_TTSTOP 1059 && (tp->t_iflag & IXANY 1060 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 1061 tp->t_state &= ~TS_TTSTOP; 1062 tp->t_lflag &= ~FLUSHO; 1063 comstart(tp); 1064 } 1065 critical_enter(); 1066 COM_LOCK(); 1067 } while (buf < com->iptr); 1068 } else { 1069 do { 1070 /* 1071 * This may look odd, but it is using save-and-enable 1072 * semantics instead of the save-and-disable semantics 1073 * that are used everywhere else. 1074 */ 1075 COM_UNLOCK(); 1076 critical_exit(); 1077 line_status = buf[com->ierroff]; 1078 recv_data = *buf++; 1079 if (line_status 1080 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 1081 if (line_status & LSR_BI) 1082 recv_data |= TTY_BI; 1083 if (line_status & LSR_FE) 1084 recv_data |= TTY_FE; 1085 if (line_status & LSR_OE) 1086 recv_data |= TTY_OE; 1087 if (line_status & LSR_PE) 1088 recv_data |= TTY_PE; 1089 } 1090 (*linesw[tp->t_line].l_rint)(recv_data, tp); 1091 critical_enter(); 1092 COM_LOCK(); 1093 } while (buf < com->iptr); 1094 } 1095 com_events -= (com->iptr - com->ibuf); 1096 com->iptr = com->ibuf; 1097 1098 /* 1099 * There is now room for another low-level buffer full of input, 1100 * so enable RTS if it is now disabled and there is room in the 1101 * high-level buffer. 1102 */ 1103 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) && 1104 !(tp->t_state & TS_TBLOCK)) 1105#if 0 1106 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 1107#else 1108 cd_setreg(com, com->mcr_rts_reg, 1109 com->mcr_image |= com->mcr_rts); 1110#endif 1111} 1112 1113void 1114siointr(unit) 1115 int unit; 1116{ 1117 int baseu; 1118 int cy_align; 1119 cy_addr cy_iobase; 1120 int cyu; 1121 cy_addr iobase; 1122 u_char status; 1123 1124 COM_LOCK(); /* XXX could this be placed down lower in the loop? */ 1125 1126 baseu = unit * CY_MAX_PORTS; 1127 cy_align = com_addr(baseu)->cy_align; 1128 cy_iobase = com_addr(baseu)->cy_iobase; 1129 1130 /* check each CD1400 in turn */ 1131 for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { 1132 iobase = (cy_addr) (cy_iobase 1133 + (cy_chip_offset[cyu] << cy_align)); 1134 /* poll to see if it has any work */ 1135 status = cd_inb(iobase, CD1400_SVRR, cy_align); 1136 if (status == 0) 1137 continue; 1138#ifdef CyDebug 1139 ++cy_svrr_probes; 1140#endif 1141 /* service requests as appropriate, giving priority to RX */ 1142 if (status & CD1400_SVRR_RXRDY) { 1143 struct com_s *com; 1144 u_int count; 1145 u_char *ioptr; 1146 u_char line_status; 1147 u_char recv_data; 1148 u_char serv_type; 1149#ifdef PollMode 1150 u_char save_rir; 1151#endif 1152 1153#ifdef PollMode 1154 save_rir = cd_inb(iobase, CD1400_RIR, cy_align); 1155 1156 /* enter rx service */ 1157 cd_outb(iobase, CD1400_CAR, cy_align, save_rir); 1158 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1159 = save_rir & CD1400_CAR_CHAN; 1160 1161 serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); 1162 com = com_addr(baseu 1163 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1164 & CD1400_xIVR_CHAN)); 1165#else 1166 /* ack receive service */ 1167 serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); 1168 1169 com = com_addr(baseu + 1170 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1171 & CD1400_xIVR_CHAN)); 1172#endif 1173 1174 if (serv_type & CD1400_RIVR_EXCEPTION) { 1175 ++com->recv_exception; 1176 line_status = cd_inb(iobase, CD1400_RDSR, cy_align); 1177 /* break/unnattached error bits or real input? */ 1178 recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); 1179#ifndef SOFT_HOTCHAR 1180 if (line_status & CD1400_RDSR_SPECIAL 1181 && com->hotchar != 0) 1182 swi_sched(sio_ih, 0); 1183 1184#endif 1185#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ 1186 if (line_status & (LSR_PE|LSR_FE|LSR_BI)) { 1187 /* 1188 Don't store PE if IGNPAR and BI if IGNBRK, 1189 this hack allows "raw" tty optimization 1190 works even if IGN* is set. 1191 */ 1192 if ( com->tp == NULL 1193 || !(com->tp->t_state & TS_ISOPEN) 1194 || ((line_status & (LSR_PE|LSR_FE)) 1195 && (com->tp->t_iflag & IGNPAR)) 1196 || ((line_status & LSR_BI) 1197 && (com->tp->t_iflag & IGNBRK))) 1198 goto cont; 1199 if ( (line_status & (LSR_PE|LSR_FE)) 1200 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) 1201 && ((line_status & LSR_FE) 1202 || ((line_status & LSR_PE) 1203 && (com->tp->t_iflag & INPCK)))) 1204 recv_data = 0; 1205 } 1206#endif /* 1 */ 1207 ++com->bytes_in; 1208#ifdef SOFT_HOTCHAR 1209 if (com->hotchar != 0 && recv_data == com->hotchar) 1210 swi_sched(sio_ih, 0); 1211#endif 1212 ioptr = com->iptr; 1213 if (ioptr >= com->ibufend) 1214 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1215 else { 1216 if (com->do_timestamp) 1217 microtime(&com->timestamp); 1218 ++com_events; 1219 ioptr[0] = recv_data; 1220 ioptr[com->ierroff] = line_status; 1221 com->iptr = ++ioptr; 1222 if (ioptr == com->ihighwater 1223 && com->state & CS_RTS_IFLOW) 1224#if 0 1225 outb(com->modem_ctl_port, 1226 com->mcr_image &= ~MCR_RTS); 1227#else 1228 cd_outb(iobase, com->mcr_rts_reg, 1229 cy_align, 1230 com->mcr_image &= 1231 ~com->mcr_rts); 1232#endif 1233 if (line_status & LSR_OE) 1234 CE_RECORD(com, CE_OVERRUN); 1235 } 1236 goto cont; 1237 } else { 1238 int ifree; 1239 1240 count = cd_inb(iobase, CD1400_RDCR, cy_align); 1241 if (!count) 1242 goto cont; 1243 com->bytes_in += count; 1244 ioptr = com->iptr; 1245 ifree = com->ibufend - ioptr; 1246 if (count > ifree) { 1247 count -= ifree; 1248 com_events += ifree; 1249 if (ifree != 0) { 1250 if (com->do_timestamp) 1251 microtime(&com->timestamp); 1252 do { 1253 recv_data = cd_inb(iobase, 1254 CD1400_RDSR, 1255 cy_align); 1256#ifdef SOFT_HOTCHAR 1257 if (com->hotchar != 0 1258 && recv_data 1259 == com->hotchar) 1260 swi_sched(sio_ih, 0); 1261#endif 1262 ioptr[0] = recv_data; 1263 ioptr[com->ierroff] = 0; 1264 ++ioptr; 1265 } while (--ifree != 0); 1266 } 1267 com->delta_error_counts 1268 [CE_INTERRUPT_BUF_OVERFLOW] += count; 1269 do { 1270 recv_data = cd_inb(iobase, CD1400_RDSR, 1271 cy_align); 1272#ifdef SOFT_HOTCHAR 1273 if (com->hotchar != 0 1274 && recv_data == com->hotchar) 1275 swi_sched(sio_ih, 0); 1276#endif 1277 } while (--count != 0); 1278 } else { 1279 if (com->do_timestamp) 1280 microtime(&com->timestamp); 1281 if (ioptr <= com->ihighwater 1282 && ioptr + count > com->ihighwater 1283 && com->state & CS_RTS_IFLOW) 1284#if 0 1285 outb(com->modem_ctl_port, 1286 com->mcr_image &= ~MCR_RTS); 1287#else 1288 cd_outb(iobase, com->mcr_rts_reg, 1289 cy_align, 1290 com->mcr_image 1291 &= ~com->mcr_rts); 1292#endif 1293 com_events += count; 1294 do { 1295 recv_data = cd_inb(iobase, CD1400_RDSR, 1296 cy_align); 1297#ifdef SOFT_HOTCHAR 1298 if (com->hotchar != 0 1299 && recv_data == com->hotchar) 1300 swi_sched(sio_ih, 0); 1301#endif 1302 ioptr[0] = recv_data; 1303 ioptr[com->ierroff] = 0; 1304 ++ioptr; 1305 } while (--count != 0); 1306 } 1307 com->iptr = ioptr; 1308 } 1309cont: 1310 1311 /* terminate service context */ 1312#ifdef PollMode 1313 cd_outb(iobase, CD1400_RIR, cy_align, 1314 save_rir 1315 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); 1316#else 1317 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1318#endif 1319 } 1320 if (status & CD1400_SVRR_MDMCH) { 1321 struct com_s *com; 1322 u_char modem_status; 1323#ifdef PollMode 1324 u_char save_mir; 1325#else 1326 u_char vector; 1327#endif 1328 1329#ifdef PollMode 1330 save_mir = cd_inb(iobase, CD1400_MIR, cy_align); 1331 1332 /* enter modem service */ 1333 cd_outb(iobase, CD1400_CAR, cy_align, save_mir); 1334 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1335 = save_mir & CD1400_CAR_CHAN; 1336 1337 com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS 1338 + (save_mir & CD1400_MIR_CHAN)); 1339#else 1340 /* ack modem service */ 1341 vector = cy_inb(iobase, CY8_SVCACKM, cy_align); 1342 1343 com = com_addr(baseu 1344 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1345 & CD1400_xIVR_CHAN)); 1346#endif 1347 ++com->mdm; 1348 modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align); 1349 if (modem_status != com->last_modem_status) { 1350 if (com->do_dcd_timestamp 1351 && !(com->last_modem_status & MSR_DCD) 1352 && modem_status & MSR_DCD) 1353 microtime(&com->dcd_timestamp); 1354 1355 /* 1356 * Schedule high level to handle DCD changes. Note 1357 * that we don't use the delta bits anywhere. Some 1358 * UARTs mess them up, and it's easy to remember the 1359 * previous bits and calculate the delta. 1360 */ 1361 com->last_modem_status = modem_status; 1362 if (!(com->state & CS_CHECKMSR)) { 1363 com_events += LOTS_OF_EVENTS; 1364 com->state |= CS_CHECKMSR; 1365 swi_sched(sio_ih, 0); 1366 } 1367 1368#ifdef SOFT_CTS_OFLOW 1369 /* handle CTS change immediately for crisp flow ctl */ 1370 if (com->state & CS_CTS_OFLOW) { 1371 if (modem_status & MSR_CTS) { 1372 com->state |= CS_ODEVREADY; 1373 if (com->state >= (CS_BUSY | CS_TTGO 1374 | CS_ODEVREADY) 1375 && !(com->intr_enable 1376 & CD1400_SRER_TXRDY)) 1377 cd_outb(iobase, CD1400_SRER, 1378 cy_align, 1379 com->intr_enable 1380 = com->intr_enable 1381 & ~CD1400_SRER_TXMPTY 1382 | CD1400_SRER_TXRDY); 1383 } else { 1384 com->state &= ~CS_ODEVREADY; 1385 if (com->intr_enable 1386 & CD1400_SRER_TXRDY) 1387 cd_outb(iobase, CD1400_SRER, 1388 cy_align, 1389 com->intr_enable 1390 = com->intr_enable 1391 & ~CD1400_SRER_TXRDY 1392 | CD1400_SRER_TXMPTY); 1393 } 1394 } 1395#endif 1396 } 1397 1398 /* terminate service context */ 1399#ifdef PollMode 1400 cd_outb(iobase, CD1400_MIR, cy_align, 1401 save_mir 1402 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); 1403#else 1404 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1405#endif 1406 } 1407 if (status & CD1400_SVRR_TXRDY) { 1408 struct com_s *com; 1409#ifdef PollMode 1410 u_char save_tir; 1411#else 1412 u_char vector; 1413#endif 1414 1415#ifdef PollMode 1416 save_tir = cd_inb(iobase, CD1400_TIR, cy_align); 1417 1418 /* enter tx service */ 1419 cd_outb(iobase, CD1400_CAR, cy_align, save_tir); 1420 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1421 = save_tir & CD1400_CAR_CHAN; 1422 1423 com = com_addr(baseu 1424 + cyu * CD1400_NO_OF_CHANNELS 1425 + (save_tir & CD1400_TIR_CHAN)); 1426#else 1427 /* ack transmit service */ 1428 vector = cy_inb(iobase, CY8_SVCACKT, cy_align); 1429 1430 com = com_addr(baseu 1431 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1432 & CD1400_xIVR_CHAN)); 1433#endif 1434 1435 if (com->etc != ETC_NONE) { 1436 if (com->intr_enable & CD1400_SRER_TXRDY) { 1437 /* 1438 * Here due to sloppy SRER_TXRDY 1439 * enabling. Ignore. Come back when 1440 * tx is empty. 1441 */ 1442 cd_outb(iobase, CD1400_SRER, cy_align, 1443 com->intr_enable 1444 = (com->intr_enable 1445 & ~CD1400_SRER_TXRDY) 1446 | CD1400_SRER_TXMPTY); 1447 goto terminate_tx_service; 1448 } 1449 switch (com->etc) { 1450 case CD1400_ETC_SENDBREAK: 1451 case CD1400_ETC_STOPBREAK: 1452 /* 1453 * Start the command. Come back on 1454 * next tx empty interrupt, hopefully 1455 * after command has been executed. 1456 */ 1457 cd_outb(iobase, CD1400_COR2, cy_align, 1458 com->cor[1] |= CD1400_COR2_ETC); 1459 cd_outb(iobase, CD1400_TDR, cy_align, 1460 CD1400_ETC_CMD); 1461 cd_outb(iobase, CD1400_TDR, cy_align, 1462 com->etc); 1463 if (com->etc == CD1400_ETC_SENDBREAK) 1464 com->etc = ETC_BREAK_STARTING; 1465 else 1466 com->etc = ETC_BREAK_ENDING; 1467 goto terminate_tx_service; 1468 case ETC_BREAK_STARTING: 1469 /* 1470 * BREAK is now on. Continue with 1471 * SRER_TXMPTY processing, hopefully 1472 * don't come back. 1473 */ 1474 com->etc = ETC_BREAK_STARTED; 1475 break; 1476 case ETC_BREAK_STARTED: 1477 /* 1478 * Came back due to sloppy SRER_TXMPTY 1479 * enabling. Hope again. 1480 */ 1481 break; 1482 case ETC_BREAK_ENDING: 1483 /* 1484 * BREAK is now off. Continue with 1485 * SRER_TXMPTY processing and don't 1486 * come back. The SWI handler will 1487 * restart tx interrupts if necessary. 1488 */ 1489 cd_outb(iobase, CD1400_COR2, cy_align, 1490 com->cor[1] 1491 &= ~CD1400_COR2_ETC); 1492 com->etc = ETC_BREAK_ENDED; 1493 if (!(com->state & CS_ODONE)) { 1494 com_events += LOTS_OF_EVENTS; 1495 com->state |= CS_ODONE; 1496 swi_sched(sio_ih, 0); 1497 } 1498 break; 1499 case ETC_BREAK_ENDED: 1500 /* 1501 * Shouldn't get here. Hope again. 1502 */ 1503 break; 1504 } 1505 } 1506 if (com->intr_enable & CD1400_SRER_TXMPTY) { 1507 if (!(com->extra_state & CSE_ODONE)) { 1508 com_events += LOTS_OF_EVENTS; 1509 com->extra_state |= CSE_ODONE; 1510 swi_sched(sio_ih, 0); 1511 } 1512 cd_outb(iobase, CD1400_SRER, cy_align, 1513 com->intr_enable 1514 &= ~CD1400_SRER_TXMPTY); 1515 goto terminate_tx_service; 1516 } 1517 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1518 u_char *ioptr; 1519 u_int ocount; 1520 1521 ioptr = com->obufq.l_head; 1522 ocount = com->obufq.l_tail - ioptr; 1523 if (ocount > CD1400_TX_FIFO_SIZE) 1524 ocount = CD1400_TX_FIFO_SIZE; 1525 com->bytes_out += ocount; 1526 do 1527 cd_outb(iobase, CD1400_TDR, cy_align, 1528 *ioptr++); 1529 while (--ocount != 0); 1530 com->obufq.l_head = ioptr; 1531 if (ioptr >= com->obufq.l_tail) { 1532 struct lbq *qp; 1533 1534 qp = com->obufq.l_next; 1535 qp->l_queued = FALSE; 1536 qp = qp->l_next; 1537 if (qp != NULL) { 1538 com->obufq.l_head = qp->l_head; 1539 com->obufq.l_tail = qp->l_tail; 1540 com->obufq.l_next = qp; 1541 } else { 1542 /* output just completed */ 1543 com->state &= ~CS_BUSY; 1544 1545 /* 1546 * The setting of CSE_ODONE may be 1547 * stale here. We currently only 1548 * use it when CS_BUSY is set, and 1549 * fixing it when we clear CS_BUSY 1550 * is easiest. 1551 */ 1552 if (com->extra_state & CSE_ODONE) { 1553 com_events -= LOTS_OF_EVENTS; 1554 com->extra_state &= ~CSE_ODONE; 1555 } 1556 1557 cd_outb(iobase, CD1400_SRER, cy_align, 1558 com->intr_enable 1559 = (com->intr_enable 1560 & ~CD1400_SRER_TXRDY) 1561 | CD1400_SRER_TXMPTY); 1562 } 1563 if (!(com->state & CS_ODONE)) { 1564 com_events += LOTS_OF_EVENTS; 1565 com->state |= CS_ODONE; 1566 1567 /* handle at high level ASAP */ 1568 swi_sched(sio_ih, 0); 1569 } 1570 } 1571 } 1572 1573 /* terminate service context */ 1574terminate_tx_service: 1575#ifdef PollMode 1576 cd_outb(iobase, CD1400_TIR, cy_align, 1577 save_tir 1578 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); 1579#else 1580 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1581#endif 1582 } 1583 } 1584 1585 /* ensure an edge for the next interrupt */ 1586 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 1587 1588 swi_sched(sio_ih, 0); 1589 1590 COM_UNLOCK(); 1591} 1592 1593#if 0 1594static void 1595siointr1(com) 1596 struct com_s *com; 1597{ 1598} 1599#endif 1600 1601static int 1602sioioctl(dev, cmd, data, flag, td) 1603 dev_t dev; 1604 u_long cmd; 1605 caddr_t data; 1606 int flag; 1607 struct thread *td; 1608{ 1609 struct com_s *com; 1610 int error; 1611 int mynor; 1612 int s; 1613 struct tty *tp; 1614#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1615 int oldcmd; 1616 struct termios term; 1617#endif 1618 1619 mynor = minor(dev); 1620 com = com_addr(MINOR_TO_UNIT(mynor)); 1621 if (mynor & CONTROL_MASK) { 1622 struct termios *ct; 1623 1624 switch (mynor & CONTROL_MASK) { 1625 case CONTROL_INIT_STATE: 1626 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 1627 break; 1628 case CONTROL_LOCK_STATE: 1629 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 1630 break; 1631 default: 1632 return (ENODEV); /* /dev/nodev */ 1633 } 1634 switch (cmd) { 1635 case TIOCSETA: 1636 error = suser(td); 1637 if (error != 0) 1638 return (error); 1639 *ct = *(struct termios *)data; 1640 return (0); 1641 case TIOCGETA: 1642 *(struct termios *)data = *ct; 1643 return (0); 1644 case TIOCGETD: 1645 *(int *)data = TTYDISC; 1646 return (0); 1647 case TIOCGWINSZ: 1648 bzero(data, sizeof(struct winsize)); 1649 return (0); 1650 default: 1651 return (ENOTTY); 1652 } 1653 } 1654 tp = com->tp; 1655#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1656 term = tp->t_termios; 1657 oldcmd = cmd; 1658 error = ttsetcompat(tp, &cmd, data, &term); 1659 if (error != 0) 1660 return (error); 1661 if (cmd != oldcmd) 1662 data = (caddr_t)&term; 1663#endif 1664 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1665 int cc; 1666 struct termios *dt = (struct termios *)data; 1667 struct termios *lt = mynor & CALLOUT_MASK 1668 ? &com->lt_out : &com->lt_in; 1669 1670 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1671 | (dt->c_iflag & ~lt->c_iflag); 1672 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1673 | (dt->c_oflag & ~lt->c_oflag); 1674 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1675 | (dt->c_cflag & ~lt->c_cflag); 1676 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1677 | (dt->c_lflag & ~lt->c_lflag); 1678 for (cc = 0; cc < NCCS; ++cc) 1679 if (lt->c_cc[cc] != 0) 1680 dt->c_cc[cc] = tp->t_cc[cc]; 1681 if (lt->c_ispeed != 0) 1682 dt->c_ispeed = tp->t_ispeed; 1683 if (lt->c_ospeed != 0) 1684 dt->c_ospeed = tp->t_ospeed; 1685 } 1686 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); 1687 if (error != ENOIOCTL) 1688 return (error); 1689 s = spltty(); 1690 error = ttioctl(tp, cmd, data, flag); 1691 disc_optim(tp, &tp->t_termios, com); 1692 if (error != ENOIOCTL) { 1693 splx(s); 1694 return (error); 1695 } 1696 switch (cmd) { 1697 case TIOCSBRK: 1698#if 0 1699 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 1700#else 1701 cd_etc(com, CD1400_ETC_SENDBREAK); 1702#endif 1703 break; 1704 case TIOCCBRK: 1705#if 0 1706 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1707#else 1708 cd_etc(com, CD1400_ETC_STOPBREAK); 1709#endif 1710 break; 1711 case TIOCSDTR: 1712 (void)commctl(com, TIOCM_DTR, DMBIS); 1713 break; 1714 case TIOCCDTR: 1715 (void)commctl(com, TIOCM_DTR, DMBIC); 1716 break; 1717 /* 1718 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 1719 * changes get undone on the next call to comparam(). 1720 */ 1721 case TIOCMSET: 1722 (void)commctl(com, *(int *)data, DMSET); 1723 break; 1724 case TIOCMBIS: 1725 (void)commctl(com, *(int *)data, DMBIS); 1726 break; 1727 case TIOCMBIC: 1728 (void)commctl(com, *(int *)data, DMBIC); 1729 break; 1730 case TIOCMGET: 1731 *(int *)data = commctl(com, 0, DMGET); 1732 break; 1733 case TIOCMSDTRWAIT: 1734 /* must be root since the wait applies to following logins */ 1735 error = suser(td); 1736 if (error != 0) { 1737 splx(s); 1738 return (error); 1739 } 1740 com->dtr_wait = *(int *)data * hz / 100; 1741 break; 1742 case TIOCMGDTRWAIT: 1743 *(int *)data = com->dtr_wait * 100 / hz; 1744 break; 1745 case TIOCTIMESTAMP: 1746 com->do_timestamp = TRUE; 1747 *(struct timeval *)data = com->timestamp; 1748 break; 1749 case TIOCDCDTIMESTAMP: 1750 com->do_dcd_timestamp = TRUE; 1751 *(struct timeval *)data = com->dcd_timestamp; 1752 break; 1753 default: 1754 splx(s); 1755 return (ENOTTY); 1756 } 1757 splx(s); 1758 return (0); 1759} 1760 1761static void 1762siopoll(void *arg) 1763{ 1764 int unit; 1765 1766#ifdef CyDebug 1767 ++cy_timeouts; 1768#endif 1769 if (com_events == 0) 1770 return; 1771repeat: 1772 for (unit = 0; unit < NSIO; ++unit) { 1773 struct com_s *com; 1774 int incc; 1775 struct tty *tp; 1776 1777 com = com_addr(unit); 1778 if (com == NULL) 1779 continue; 1780 tp = com->tp; 1781 if (tp == NULL) { 1782 /* 1783 * XXX forget any events related to closed devices 1784 * (actually never opened devices) so that we don't 1785 * loop. 1786 */ 1787 critical_enter(); 1788 COM_LOCK(); 1789 incc = com->iptr - com->ibuf; 1790 com->iptr = com->ibuf; 1791 if (com->state & CS_CHECKMSR) { 1792 incc += LOTS_OF_EVENTS; 1793 com->state &= ~CS_CHECKMSR; 1794 } 1795 com_events -= incc; 1796 COM_UNLOCK(); 1797 critical_exit(); 1798 if (incc != 0) 1799 log(LOG_DEBUG, 1800 "sio%d: %d events for device with no tp\n", 1801 unit, incc); 1802 continue; 1803 } 1804 if (com->iptr != com->ibuf) { 1805 critical_enter(); 1806 COM_LOCK(); 1807 sioinput(com); 1808 COM_UNLOCK(); 1809 critical_exit(); 1810 } 1811 if (com->state & CS_CHECKMSR) { 1812 u_char delta_modem_status; 1813 1814 critical_enter(); 1815 COM_LOCK(); 1816 sioinput(com); 1817 delta_modem_status = com->last_modem_status 1818 ^ com->prev_modem_status; 1819 com->prev_modem_status = com->last_modem_status; 1820 com_events -= LOTS_OF_EVENTS; 1821 com->state &= ~CS_CHECKMSR; 1822 COM_UNLOCK(); 1823 critical_exit(); 1824 if (delta_modem_status & MSR_DCD) 1825 (*linesw[tp->t_line].l_modem) 1826 (tp, com->prev_modem_status & MSR_DCD); 1827 } 1828 if (com->extra_state & CSE_ODONE) { 1829 critical_enter(); 1830 COM_LOCK(); 1831 com_events -= LOTS_OF_EVENTS; 1832 com->extra_state &= ~CSE_ODONE; 1833 COM_UNLOCK(); 1834 critical_exit(); 1835 if (!(com->state & CS_BUSY)) { 1836 tp->t_state &= ~TS_BUSY; 1837 ttwwakeup(com->tp); 1838 } 1839 if (com->etc != ETC_NONE) { 1840 if (com->etc == ETC_BREAK_ENDED) 1841 com->etc = ETC_NONE; 1842 wakeup(&com->etc); 1843 } 1844 } 1845 if (com->state & CS_ODONE) { 1846 critical_enter(); 1847 COM_LOCK(); 1848 com_events -= LOTS_OF_EVENTS; 1849 com->state &= ~CS_ODONE; 1850 COM_UNLOCK(); 1851 critical_exit(); 1852 (*linesw[tp->t_line].l_start)(tp); 1853 } 1854 if (com_events == 0) 1855 break; 1856 } 1857 if (com_events >= LOTS_OF_EVENTS) 1858 goto repeat; 1859} 1860 1861static int 1862comparam(tp, t) 1863 struct tty *tp; 1864 struct termios *t; 1865{ 1866 int bits; 1867 int cflag; 1868 struct com_s *com; 1869 u_char cor_change; 1870 u_long cy_clock; 1871 int idivisor; 1872 int iflag; 1873 int iprescaler; 1874 int itimeout; 1875 int odivisor; 1876 int oprescaler; 1877 u_char opt; 1878 int s; 1879 int unit; 1880 1881 /* do historical conversions */ 1882 if (t->c_ispeed == 0) 1883 t->c_ispeed = t->c_ospeed; 1884 1885 unit = DEV_TO_UNIT(tp->t_dev); 1886 com = com_addr(unit); 1887 1888 /* check requested parameters */ 1889 cy_clock = CY_CLOCK(com->gfrcr_image); 1890 idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler); 1891 if (idivisor < 0) 1892 return (EINVAL); 1893 odivisor = comspeed(t->c_ospeed, cy_clock, &oprescaler); 1894 if (odivisor < 0) 1895 return (EINVAL); 1896 1897 /* parameters are OK, convert them to the com struct and the device */ 1898 s = spltty(); 1899 if (odivisor == 0) 1900 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 1901 else 1902 (void)commctl(com, TIOCM_DTR, DMBIS); 1903 1904 (void) siosetwater(com, t->c_ispeed); 1905 1906 /* XXX we don't actually change the speed atomically. */ 1907 1908 if (idivisor != 0) { 1909 cd_setreg(com, CD1400_RBPR, idivisor); 1910 cd_setreg(com, CD1400_RCOR, iprescaler); 1911 } 1912 if (odivisor != 0) { 1913 cd_setreg(com, CD1400_TBPR, odivisor); 1914 cd_setreg(com, CD1400_TCOR, oprescaler); 1915 } 1916 1917 /* 1918 * channel control 1919 * receiver enable 1920 * transmitter enable (always set) 1921 */ 1922 cflag = t->c_cflag; 1923 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 1924 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 1925 if (opt != com->channel_control) { 1926 com->channel_control = opt; 1927 cd1400_channel_cmd(com, opt); 1928 } 1929 1930#ifdef Smarts 1931 /* set special chars */ 1932 /* XXX if one is _POSIX_VDISABLE, can't use some others */ 1933 if (t->c_cc[VSTOP] != _POSIX_VDISABLE) 1934 cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); 1935 if (t->c_cc[VSTART] != _POSIX_VDISABLE) 1936 cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); 1937 if (t->c_cc[VINTR] != _POSIX_VDISABLE) 1938 cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); 1939 if (t->c_cc[VSUSP] != _POSIX_VDISABLE) 1940 cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); 1941#endif 1942 1943 /* 1944 * set channel option register 1 - 1945 * parity mode 1946 * stop bits 1947 * char length 1948 */ 1949 opt = 0; 1950 /* parity */ 1951 if (cflag & PARENB) { 1952 if (cflag & PARODD) 1953 opt |= CD1400_COR1_PARODD; 1954 opt |= CD1400_COR1_PARNORMAL; 1955 } 1956 iflag = t->c_iflag; 1957 if (!(iflag & INPCK)) 1958 opt |= CD1400_COR1_NOINPCK; 1959 bits = 1 + 1; 1960 /* stop bits */ 1961 if (cflag & CSTOPB) { 1962 ++bits; 1963 opt |= CD1400_COR1_STOP2; 1964 } 1965 /* char length */ 1966 switch (cflag & CSIZE) { 1967 case CS5: 1968 bits += 5; 1969 opt |= CD1400_COR1_CS5; 1970 break; 1971 case CS6: 1972 bits += 6; 1973 opt |= CD1400_COR1_CS6; 1974 break; 1975 case CS7: 1976 bits += 7; 1977 opt |= CD1400_COR1_CS7; 1978 break; 1979 default: 1980 bits += 8; 1981 opt |= CD1400_COR1_CS8; 1982 break; 1983 } 1984 cor_change = 0; 1985 if (opt != com->cor[0]) { 1986 cor_change |= CD1400_CCR_COR1; 1987 cd_setreg(com, CD1400_COR1, com->cor[0] = opt); 1988 } 1989 1990 /* 1991 * Set receive time-out period, normally to max(one char time, 5 ms). 1992 */ 1993 if (t->c_ispeed == 0) 1994 itimeout = cd_getreg(com, CD1400_RTPR); 1995 else { 1996 itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; 1997#ifdef SOFT_HOTCHAR 1998#define MIN_RTP 1 1999#else 2000#define MIN_RTP 5 2001#endif 2002 if (itimeout < MIN_RTP) 2003 itimeout = MIN_RTP; 2004 } 2005 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 2006 && t->c_cc[VTIME] * 10 > itimeout) 2007 itimeout = t->c_cc[VTIME] * 10; 2008 if (itimeout > 255) 2009 itimeout = 255; 2010 cd_setreg(com, CD1400_RTPR, itimeout); 2011 2012 /* 2013 * set channel option register 2 - 2014 * flow control 2015 */ 2016 opt = 0; 2017#ifdef Smarts 2018 if (iflag & IXANY) 2019 opt |= CD1400_COR2_IXANY; 2020 if (iflag & IXOFF) 2021 opt |= CD1400_COR2_IXOFF; 2022#endif 2023#ifndef SOFT_CTS_OFLOW 2024 if (cflag & CCTS_OFLOW) 2025 opt |= CD1400_COR2_CCTS_OFLOW; 2026#endif 2027 critical_enter(); 2028 COM_LOCK(); 2029 if (opt != com->cor[1]) { 2030 cor_change |= CD1400_CCR_COR2; 2031 cd_setreg(com, CD1400_COR2, com->cor[1] = opt); 2032 } 2033 COM_UNLOCK(); 2034 critical_exit(); 2035 2036 /* 2037 * set channel option register 3 - 2038 * receiver FIFO interrupt threshold 2039 * flow control 2040 */ 2041 opt = RxFifoThreshold; 2042#ifdef Smarts 2043 if (t->c_lflag & ICANON) 2044 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 2045 if (iflag & IXOFF) 2046 /* detect and transparently handle START and STOP chars */ 2047 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 2048#endif 2049 if (opt != com->cor[2]) { 2050 cor_change |= CD1400_CCR_COR3; 2051 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2052 } 2053 2054 /* notify the CD1400 if COR1-3 have changed */ 2055 if (cor_change) 2056 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); 2057 2058 /* 2059 * set channel option register 4 - 2060 * CR/NL processing 2061 * break processing 2062 * received exception processing 2063 */ 2064 opt = 0; 2065 if (iflag & IGNCR) 2066 opt |= CD1400_COR4_IGNCR; 2067#ifdef Smarts 2068 /* 2069 * we need a new ttyinput() for this, as we don't want to 2070 * have ICRNL && INLCR being done in both layers, or to have 2071 * synchronisation problems 2072 */ 2073 if (iflag & ICRNL) 2074 opt |= CD1400_COR4_ICRNL; 2075 if (iflag & INLCR) 2076 opt |= CD1400_COR4_INLCR; 2077#endif 2078 if (iflag & IGNBRK) 2079 opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; 2080 /* 2081 * The `-ignbrk -brkint parmrk' case is not handled by the hardware, 2082 * so only tell the hardware about -brkint if -parmrk. 2083 */ 2084 if (!(iflag & (BRKINT | PARMRK))) 2085 opt |= CD1400_COR4_NOBRKINT; 2086#if 0 2087 /* XXX using this "intelligence" breaks reporting of overruns. */ 2088 if (iflag & IGNPAR) 2089 opt |= CD1400_COR4_PFO_DISCARD; 2090 else { 2091 if (iflag & PARMRK) 2092 opt |= CD1400_COR4_PFO_ESC; 2093 else 2094 opt |= CD1400_COR4_PFO_NUL; 2095 } 2096#else 2097 opt |= CD1400_COR4_PFO_EXCEPTION; 2098#endif 2099 cd_setreg(com, CD1400_COR4, opt); 2100 2101 /* 2102 * set channel option register 5 - 2103 */ 2104 opt = 0; 2105 if (iflag & ISTRIP) 2106 opt |= CD1400_COR5_ISTRIP; 2107 if (t->c_iflag & IEXTEN) 2108 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 2109 opt |= CD1400_COR5_LNEXT; 2110#ifdef Smarts 2111 if (t->c_oflag & ONLCR) 2112 opt |= CD1400_COR5_ONLCR; 2113 if (t->c_oflag & OCRNL) 2114 opt |= CD1400_COR5_OCRNL; 2115#endif 2116 cd_setreg(com, CD1400_COR5, opt); 2117 2118 /* 2119 * We always generate modem status change interrupts for CD changes. 2120 * Among other things, this is necessary to track TS_CARR_ON for 2121 * pstat to print even when the driver doesn't care. CD changes 2122 * should be rare so interrupts for them are not worth extra code to 2123 * avoid. We avoid interrupts for other modem status changes (except 2124 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is 2125 * simplest and best. 2126 */ 2127 2128 /* 2129 * set modem change option register 1 2130 * generate modem interrupts on which 1 -> 0 input transitions 2131 * also controls auto-DTR output flow-control, which we don't use 2132 */ 2133 opt = CD1400_MCOR1_CDzd; 2134#ifdef SOFT_CTS_OFLOW 2135 if (cflag & CCTS_OFLOW) 2136 opt |= CD1400_MCOR1_CTSzd; 2137#endif 2138 cd_setreg(com, CD1400_MCOR1, opt); 2139 2140 /* 2141 * set modem change option register 2 2142 * generate modem interrupts on specific 0 -> 1 input transitions 2143 */ 2144 opt = CD1400_MCOR2_CDod; 2145#ifdef SOFT_CTS_OFLOW 2146 if (cflag & CCTS_OFLOW) 2147 opt |= CD1400_MCOR2_CTSod; 2148#endif 2149 cd_setreg(com, CD1400_MCOR2, opt); 2150 2151 /* 2152 * XXX should have done this long ago, but there is too much state 2153 * to change all atomically. 2154 */ 2155 critical_enter(); 2156 COM_LOCK(); 2157 2158 com->state &= ~CS_TTGO; 2159 if (!(tp->t_state & TS_TTSTOP)) 2160 com->state |= CS_TTGO; 2161 if (cflag & CRTS_IFLOW) { 2162 com->state |= CS_RTS_IFLOW; 2163 /* 2164 * If CS_RTS_IFLOW just changed from off to on, the change 2165 * needs to be propagated to MCR_RTS. This isn't urgent, 2166 * so do it later by calling comstart() instead of repeating 2167 * a lot of code from comstart() here. 2168 */ 2169 } else if (com->state & CS_RTS_IFLOW) { 2170 com->state &= ~CS_RTS_IFLOW; 2171 /* 2172 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2173 * on here, since comstart() won't do it later. 2174 */ 2175#if 0 2176 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2177#else 2178 cd_setreg(com, com->mcr_rts_reg, 2179 com->mcr_image |= com->mcr_rts); 2180#endif 2181 } 2182 2183 /* 2184 * Set up state to handle output flow control. 2185 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2186 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2187 */ 2188 com->state |= CS_ODEVREADY; 2189#ifdef SOFT_CTS_OFLOW 2190 com->state &= ~CS_CTS_OFLOW; 2191 if (cflag & CCTS_OFLOW) { 2192 com->state |= CS_CTS_OFLOW; 2193 if (!(com->last_modem_status & MSR_CTS)) 2194 com->state &= ~CS_ODEVREADY; 2195 } 2196#endif 2197 /* XXX shouldn't call functions while intrs are disabled. */ 2198 disc_optim(tp, t, com); 2199#if 0 2200 /* 2201 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2202 * unconditionally, but that defeated the careful discarding of 2203 * stale input in sioopen(). 2204 */ 2205 if (com->state >= (CS_BUSY | CS_TTGO)) 2206 siointr1(com); 2207#endif 2208 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2209 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 2210 cd_setreg(com, CD1400_SRER, 2211 com->intr_enable 2212 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2213 | CD1400_SRER_TXRDY); 2214 } else { 2215 if (com->intr_enable & CD1400_SRER_TXRDY) 2216 cd_setreg(com, CD1400_SRER, 2217 com->intr_enable 2218 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2219 | CD1400_SRER_TXMPTY); 2220 } 2221 2222 COM_UNLOCK(); 2223 critical_exit(); 2224 splx(s); 2225 comstart(tp); 2226 if (com->ibufold != NULL) { 2227 free(com->ibufold, M_DEVBUF); 2228 com->ibufold = NULL; 2229 } 2230 return (0); 2231} 2232 2233static int 2234siosetwater(com, speed) 2235 struct com_s *com; 2236 speed_t speed; 2237{ 2238 int cp4ticks; 2239 u_char *ibuf; 2240 int ibufsize; 2241 struct tty *tp; 2242 2243 /* 2244 * Make the buffer size large enough to handle a softtty interrupt 2245 * latency of about 2 ticks without loss of throughput or data 2246 * (about 3 ticks if input flow control is not used or not honoured, 2247 * but a bit less for CS5-CS7 modes). 2248 */ 2249 cp4ticks = speed / 10 / hz * 4; 2250 for (ibufsize = 128; ibufsize < cp4ticks;) 2251 ibufsize <<= 1; 2252 if (ibufsize == com->ibufsize) { 2253 return (0); 2254 } 2255 2256 /* 2257 * Allocate input buffer. The extra factor of 2 in the size is 2258 * to allow for an error byte for each input byte. 2259 */ 2260 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 2261 if (ibuf == NULL) { 2262 return (ENOMEM); 2263 } 2264 2265 /* Initialize non-critical variables. */ 2266 com->ibufold = com->ibuf; 2267 com->ibufsize = ibufsize; 2268 tp = com->tp; 2269 if (tp != NULL) { 2270 tp->t_ififosize = 2 * ibufsize; 2271 tp->t_ispeedwat = (speed_t)-1; 2272 tp->t_ospeedwat = (speed_t)-1; 2273 } 2274 2275 /* 2276 * Read current input buffer, if any. Continue with interrupts 2277 * disabled. 2278 */ 2279 critical_enter(); 2280 COM_LOCK(); 2281 if (com->iptr != com->ibuf) 2282 sioinput(com); 2283 2284 /*- 2285 * Initialize critical variables, including input buffer watermarks. 2286 * The external device is asked to stop sending when the buffer 2287 * exactly reaches high water, or when the high level requests it. 2288 * The high level is notified immediately (rather than at a later 2289 * clock tick) when this watermark is reached. 2290 * The buffer size is chosen so the watermark should almost never 2291 * be reached. 2292 * The low watermark is invisibly 0 since the buffer is always 2293 * emptied all at once. 2294 */ 2295 com->iptr = com->ibuf = ibuf; 2296 com->ibufend = ibuf + ibufsize; 2297 com->ierroff = ibufsize; 2298 com->ihighwater = ibuf + 3 * ibufsize / 4; 2299 2300 COM_UNLOCK(); 2301 critical_exit(); 2302 return (0); 2303} 2304 2305static void 2306comstart(tp) 2307 struct tty *tp; 2308{ 2309 struct com_s *com; 2310 int s; 2311#ifdef CyDebug 2312 bool_t started; 2313#endif 2314 int unit; 2315 2316 unit = DEV_TO_UNIT(tp->t_dev); 2317 com = com_addr(unit); 2318 s = spltty(); 2319 2320#ifdef CyDebug 2321 ++com->start_count; 2322 started = FALSE; 2323#endif 2324 2325 critical_enter(); 2326 COM_LOCK(); 2327 if (tp->t_state & TS_TTSTOP) { 2328 com->state &= ~CS_TTGO; 2329 if (com->intr_enable & CD1400_SRER_TXRDY) 2330 cd_setreg(com, CD1400_SRER, 2331 com->intr_enable 2332 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2333 | CD1400_SRER_TXMPTY); 2334 } else { 2335 com->state |= CS_TTGO; 2336 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2337 && !(com->intr_enable & CD1400_SRER_TXRDY)) 2338 cd_setreg(com, CD1400_SRER, 2339 com->intr_enable 2340 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2341 | CD1400_SRER_TXRDY); 2342 } 2343 if (tp->t_state & TS_TBLOCK) { 2344 if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) 2345#if 0 2346 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2347#else 2348 cd_setreg(com, com->mcr_rts_reg, 2349 com->mcr_image &= ~com->mcr_rts); 2350#endif 2351 } else { 2352 if (!(com->mcr_image & com->mcr_rts) 2353 && com->iptr < com->ihighwater 2354 && com->state & CS_RTS_IFLOW) 2355#if 0 2356 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2357#else 2358 cd_setreg(com, com->mcr_rts_reg, 2359 com->mcr_image |= com->mcr_rts); 2360#endif 2361 } 2362 COM_UNLOCK(); 2363 critical_exit(); 2364 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2365 ttwwakeup(tp); 2366 splx(s); 2367 return; 2368 } 2369 if (tp->t_outq.c_cc != 0) { 2370 struct lbq *qp; 2371 struct lbq *next; 2372 2373 if (!com->obufs[0].l_queued) { 2374#ifdef CyDebug 2375 started = TRUE; 2376#endif 2377 com->obufs[0].l_tail 2378 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2379 sizeof com->obuf1); 2380 com->obufs[0].l_next = NULL; 2381 com->obufs[0].l_queued = TRUE; 2382 critical_enter(); 2383 COM_LOCK(); 2384 if (com->state & CS_BUSY) { 2385 qp = com->obufq.l_next; 2386 while ((next = qp->l_next) != NULL) 2387 qp = next; 2388 qp->l_next = &com->obufs[0]; 2389 } else { 2390 com->obufq.l_head = com->obufs[0].l_head; 2391 com->obufq.l_tail = com->obufs[0].l_tail; 2392 com->obufq.l_next = &com->obufs[0]; 2393 com->state |= CS_BUSY; 2394 if (com->state >= (CS_BUSY | CS_TTGO 2395 | CS_ODEVREADY)) 2396 cd_setreg(com, CD1400_SRER, 2397 com->intr_enable 2398 = (com->intr_enable 2399 & ~CD1400_SRER_TXMPTY) 2400 | CD1400_SRER_TXRDY); 2401 } 2402 COM_UNLOCK(); 2403 critical_exit(); 2404 } 2405 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2406#ifdef CyDebug 2407 started = TRUE; 2408#endif 2409 com->obufs[1].l_tail 2410 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2411 sizeof com->obuf2); 2412 com->obufs[1].l_next = NULL; 2413 com->obufs[1].l_queued = TRUE; 2414 critical_enter(); 2415 COM_LOCK(); 2416 if (com->state & CS_BUSY) { 2417 qp = com->obufq.l_next; 2418 while ((next = qp->l_next) != NULL) 2419 qp = next; 2420 qp->l_next = &com->obufs[1]; 2421 } else { 2422 com->obufq.l_head = com->obufs[1].l_head; 2423 com->obufq.l_tail = com->obufs[1].l_tail; 2424 com->obufq.l_next = &com->obufs[1]; 2425 com->state |= CS_BUSY; 2426 if (com->state >= (CS_BUSY | CS_TTGO 2427 | CS_ODEVREADY)) 2428 cd_setreg(com, CD1400_SRER, 2429 com->intr_enable 2430 = (com->intr_enable 2431 & ~CD1400_SRER_TXMPTY) 2432 | CD1400_SRER_TXRDY); 2433 } 2434 COM_UNLOCK(); 2435 critical_exit(); 2436 } 2437 tp->t_state |= TS_BUSY; 2438 } 2439#ifdef CyDebug 2440 if (started) 2441 ++com->start_real; 2442#endif 2443#if 0 2444 critical_enter(); 2445 COM_LOCK(); 2446 if (com->state >= (CS_BUSY | CS_TTGO)) 2447 siointr1(com); /* fake interrupt to start output */ 2448 COM_UNLOCK(); 2449 critical_exit(); 2450#endif 2451 ttwwakeup(tp); 2452 splx(s); 2453} 2454 2455static void 2456comstop(tp, rw) 2457 struct tty *tp; 2458 int rw; 2459{ 2460 struct com_s *com; 2461 bool_t wakeup_etc; 2462 2463 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2464 wakeup_etc = FALSE; 2465 critical_enter(); 2466 COM_LOCK(); 2467 if (rw & FWRITE) { 2468 com->obufs[0].l_queued = FALSE; 2469 com->obufs[1].l_queued = FALSE; 2470 if (com->extra_state & CSE_ODONE) { 2471 com_events -= LOTS_OF_EVENTS; 2472 com->extra_state &= ~CSE_ODONE; 2473 if (com->etc != ETC_NONE) { 2474 if (com->etc == ETC_BREAK_ENDED) 2475 com->etc = ETC_NONE; 2476 wakeup_etc = TRUE; 2477 } 2478 } 2479 com->tp->t_state &= ~TS_BUSY; 2480 if (com->state & CS_ODONE) 2481 com_events -= LOTS_OF_EVENTS; 2482 com->state &= ~(CS_ODONE | CS_BUSY); 2483 } 2484 if (rw & FREAD) { 2485 /* XXX no way to reset only input fifo. */ 2486 com_events -= (com->iptr - com->ibuf); 2487 com->iptr = com->ibuf; 2488 } 2489 COM_UNLOCK(); 2490 critical_exit(); 2491 if (wakeup_etc) 2492 wakeup(&com->etc); 2493 if (rw & FWRITE && com->etc == ETC_NONE) 2494 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 2495 comstart(tp); 2496} 2497 2498static int 2499commctl(com, bits, how) 2500 struct com_s *com; 2501 int bits; 2502 int how; 2503{ 2504 int mcr; 2505 int msr; 2506 2507 if (how == DMGET) { 2508 if (com->channel_control & CD1400_CCR_RCVEN) 2509 bits |= TIOCM_LE; 2510 mcr = com->mcr_image; 2511 if (mcr & com->mcr_dtr) 2512 bits |= TIOCM_DTR; 2513 if (mcr & com->mcr_rts) 2514 /* XXX wired on for Cyclom-8Ys */ 2515 bits |= TIOCM_RTS; 2516 2517 /* 2518 * We must read the modem status from the hardware because 2519 * we don't generate modem status change interrupts for all 2520 * changes, so com->prev_modem_status is not guaranteed to 2521 * be up to date. This is safe, unlike for sio, because 2522 * reading the status register doesn't clear pending modem 2523 * status change interrupts. 2524 */ 2525 msr = cd_getreg(com, CD1400_MSVR2); 2526 2527 if (msr & MSR_CTS) 2528 bits |= TIOCM_CTS; 2529 if (msr & MSR_DCD) 2530 bits |= TIOCM_CD; 2531 if (msr & MSR_DSR) 2532 bits |= TIOCM_DSR; 2533 if (msr & MSR_RI) 2534 /* XXX not connected except for Cyclom-16Y? */ 2535 bits |= TIOCM_RI; 2536 return (bits); 2537 } 2538 mcr = 0; 2539 if (bits & TIOCM_DTR) 2540 mcr |= com->mcr_dtr; 2541 if (bits & TIOCM_RTS) 2542 mcr |= com->mcr_rts; 2543 critical_enter(); 2544 COM_LOCK(); 2545 switch (how) { 2546 case DMSET: 2547 com->mcr_image = mcr; 2548 cd_setreg(com, CD1400_MSVR1, mcr); 2549 cd_setreg(com, CD1400_MSVR2, mcr); 2550 break; 2551 case DMBIS: 2552 com->mcr_image = mcr = com->mcr_image | mcr; 2553 cd_setreg(com, CD1400_MSVR1, mcr); 2554 cd_setreg(com, CD1400_MSVR2, mcr); 2555 break; 2556 case DMBIC: 2557 com->mcr_image = mcr = com->mcr_image & ~mcr; 2558 cd_setreg(com, CD1400_MSVR1, mcr); 2559 cd_setreg(com, CD1400_MSVR2, mcr); 2560 break; 2561 } 2562 COM_UNLOCK(); 2563 critical_exit(); 2564 return (0); 2565} 2566 2567static void 2568siosettimeout() 2569{ 2570 struct com_s *com; 2571 bool_t someopen; 2572 int unit; 2573 2574 /* 2575 * Set our timeout period to 1 second if no polled devices are open. 2576 * Otherwise set it to max(1/200, 1/hz). 2577 * Enable timeouts iff some device is open. 2578 */ 2579 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2580 sio_timeout = hz; 2581 someopen = FALSE; 2582 for (unit = 0; unit < NSIO; ++unit) { 2583 com = com_addr(unit); 2584 if (com != NULL && com->tp != NULL 2585 && com->tp->t_state & TS_ISOPEN) { 2586 someopen = TRUE; 2587#if 0 2588 if (com->poll || com->poll_output) { 2589 sio_timeout = hz > 200 ? hz / 200 : 1; 2590 break; 2591 } 2592#endif 2593 } 2594 } 2595 if (someopen) { 2596 sio_timeouts_until_log = hz / sio_timeout; 2597 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 2598 sio_timeout); 2599 } else { 2600 /* Flush error messages, if any. */ 2601 sio_timeouts_until_log = 1; 2602 comwakeup((void *)NULL); 2603 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2604 } 2605} 2606 2607static void 2608comwakeup(chan) 2609 void *chan; 2610{ 2611 struct com_s *com; 2612 int unit; 2613 2614 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 2615 2616#if 0 2617 /* 2618 * Recover from lost output interrupts. 2619 * Poll any lines that don't use interrupts. 2620 */ 2621 for (unit = 0; unit < NSIO; ++unit) { 2622 com = com_addr(unit); 2623 if (com != NULL 2624 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2625 critical_enter(); 2626 COM_LOCK(); 2627 siointr1(com); 2628 COM_UNLOCK(); 2629 critical_exit(); 2630 } 2631 } 2632#endif 2633 2634 /* 2635 * Check for and log errors, but not too often. 2636 */ 2637 if (--sio_timeouts_until_log > 0) 2638 return; 2639 sio_timeouts_until_log = hz / sio_timeout; 2640 for (unit = 0; unit < NSIO; ++unit) { 2641 int errnum; 2642 2643 com = com_addr(unit); 2644 if (com == NULL) 2645 continue; 2646 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2647 u_int delta; 2648 u_long total; 2649 2650 critical_enter(); 2651 COM_LOCK(); 2652 delta = com->delta_error_counts[errnum]; 2653 com->delta_error_counts[errnum] = 0; 2654 COM_UNLOCK(); 2655 critical_exit(); 2656 if (delta == 0) 2657 continue; 2658 total = com->error_counts[errnum] += delta; 2659 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 2660 unit, delta, error_desc[errnum], 2661 delta == 1 ? "" : "s", total); 2662 } 2663 } 2664} 2665 2666static void 2667disc_optim(tp, t, com) 2668 struct tty *tp; 2669 struct termios *t; 2670 struct com_s *com; 2671{ 2672#ifndef SOFT_HOTCHAR 2673 u_char opt; 2674#endif 2675 2676 /* 2677 * XXX can skip a lot more cases if Smarts. Maybe 2678 * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we 2679 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. 2680 */ 2681 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 2682 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2683 && (!(t->c_iflag & PARMRK) 2684 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 2685 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 2686 && linesw[tp->t_line].l_rint == ttyinput) 2687 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2688 else 2689 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2690 com->hotchar = linesw[tp->t_line].l_hotchar; 2691#ifndef SOFT_HOTCHAR 2692 opt = com->cor[2] & ~CD1400_COR3_SCD34; 2693 if (com->hotchar != 0) { 2694 cd_setreg(com, CD1400_SCHR3, com->hotchar); 2695 cd_setreg(com, CD1400_SCHR4, com->hotchar); 2696 opt |= CD1400_COR3_SCD34; 2697 } 2698 if (opt != com->cor[2]) { 2699 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2700 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 2701 } 2702#endif 2703} 2704 2705#ifdef Smarts 2706/* standard line discipline input routine */ 2707int 2708cyinput(c, tp) 2709 int c; 2710 struct tty *tp; 2711{ 2712 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 2713 * bits, as they are done by the CD1400. Hardly worth the effort, 2714 * given that high-throughput sessions are raw anyhow. 2715 */ 2716} 2717#endif /* Smarts */ 2718 2719static int 2720comspeed(speed, cy_clock, prescaler_io) 2721 speed_t speed; 2722 u_long cy_clock; 2723 int *prescaler_io; 2724{ 2725 int actual; 2726 int error; 2727 int divider; 2728 int prescaler; 2729 int prescaler_unit; 2730 2731 if (speed == 0) 2732 return (0); 2733 if (speed < 0 || speed > 150000) 2734 return (-1); 2735 2736 /* determine which prescaler to use */ 2737 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2738 prescaler_unit--, prescaler >>= 2) { 2739 if (cy_clock / prescaler / speed > 63) 2740 break; 2741 } 2742 2743 divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ 2744 if (divider > 255) 2745 divider = 255; 2746 actual = cy_clock/prescaler/divider; 2747 2748 /* 10 times error in percent: */ 2749 error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; 2750 2751 /* 3.0% max error tolerance */ 2752 if (error < -30 || error > 30) 2753 return (-1); 2754 2755#if 0 2756 printf("prescaler = %d (%d)\n", prescaler, prescaler_unit); 2757 printf("divider = %d (%x)\n", divider, divider); 2758 printf("actual = %d\n", actual); 2759 printf("error = %d\n", error); 2760#endif 2761 2762 *prescaler_io = prescaler_unit; 2763 return (divider); 2764} 2765 2766static void 2767cd1400_channel_cmd(com, cmd) 2768 struct com_s *com; 2769 int cmd; 2770{ 2771 cd1400_channel_cmd_wait(com); 2772 cd_setreg(com, CD1400_CCR, cmd); 2773 cd1400_channel_cmd_wait(com); 2774} 2775 2776static void 2777cd1400_channel_cmd_wait(com) 2778 struct com_s *com; 2779{ 2780 struct timeval start; 2781 struct timeval tv; 2782 long usec; 2783 2784 if (cd_getreg(com, CD1400_CCR) == 0) 2785 return; 2786 microtime(&start); 2787 for (;;) { 2788 if (cd_getreg(com, CD1400_CCR) == 0) 2789 return; 2790 microtime(&tv); 2791 usec = 1000000 * (tv.tv_sec - start.tv_sec) + 2792 tv.tv_usec - start.tv_usec; 2793 if (usec >= 5000) { 2794 log(LOG_ERR, 2795 "cy%d: channel command timeout (%ld usec)\n", 2796 com->unit, usec); 2797 return; 2798 } 2799 } 2800} 2801 2802static void 2803cd_etc(com, etc) 2804 struct com_s *com; 2805 int etc; 2806{ 2807 2808 /* 2809 * We can't change the hardware's ETC state while there are any 2810 * characters in the tx fifo, since those characters would be 2811 * interpreted as commands! Unputting characters from the fifo 2812 * is difficult, so we wait up to 12 character times for the fifo 2813 * to drain. The command will be delayed for up to 2 character 2814 * times for the tx to become empty. Unputting characters from 2815 * the tx holding and shift registers is impossible, so we wait 2816 * for the tx to become empty so that the command is sure to be 2817 * executed soon after we issue it. 2818 */ 2819 critical_enter(); 2820 COM_LOCK(); 2821 if (com->etc == etc) 2822 goto wait; 2823 if ((etc == CD1400_ETC_SENDBREAK 2824 && (com->etc == ETC_BREAK_STARTING 2825 || com->etc == ETC_BREAK_STARTED)) 2826 || (etc == CD1400_ETC_STOPBREAK 2827 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED 2828 || com->etc == ETC_NONE))) { 2829 COM_UNLOCK(); 2830 critical_exit(); 2831 return; 2832 } 2833 com->etc = etc; 2834 cd_setreg(com, CD1400_SRER, 2835 com->intr_enable 2836 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); 2837wait: 2838 COM_UNLOCK(); 2839 critical_exit(); 2840 while (com->etc == etc 2841 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) 2842 continue; 2843} 2844 2845static int 2846cd_getreg(com, reg) 2847 struct com_s *com; 2848 int reg; 2849{ 2850 struct com_s *basecom; 2851 u_char car; 2852 int cy_align; 2853 register_t eflags; 2854 cy_addr iobase; 2855 int val; 2856 2857 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2858 car = com->unit & CD1400_CAR_CHAN; 2859 cy_align = com->cy_align; 2860 iobase = com->iobase; 2861 eflags = read_eflags(); 2862 critical_enter(); 2863 if (eflags & PSL_I) 2864 COM_LOCK(); 2865 if (basecom->car != car) 2866 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2867 val = cd_inb(iobase, reg, cy_align); 2868 if (eflags & PSL_I) 2869 COM_UNLOCK(); 2870 critical_exit(); 2871 return (val); 2872} 2873 2874static void 2875cd_setreg(com, reg, val) 2876 struct com_s *com; 2877 int reg; 2878 int val; 2879{ 2880 struct com_s *basecom; 2881 u_char car; 2882 int cy_align; 2883 register_t eflags; 2884 cy_addr iobase; 2885 2886 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2887 car = com->unit & CD1400_CAR_CHAN; 2888 cy_align = com->cy_align; 2889 iobase = com->iobase; 2890 eflags = read_eflags(); 2891 critical_enter(); 2892 if (eflags & PSL_I) 2893 COM_LOCK(); 2894 if (basecom->car != car) 2895 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2896 cd_outb(iobase, reg, cy_align, val); 2897 if (eflags & PSL_I) 2898 COM_UNLOCK(); 2899 critical_exit(); 2900} 2901 2902#ifdef CyDebug 2903/* useful in ddb */ 2904void 2905cystatus(unit) 2906 int unit; 2907{ 2908 struct com_s *com; 2909 cy_addr iobase; 2910 u_int ocount; 2911 struct tty *tp; 2912 2913 com = com_addr(unit); 2914 printf("info for channel %d\n", unit); 2915 printf("------------------\n"); 2916 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2917 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2918 if (com == NULL) 2919 return; 2920 iobase = com->iobase; 2921 printf("\n"); 2922 printf("cd1400 base address:\\tt%p\n", iobase); 2923 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2924 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2925 com->cor[0], com->cor[1], com->cor[2]); 2926 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2927 cd_getreg(com, CD1400_SRER), com->intr_enable); 2928 printf("service request register:\t0x%02x\n", 2929 cd_inb(iobase, CD1400_SVRR, com->cy_align)); 2930 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2931 cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); 2932 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2933 cd_inb(iobase, CD1400_RIR, com->cy_align), 2934 cd_inb(iobase, CD1400_TIR, com->cy_align), 2935 cd_inb(iobase, CD1400_MIR, com->cy_align)); 2936 printf("\n"); 2937 printf("com state:\t\t\t0x%02x\n", com->state); 2938 printf("calls to comstart():\t\t%d (%d useful)\n", 2939 com->start_count, com->start_real); 2940 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2941 ocount = 0; 2942 if (com->obufs[0].l_queued) 2943 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2944 if (com->obufs[1].l_queued) 2945 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2946 printf("tx buffer chars:\t\t%u\n", ocount); 2947 printf("received chars:\t\t\t%d\n", com->bytes_in); 2948 printf("received exceptions:\t\t%d\n", com->recv_exception); 2949 printf("modem signal deltas:\t\t%d\n", com->mdm); 2950 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2951 printf("\n"); 2952 tp = com->tp; 2953 if (tp != NULL) { 2954 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2955 printf( 2956 "upper layer queue lengths:\t%d raw, %d canon, %d output\n", 2957 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 2958 } else 2959 printf("tty state:\t\t\tclosed\n"); 2960} 2961#endif /* CyDebug */
|