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