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