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