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