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