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