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