cy.c revision 43425
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.84 1999/01/28 01:59:53 dillon 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 && 732 suser(p->p_ucred, &p->p_acflag)) { 733 error = EBUSY; 734 goto out; 735 } 736 } else { 737 /* 738 * The device isn't open, so there are no conflicts. 739 * Initialize it. Initialization is done twice in many 740 * cases: to preempt sleeping callin opens if we are 741 * callout, and to complete a callin open after DCD rises. 742 */ 743 tp->t_oproc = comstart; 744 tp->t_param = comparam; 745 tp->t_dev = dev; 746 tp->t_termios = mynor & CALLOUT_MASK 747 ? com->it_out : com->it_in; 748 tp->t_ififosize = 2 * RS_IBUFSIZE; 749 tp->t_ispeedwat = (speed_t)-1; 750 tp->t_ospeedwat = (speed_t)-1; 751 752 /* Encode per-board unit in LIVR for access in intr routines. */ 753 cd_setreg(com, CD1400_LIVR, 754 (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); 755 756 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 757#if 0 758 com->poll = com->no_irq; 759 com->poll_output = com->loses_outints; 760#endif 761 ++com->wopeners; 762 error = comparam(tp, &tp->t_termios); 763 --com->wopeners; 764 if (error != 0) 765 goto out; 766#if 0 767 if (com->hasfifo) { 768 /* 769 * (Re)enable and flush fifos. 770 * 771 * Certain SMC chips cause problems if the fifos 772 * are enabled while input is ready. Turn off the 773 * fifo if necessary to clear the input. We test 774 * the input ready bit after enabling the fifos 775 * since we've already enabled them in comparam() 776 * and to handle races between enabling and fresh 777 * input. 778 */ 779 while (TRUE) { 780 outb(iobase + com_fifo, 781 FIFO_RCV_RST | FIFO_XMT_RST 782 | com->fifo_image); 783 DELAY(100); 784 if (!(inb(com->line_status_port) & LSR_RXRDY)) 785 break; 786 outb(iobase + com_fifo, 0); 787 DELAY(100); 788 (void) inb(com->data_port); 789 } 790 } 791 792 disable_intr(); 793 (void) inb(com->line_status_port); 794 (void) inb(com->data_port); 795 com->prev_modem_status = com->last_modem_status 796 = inb(com->modem_status_port); 797 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS 798 | IER_EMSC); 799 enable_intr(); 800#else /* !0 */ 801 /* 802 * Flush fifos. This requires a full channel reset which 803 * also disables the transmitter and receiver. Recover 804 * from this. 805 */ 806 cd1400_channel_cmd(com, 807 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); 808 cd1400_channel_cmd(com, com->channel_control); 809 810 disable_intr(); 811 com->prev_modem_status = com->last_modem_status 812 = cd_getreg(com, CD1400_MSVR2); 813 cd_setreg(com, CD1400_SRER, 814 com->intr_enable 815 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 816 enable_intr(); 817#endif /* 0 */ 818 /* 819 * Handle initial DCD. Callout devices get a fake initial 820 * DCD (trapdoor DCD). If we are callout, then any sleeping 821 * callin opens get woken up and resume sleeping on "cybi" 822 * instead of "cydcd". 823 */ 824 /* 825 * XXX `mynor & CALLOUT_MASK' should be 826 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 827 * TRAPDOOR_CARRIER is the default initial state for callout 828 * devices and SOFT_CARRIER is like CLOCAL except it hides 829 * the true carrier. 830 */ 831 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 832 (*linesw[tp->t_line].l_modem)(tp, 1); 833 } 834 /* 835 * Wait for DCD if necessary. 836 */ 837 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 838 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 839 ++com->wopeners; 840 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0); 841 --com->wopeners; 842 if (error != 0) 843 goto out; 844 goto open_top; 845 } 846 error = (*linesw[tp->t_line].l_open)(dev, tp); 847 disc_optim(tp, &tp->t_termios, com); 848 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 849 com->active_out = TRUE; 850 siosettimeout(); 851out: 852 splx(s); 853 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 854 comhardclose(com); 855 return (error); 856} 857 858static int 859sioclose(dev, flag, mode, p) 860 dev_t dev; 861 int flag; 862 int mode; 863 struct proc *p; 864{ 865 struct com_s *com; 866 int mynor; 867 int s; 868 struct tty *tp; 869 870 mynor = minor(dev); 871 if (mynor & CONTROL_MASK) 872 return (0); 873 com = com_addr(MINOR_TO_UNIT(mynor)); 874 tp = com->tp; 875 s = spltty(); 876 cd_etc(com, CD1400_ETC_STOPBREAK); 877 (*linesw[tp->t_line].l_close)(tp, flag); 878 disc_optim(tp, &tp->t_termios, com); 879 siostop(tp, FREAD | FWRITE); 880 comhardclose(com); 881 ttyclose(tp); 882 siosettimeout(); 883 splx(s); 884#ifdef broken /* session holds a ref to the tty; can't deallocate */ 885 ttyfree(tp); 886 com->tp = sio_tty[unit] = NULL; 887#endif 888 return (0); 889} 890 891static void 892comhardclose(com) 893 struct com_s *com; 894{ 895 cy_addr iobase; 896 int s; 897 struct tty *tp; 898 int unit; 899 900 unit = com->unit; 901 iobase = com->iobase; 902 s = spltty(); 903#if 0 904 com->poll = FALSE; 905 com->poll_output = FALSE; 906#endif 907 com->do_timestamp = 0; 908#if 0 909 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 910#else 911 /* XXX */ 912 disable_intr(); 913 com->etc = ETC_NONE; 914 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); 915 enable_intr(); 916 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 917#endif 918 919 { 920#if 0 921 outb(iobase + com_ier, 0); 922#else 923 disable_intr(); 924 cd_setreg(com, CD1400_SRER, com->intr_enable = 0); 925 enable_intr(); 926#endif 927 tp = com->tp; 928 if ((tp->t_cflag & HUPCL) 929 /* 930 * XXX we will miss any carrier drop between here and the 931 * next open. Perhaps we should watch DCD even when the 932 * port is closed; it is not sufficient to check it at 933 * the next open because it might go up and down while 934 * we're not watching. 935 */ 936 || (!com->active_out 937 && !(com->prev_modem_status & MSR_DCD) 938 && !(com->it_in.c_cflag & CLOCAL)) 939 || !(tp->t_state & TS_ISOPEN)) { 940 (void)commctl(com, TIOCM_DTR, DMBIC); 941 942 /* Disable receiver (leave transmitter enabled). */ 943 com->channel_control = CD1400_CCR_CMDCHANCTL 944 | CD1400_CCR_XMTEN 945 | CD1400_CCR_RCVDIS; 946 cd1400_channel_cmd(com, com->channel_control); 947 948 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 949 timeout(siodtrwakeup, com, com->dtr_wait); 950 com->state |= CS_DTR_OFF; 951 } 952 } 953 } 954#if 0 955 if (com->hasfifo) { 956 /* 957 * Disable fifos so that they are off after controlled 958 * reboots. Some BIOSes fail to detect 16550s when the 959 * fifos are enabled. 960 */ 961 outb(iobase + com_fifo, 0); 962 } 963#endif 964 com->active_out = FALSE; 965 wakeup(&com->active_out); 966 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 967 splx(s); 968} 969 970static int 971sioread(dev, uio, flag) 972 dev_t dev; 973 struct uio *uio; 974 int flag; 975{ 976 int mynor; 977 struct tty *tp; 978 979 mynor = minor(dev); 980 if (mynor & CONTROL_MASK) 981 return (ENODEV); 982 tp = com_addr(MINOR_TO_UNIT(mynor))->tp; 983 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 984} 985 986static int 987siowrite(dev, uio, flag) 988 dev_t dev; 989 struct uio *uio; 990 int flag; 991{ 992 int mynor; 993 struct tty *tp; 994 int unit; 995 996 mynor = minor(dev); 997 if (mynor & CONTROL_MASK) 998 return (ENODEV); 999 1000 unit = MINOR_TO_UNIT(mynor); 1001 tp = com_addr(unit)->tp; 1002 /* 1003 * (XXX) We disallow virtual consoles if the physical console is 1004 * a serial port. This is in case there is a display attached that 1005 * is not the console. In that situation we don't need/want the X 1006 * server taking over the console. 1007 */ 1008 if (constty != NULL && unit == comconsole) 1009 constty = NULL; 1010#ifdef Smarts 1011 /* XXX duplicate ttwrite(), but without so much output processing on 1012 * CR & LF chars. Hardly worth the effort, given that high-throughput 1013 * sessions are raw anyhow. 1014 */ 1015#else 1016 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1017#endif 1018} 1019 1020static void 1021siodtrwakeup(chan) 1022 void *chan; 1023{ 1024 struct com_s *com; 1025 1026 com = (struct com_s *)chan; 1027 com->state &= ~CS_DTR_OFF; 1028 wakeup(&com->dtr_wait); 1029} 1030 1031void 1032siointr(unit) 1033 int unit; 1034{ 1035 int baseu; 1036 int cy_align; 1037 cy_addr cy_iobase; 1038 int cyu; 1039 cy_addr iobase; 1040 u_char status; 1041 1042 COM_LOCK(); /* XXX could this be placed down lower in the loop? */ 1043 1044 baseu = unit * CY_MAX_PORTS; 1045 cy_align = com_addr(baseu)->cy_align; 1046 cy_iobase = com_addr(baseu)->cy_iobase; 1047 1048 /* check each CD1400 in turn */ 1049 for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { 1050 iobase = (cy_addr) (cy_iobase 1051 + (cy_chip_offset[cyu] << cy_align)); 1052 /* poll to see if it has any work */ 1053 status = cd_inb(iobase, CD1400_SVRR, cy_align); 1054 if (status == 0) 1055 continue; 1056#ifdef CyDebug 1057 ++cy_svrr_probes; 1058#endif 1059 /* service requests as appropriate, giving priority to RX */ 1060 if (status & CD1400_SVRR_RXRDY) { 1061 struct com_s *com; 1062 u_int count; 1063 u_char *ioptr; 1064 u_char line_status; 1065 u_char recv_data; 1066 u_char serv_type; 1067#ifdef PollMode 1068 u_char save_rir; 1069#endif 1070 1071#ifdef PollMode 1072 save_rir = cd_inb(iobase, CD1400_RIR, cy_align); 1073 1074 /* enter rx service */ 1075 cd_outb(iobase, CD1400_CAR, cy_align, save_rir); 1076 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1077 = save_rir & CD1400_CAR_CHAN; 1078 1079 serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); 1080 com = com_addr(baseu 1081 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1082 & CD1400_xIVR_CHAN)); 1083#else 1084 /* ack receive service */ 1085 serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); 1086 1087 com = com_addr(baseu + 1088 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1089 & CD1400_xIVR_CHAN)); 1090#endif 1091 1092 if (serv_type & CD1400_RIVR_EXCEPTION) { 1093 ++com->recv_exception; 1094 line_status = cd_inb(iobase, CD1400_RDSR, cy_align); 1095 /* break/unnattached error bits or real input? */ 1096 recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); 1097#ifndef SOFT_HOTCHAR 1098 if (line_status & CD1400_RDSR_SPECIAL 1099 && com->hotchar != 0) 1100 setsofttty(); 1101#endif 1102#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ 1103 if (line_status & (LSR_PE|LSR_FE|LSR_BI)) { 1104 /* 1105 Don't store PE if IGNPAR and BI if IGNBRK, 1106 this hack allows "raw" tty optimization 1107 works even if IGN* is set. 1108 */ 1109 if ( com->tp == NULL 1110 || !(com->tp->t_state & TS_ISOPEN) 1111 || ((line_status & (LSR_PE|LSR_FE)) 1112 && (com->tp->t_iflag & IGNPAR)) 1113 || ((line_status & LSR_BI) 1114 && (com->tp->t_iflag & IGNBRK))) 1115 goto cont; 1116 if ( (line_status & (LSR_PE|LSR_FE)) 1117 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) 1118 && ((line_status & LSR_FE) 1119 || ((line_status & LSR_PE) 1120 && (com->tp->t_iflag & INPCK)))) 1121 recv_data = 0; 1122 } 1123#endif /* 1 */ 1124 ++com->bytes_in; 1125#ifdef SOFT_HOTCHAR 1126 if (com->hotchar != 0 && recv_data == com->hotchar) 1127 setsofttty(); 1128#endif 1129 ioptr = com->iptr; 1130 if (ioptr >= com->ibufend) 1131 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1132 else { 1133 if (com->do_timestamp) 1134 microtime(&com->timestamp); 1135 ++com_events; 1136 ioptr[0] = recv_data; 1137 ioptr[CE_INPUT_OFFSET] = line_status; 1138 com->iptr = ++ioptr; 1139 if (ioptr == com->ihighwater 1140 && com->state & CS_RTS_IFLOW) 1141#if 0 1142 outb(com->modem_ctl_port, 1143 com->mcr_image &= ~MCR_RTS); 1144#else 1145 cd_outb(iobase, com->mcr_rts_reg, 1146 cy_align, 1147 com->mcr_image &= 1148 ~com->mcr_rts); 1149#endif 1150 if (line_status & LSR_OE) 1151 CE_RECORD(com, CE_OVERRUN); 1152 } 1153 goto cont; 1154 } else { 1155 int ifree; 1156 1157 count = cd_inb(iobase, CD1400_RDCR, cy_align); 1158 if (!count) 1159 goto cont; 1160 com->bytes_in += count; 1161 ioptr = com->iptr; 1162 ifree = com->ibufend - ioptr; 1163 if (count > ifree) { 1164 count -= ifree; 1165 com_events += ifree; 1166 if (ifree != 0) { 1167 if (com->do_timestamp) 1168 microtime(&com->timestamp); 1169 do { 1170 recv_data = cd_inb(iobase, 1171 CD1400_RDSR, 1172 cy_align); 1173#ifdef SOFT_HOTCHAR 1174 if (com->hotchar != 0 1175 && recv_data 1176 == com->hotchar) 1177 setsofttty(); 1178#endif 1179 ioptr[0] = recv_data; 1180 ioptr[CE_INPUT_OFFSET] = 0; 1181 ++ioptr; 1182 } while (--ifree != 0); 1183 } 1184 com->delta_error_counts 1185 [CE_INTERRUPT_BUF_OVERFLOW] += count; 1186 do { 1187 recv_data = cd_inb(iobase, CD1400_RDSR, 1188 cy_align); 1189#ifdef SOFT_HOTCHAR 1190 if (com->hotchar != 0 1191 && recv_data == com->hotchar) 1192 setsofttty(); 1193#endif 1194 } while (--count != 0); 1195 } else { 1196 if (com->do_timestamp) 1197 microtime(&com->timestamp); 1198 if (ioptr <= com->ihighwater 1199 && ioptr + count > com->ihighwater 1200 && com->state & CS_RTS_IFLOW) 1201#if 0 1202 outb(com->modem_ctl_port, 1203 com->mcr_image &= ~MCR_RTS); 1204#else 1205 cd_outb(iobase, com->mcr_rts_reg, 1206 cy_align, 1207 com->mcr_image 1208 &= ~com->mcr_rts); 1209#endif 1210 com_events += count; 1211 do { 1212 recv_data = cd_inb(iobase, CD1400_RDSR, 1213 cy_align); 1214#ifdef SOFT_HOTCHAR 1215 if (com->hotchar != 0 1216 && recv_data == com->hotchar) 1217 setsofttty(); 1218#endif 1219 ioptr[0] = recv_data; 1220 ioptr[CE_INPUT_OFFSET] = 0; 1221 ++ioptr; 1222 } while (--count != 0); 1223 } 1224 com->iptr = ioptr; 1225 } 1226cont: 1227 1228 /* terminate service context */ 1229#ifdef PollMode 1230 cd_outb(iobase, CD1400_RIR, cy_align, 1231 save_rir 1232 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); 1233#else 1234 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1235#endif 1236 } 1237 if (status & CD1400_SVRR_MDMCH) { 1238 struct com_s *com; 1239 u_char modem_status; 1240#ifdef PollMode 1241 u_char save_mir; 1242#else 1243 u_char vector; 1244#endif 1245 1246#ifdef PollMode 1247 save_mir = cd_inb(iobase, CD1400_MIR, cy_align); 1248 1249 /* enter modem service */ 1250 cd_outb(iobase, CD1400_CAR, cy_align, save_mir); 1251 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1252 = save_mir & CD1400_CAR_CHAN; 1253 1254 com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS 1255 + (save_mir & CD1400_MIR_CHAN)); 1256#else 1257 /* ack modem service */ 1258 vector = cy_inb(iobase, CY8_SVCACKM, cy_align); 1259 1260 com = com_addr(baseu 1261 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1262 & CD1400_xIVR_CHAN)); 1263#endif 1264 ++com->mdm; 1265 modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align); 1266 if (modem_status != com->last_modem_status) { 1267 if (com->do_dcd_timestamp 1268 && !(com->last_modem_status & MSR_DCD) 1269 && modem_status & MSR_DCD) 1270 microtime(&com->dcd_timestamp); 1271 1272 /* 1273 * Schedule high level to handle DCD changes. Note 1274 * that we don't use the delta bits anywhere. Some 1275 * UARTs mess them up, and it's easy to remember the 1276 * previous bits and calculate the delta. 1277 */ 1278 com->last_modem_status = modem_status; 1279 if (!(com->state & CS_CHECKMSR)) { 1280 com_events += LOTS_OF_EVENTS; 1281 com->state |= CS_CHECKMSR; 1282 setsofttty(); 1283 } 1284 1285#ifdef SOFT_CTS_OFLOW 1286 /* handle CTS change immediately for crisp flow ctl */ 1287 if (com->state & CS_CTS_OFLOW) { 1288 if (modem_status & MSR_CTS) { 1289 com->state |= CS_ODEVREADY; 1290 if (com->state >= (CS_BUSY | CS_TTGO 1291 | CS_ODEVREADY) 1292 && !(com->intr_enable 1293 & CD1400_SRER_TXRDY)) 1294 cd_outb(iobase, CD1400_SRER, 1295 cy_align, 1296 com->intr_enable 1297 = com->intr_enable 1298 & ~CD1400_SRER_TXMPTY 1299 | CD1400_SRER_TXRDY); 1300 } else { 1301 com->state &= ~CS_ODEVREADY; 1302 if (com->intr_enable 1303 & CD1400_SRER_TXRDY) 1304 cd_outb(iobase, CD1400_SRER, 1305 cy_align, 1306 com->intr_enable 1307 = com->intr_enable 1308 & ~CD1400_SRER_TXRDY 1309 | CD1400_SRER_TXMPTY); 1310 } 1311 } 1312#endif 1313 } 1314 1315 /* terminate service context */ 1316#ifdef PollMode 1317 cd_outb(iobase, CD1400_MIR, cy_align, 1318 save_mir 1319 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); 1320#else 1321 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1322#endif 1323 } 1324 if (status & CD1400_SVRR_TXRDY) { 1325 struct com_s *com; 1326#ifdef PollMode 1327 u_char save_tir; 1328#else 1329 u_char vector; 1330#endif 1331 1332#ifdef PollMode 1333 save_tir = cd_inb(iobase, CD1400_TIR, cy_align); 1334 1335 /* enter tx service */ 1336 cd_outb(iobase, CD1400_CAR, cy_align, save_tir); 1337 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1338 = save_tir & CD1400_CAR_CHAN; 1339 1340 com = com_addr(baseu 1341 + cyu * CD1400_NO_OF_CHANNELS 1342 + (save_tir & CD1400_TIR_CHAN)); 1343#else 1344 /* ack transmit service */ 1345 vector = cy_inb(iobase, CY8_SVCACKT, cy_align); 1346 1347 com = com_addr(baseu 1348 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1349 & CD1400_xIVR_CHAN)); 1350#endif 1351 1352 if (com->etc != ETC_NONE) { 1353 if (com->intr_enable & CD1400_SRER_TXRDY) { 1354 /* 1355 * Here due to sloppy SRER_TXRDY 1356 * enabling. Ignore. Come back when 1357 * tx is empty. 1358 */ 1359 cd_outb(iobase, CD1400_SRER, cy_align, 1360 com->intr_enable 1361 = (com->intr_enable 1362 & ~CD1400_SRER_TXRDY) 1363 | CD1400_SRER_TXMPTY); 1364 goto terminate_tx_service; 1365 } 1366 switch (com->etc) { 1367 case CD1400_ETC_SENDBREAK: 1368 case CD1400_ETC_STOPBREAK: 1369 /* 1370 * Start the command. Come back on 1371 * next tx empty interrupt, hopefully 1372 * after command has been executed. 1373 */ 1374 cd_outb(iobase, CD1400_COR2, cy_align, 1375 com->cor[1] |= CD1400_COR2_ETC); 1376 cd_outb(iobase, CD1400_TDR, cy_align, 1377 CD1400_ETC_CMD); 1378 cd_outb(iobase, CD1400_TDR, cy_align, 1379 com->etc); 1380 if (com->etc == CD1400_ETC_SENDBREAK) 1381 com->etc = ETC_BREAK_STARTING; 1382 else 1383 com->etc = ETC_BREAK_ENDING; 1384 goto terminate_tx_service; 1385 case ETC_BREAK_STARTING: 1386 /* 1387 * BREAK is now on. Continue with 1388 * SRER_TXMPTY processing, hopefully 1389 * don't come back. 1390 */ 1391 com->etc = ETC_BREAK_STARTED; 1392 break; 1393 case ETC_BREAK_STARTED: 1394 /* 1395 * Came back due to sloppy SRER_TXMPTY 1396 * enabling. Hope again. 1397 */ 1398 break; 1399 case ETC_BREAK_ENDING: 1400 /* 1401 * BREAK is now off. Continue with 1402 * SRER_TXMPTY processing and don't 1403 * come back. The SWI handler will 1404 * restart tx interrupts if necessary. 1405 */ 1406 cd_outb(iobase, CD1400_COR2, cy_align, 1407 com->cor[1] 1408 &= ~CD1400_COR2_ETC); 1409 com->etc = ETC_BREAK_ENDED; 1410 if (!(com->state & CS_ODONE)) { 1411 com_events += LOTS_OF_EVENTS; 1412 com->state |= CS_ODONE; 1413 setsofttty(); 1414 } 1415 break; 1416 case ETC_BREAK_ENDED: 1417 /* 1418 * Shouldn't get here. Hope again. 1419 */ 1420 break; 1421 } 1422 } 1423 if (com->intr_enable & CD1400_SRER_TXMPTY) { 1424 if (!(com->extra_state & CSE_ODONE)) { 1425 com_events += LOTS_OF_EVENTS; 1426 com->extra_state |= CSE_ODONE; 1427 setsofttty(); 1428 } 1429 cd_outb(iobase, CD1400_SRER, cy_align, 1430 com->intr_enable 1431 &= ~CD1400_SRER_TXMPTY); 1432 goto terminate_tx_service; 1433 } 1434 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1435 u_char *ioptr; 1436 u_int ocount; 1437 1438 ioptr = com->obufq.l_head; 1439 ocount = com->obufq.l_tail - ioptr; 1440 if (ocount > CD1400_TX_FIFO_SIZE) 1441 ocount = CD1400_TX_FIFO_SIZE; 1442 com->bytes_out += ocount; 1443 do 1444 cd_outb(iobase, CD1400_TDR, cy_align, 1445 *ioptr++); 1446 while (--ocount != 0); 1447 com->obufq.l_head = ioptr; 1448 if (ioptr >= com->obufq.l_tail) { 1449 struct lbq *qp; 1450 1451 qp = com->obufq.l_next; 1452 qp->l_queued = FALSE; 1453 qp = qp->l_next; 1454 if (qp != NULL) { 1455 com->obufq.l_head = qp->l_head; 1456 com->obufq.l_tail = qp->l_tail; 1457 com->obufq.l_next = qp; 1458 } else { 1459 /* output just completed */ 1460 com->state &= ~CS_BUSY; 1461 1462 /* 1463 * The setting of CSE_ODONE may be 1464 * stale here. We currently only 1465 * use it when CS_BUSY is set, and 1466 * fixing it when we clear CS_BUSY 1467 * is easiest. 1468 */ 1469 if (com->extra_state & CSE_ODONE) { 1470 com_events -= LOTS_OF_EVENTS; 1471 com->extra_state &= ~CSE_ODONE; 1472 } 1473 1474 cd_outb(iobase, CD1400_SRER, cy_align, 1475 com->intr_enable 1476 = (com->intr_enable 1477 & ~CD1400_SRER_TXRDY) 1478 | CD1400_SRER_TXMPTY); 1479 } 1480 if (!(com->state & CS_ODONE)) { 1481 com_events += LOTS_OF_EVENTS; 1482 com->state |= CS_ODONE; 1483 1484 /* handle at high level ASAP */ 1485 setsofttty(); 1486 } 1487 } 1488 } 1489 1490 /* terminate service context */ 1491terminate_tx_service: 1492#ifdef PollMode 1493 cd_outb(iobase, CD1400_TIR, cy_align, 1494 save_tir 1495 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); 1496#else 1497 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1498#endif 1499 } 1500 } 1501 1502 /* ensure an edge for the next interrupt */ 1503 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 1504 1505 schedsofttty(); 1506 1507 COM_UNLOCK(); 1508} 1509 1510#if 0 1511static void 1512siointr1(com) 1513 struct com_s *com; 1514{ 1515} 1516#endif 1517 1518static int 1519sioioctl(dev, cmd, data, flag, p) 1520 dev_t dev; 1521 u_long cmd; 1522 caddr_t data; 1523 int flag; 1524 struct proc *p; 1525{ 1526 struct com_s *com; 1527 int error; 1528 int mynor; 1529 int s; 1530 struct tty *tp; 1531#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1532 int oldcmd; 1533 struct termios term; 1534#endif 1535 1536 mynor = minor(dev); 1537 com = com_addr(MINOR_TO_UNIT(mynor)); 1538 if (mynor & CONTROL_MASK) { 1539 struct termios *ct; 1540 1541 switch (mynor & CONTROL_MASK) { 1542 case CONTROL_INIT_STATE: 1543 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 1544 break; 1545 case CONTROL_LOCK_STATE: 1546 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 1547 break; 1548 default: 1549 return (ENODEV); /* /dev/nodev */ 1550 } 1551 switch (cmd) { 1552 case TIOCSETA: 1553 error = suser(p->p_ucred, &p->p_acflag); 1554 if (error != 0) 1555 return (error); 1556 *ct = *(struct termios *)data; 1557 return (0); 1558 case TIOCGETA: 1559 *(struct termios *)data = *ct; 1560 return (0); 1561 case TIOCGETD: 1562 *(int *)data = TTYDISC; 1563 return (0); 1564 case TIOCGWINSZ: 1565 bzero(data, sizeof(struct winsize)); 1566 return (0); 1567 default: 1568 return (ENOTTY); 1569 } 1570 } 1571 tp = com->tp; 1572#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1573 term = tp->t_termios; 1574 oldcmd = cmd; 1575 error = ttsetcompat(tp, &cmd, data, &term); 1576 if (error != 0) 1577 return (error); 1578 if (cmd != oldcmd) 1579 data = (caddr_t)&term; 1580#endif 1581 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1582 int cc; 1583 struct termios *dt = (struct termios *)data; 1584 struct termios *lt = mynor & CALLOUT_MASK 1585 ? &com->lt_out : &com->lt_in; 1586 1587 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1588 | (dt->c_iflag & ~lt->c_iflag); 1589 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1590 | (dt->c_oflag & ~lt->c_oflag); 1591 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1592 | (dt->c_cflag & ~lt->c_cflag); 1593 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1594 | (dt->c_lflag & ~lt->c_lflag); 1595 for (cc = 0; cc < NCCS; ++cc) 1596 if (lt->c_cc[cc] != 0) 1597 dt->c_cc[cc] = tp->t_cc[cc]; 1598 if (lt->c_ispeed != 0) 1599 dt->c_ispeed = tp->t_ispeed; 1600 if (lt->c_ospeed != 0) 1601 dt->c_ospeed = tp->t_ospeed; 1602 } 1603 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1604 if (error != ENOIOCTL) 1605 return (error); 1606 s = spltty(); 1607 error = ttioctl(tp, cmd, data, flag); 1608 disc_optim(tp, &tp->t_termios, com); 1609 if (error != ENOIOCTL) { 1610 splx(s); 1611 return (error); 1612 } 1613 switch (cmd) { 1614 case TIOCSBRK: 1615#if 0 1616 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 1617#else 1618 cd_etc(com, CD1400_ETC_SENDBREAK); 1619#endif 1620 break; 1621 case TIOCCBRK: 1622#if 0 1623 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1624#else 1625 cd_etc(com, CD1400_ETC_STOPBREAK); 1626#endif 1627 break; 1628 case TIOCSDTR: 1629 (void)commctl(com, TIOCM_DTR, DMBIS); 1630 break; 1631 case TIOCCDTR: 1632 (void)commctl(com, TIOCM_DTR, DMBIC); 1633 break; 1634 /* 1635 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 1636 * changes get undone on the next call to comparam(). 1637 */ 1638 case TIOCMSET: 1639 (void)commctl(com, *(int *)data, DMSET); 1640 break; 1641 case TIOCMBIS: 1642 (void)commctl(com, *(int *)data, DMBIS); 1643 break; 1644 case TIOCMBIC: 1645 (void)commctl(com, *(int *)data, DMBIC); 1646 break; 1647 case TIOCMGET: 1648 *(int *)data = commctl(com, 0, DMGET); 1649 break; 1650 case TIOCMSDTRWAIT: 1651 /* must be root since the wait applies to following logins */ 1652 error = suser(p->p_ucred, &p->p_acflag); 1653 if (error != 0) { 1654 splx(s); 1655 return (error); 1656 } 1657 com->dtr_wait = *(int *)data * hz / 100; 1658 break; 1659 case TIOCMGDTRWAIT: 1660 *(int *)data = com->dtr_wait * 100 / hz; 1661 break; 1662 case TIOCTIMESTAMP: 1663 com->do_timestamp = TRUE; 1664 *(struct timeval *)data = com->timestamp; 1665 break; 1666 case TIOCDCDTIMESTAMP: 1667 com->do_dcd_timestamp = TRUE; 1668 *(struct timeval *)data = com->dcd_timestamp; 1669 break; 1670 default: 1671 splx(s); 1672 return (ENOTTY); 1673 } 1674 splx(s); 1675 return (0); 1676} 1677 1678static void 1679siopoll() 1680{ 1681 int unit; 1682 1683#ifdef CyDebug 1684 ++cy_timeouts; 1685#endif 1686 if (com_events == 0) 1687 return; 1688repeat: 1689 for (unit = 0; unit < NSIO; ++unit) { 1690 u_char *buf; 1691 struct com_s *com; 1692 u_char *ibuf; 1693 int incc; 1694 struct tty *tp; 1695 1696 com = com_addr(unit); 1697 if (com == NULL) 1698 continue; 1699 tp = com->tp; 1700 if (tp == NULL) { 1701 /* 1702 * XXX forget any events related to closed devices 1703 * (actually never opened devices) so that we don't 1704 * loop. 1705 */ 1706 disable_intr(); 1707 incc = com->iptr - com->ibuf; 1708 com->iptr = com->ibuf; 1709 if (com->state & CS_CHECKMSR) { 1710 incc += LOTS_OF_EVENTS; 1711 com->state &= ~CS_CHECKMSR; 1712 } 1713 com_events -= incc; 1714 enable_intr(); 1715 if (incc != 0) 1716 log(LOG_DEBUG, 1717 "sio%d: %d events for device with no tp\n", 1718 unit, incc); 1719 continue; 1720 } 1721 1722 /* switch the role of the low-level input buffers */ 1723 if (com->iptr == (ibuf = com->ibuf)) { 1724 buf = NULL; /* not used, but compiler can't tell */ 1725 incc = 0; 1726 } else { 1727 buf = ibuf; 1728 disable_intr(); 1729 incc = com->iptr - buf; 1730 com_events -= incc; 1731 if (ibuf == com->ibuf1) 1732 ibuf = com->ibuf2; 1733 else 1734 ibuf = com->ibuf1; 1735 com->ibufend = ibuf + RS_IBUFSIZE; 1736 com->ihighwater = ibuf + RS_IHIGHWATER; 1737 com->iptr = ibuf; 1738 1739 /* 1740 * There is now room for another low-level buffer full 1741 * of input, so enable RTS if it is now disabled and 1742 * there is room in the high-level buffer. 1743 */ 1744 if ((com->state & CS_RTS_IFLOW) 1745 && !(com->mcr_image & com->mcr_rts) 1746 && !(tp->t_state & TS_TBLOCK)) 1747#if 0 1748 outb(com->modem_ctl_port, 1749 com->mcr_image |= MCR_RTS); 1750#else 1751 cd_setreg(com, com->mcr_rts_reg, 1752 com->mcr_image |= com->mcr_rts); 1753#endif 1754 enable_intr(); 1755 com->ibuf = ibuf; 1756 } 1757 1758 if (com->state & CS_CHECKMSR) { 1759 u_char delta_modem_status; 1760 1761 disable_intr(); 1762 delta_modem_status = com->last_modem_status 1763 ^ com->prev_modem_status; 1764 com->prev_modem_status = com->last_modem_status; 1765 com_events -= LOTS_OF_EVENTS; 1766 com->state &= ~CS_CHECKMSR; 1767 enable_intr(); 1768 if (delta_modem_status & MSR_DCD) 1769 (*linesw[tp->t_line].l_modem) 1770 (tp, com->prev_modem_status & MSR_DCD); 1771 } 1772 if (com->extra_state & CSE_ODONE) { 1773 disable_intr(); 1774 com_events -= LOTS_OF_EVENTS; 1775 com->extra_state &= ~CSE_ODONE; 1776 enable_intr(); 1777 if (!(com->state & CS_BUSY)) { 1778 tp->t_state &= ~TS_BUSY; 1779 ttwwakeup(com->tp); 1780 } 1781 if (com->etc != ETC_NONE) { 1782 if (com->etc == ETC_BREAK_ENDED) 1783 com->etc = ETC_NONE; 1784 wakeup(&com->etc); 1785 } 1786 } 1787 if (com->state & CS_ODONE) { 1788 disable_intr(); 1789 com_events -= LOTS_OF_EVENTS; 1790 com->state &= ~CS_ODONE; 1791 enable_intr(); 1792 (*linesw[tp->t_line].l_start)(tp); 1793 } 1794 if (incc <= 0 || !(tp->t_state & TS_ISOPEN)) 1795 continue; 1796 /* 1797 * Avoid the grotesquely inefficient lineswitch routine 1798 * (ttyinput) in "raw" mode. It usually takes about 450 1799 * instructions (that's without canonical processing or echo!). 1800 * slinput is reasonably fast (usually 40 instructions plus 1801 * call overhead). 1802 */ 1803 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 1804 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 1805 && (com->state & CS_RTS_IFLOW 1806 || tp->t_iflag & IXOFF) 1807 && !(tp->t_state & TS_TBLOCK)) 1808 ttyblock(tp); 1809 tk_nin += incc; 1810 tk_rawcc += incc; 1811 tp->t_rawcc += incc; 1812 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 1813 += b_to_q((char *)buf, incc, &tp->t_rawq); 1814 ttwakeup(tp); 1815 if (tp->t_state & TS_TTSTOP 1816 && (tp->t_iflag & IXANY 1817 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 1818 tp->t_state &= ~TS_TTSTOP; 1819 tp->t_lflag &= ~FLUSHO; 1820 comstart(tp); 1821 } 1822 } else { 1823 do { 1824 u_char line_status; 1825 int recv_data; 1826 1827 line_status = (u_char) buf[CE_INPUT_OFFSET]; 1828 recv_data = (u_char) *buf++; 1829 if (line_status 1830 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 1831 if (line_status & LSR_BI) 1832 recv_data |= TTY_BI; 1833 if (line_status & LSR_FE) 1834 recv_data |= TTY_FE; 1835 if (line_status & LSR_OE) 1836 recv_data |= TTY_OE; 1837 if (line_status & LSR_PE) 1838 recv_data |= TTY_PE; 1839 } 1840 (*linesw[tp->t_line].l_rint)(recv_data, tp); 1841 } while (--incc > 0); 1842 } 1843 if (com_events == 0) 1844 break; 1845 } 1846 if (com_events >= LOTS_OF_EVENTS) 1847 goto repeat; 1848} 1849 1850static int 1851comparam(tp, t) 1852 struct tty *tp; 1853 struct termios *t; 1854{ 1855 int bits; 1856 int cflag; 1857 struct com_s *com; 1858 u_char cor_change; 1859 u_long cy_clock; 1860 int idivisor; 1861 int iflag; 1862 int iprescaler; 1863 int itimeout; 1864 int odivisor; 1865 int oprescaler; 1866 u_char opt; 1867 int s; 1868 int unit; 1869 1870 /* do historical conversions */ 1871 if (t->c_ispeed == 0) 1872 t->c_ispeed = t->c_ospeed; 1873 1874 unit = DEV_TO_UNIT(tp->t_dev); 1875 com = com_addr(unit); 1876 1877 /* check requested parameters */ 1878 cy_clock = CY_CLOCK(com->gfrcr_image); 1879 idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler); 1880 if (idivisor < 0) 1881 return (EINVAL); 1882 odivisor = comspeed(t->c_ospeed, cy_clock, &oprescaler); 1883 if (odivisor < 0) 1884 return (EINVAL); 1885 1886 /* parameters are OK, convert them to the com struct and the device */ 1887 s = spltty(); 1888 if (odivisor == 0) 1889 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 1890 else 1891 (void)commctl(com, TIOCM_DTR, DMBIS); 1892 1893 if (idivisor != 0) { 1894 cd_setreg(com, CD1400_RBPR, idivisor); 1895 cd_setreg(com, CD1400_RCOR, iprescaler); 1896 } 1897 if (odivisor != 0) { 1898 cd_setreg(com, CD1400_TBPR, odivisor); 1899 cd_setreg(com, CD1400_TCOR, oprescaler); 1900 } 1901 1902 /* 1903 * channel control 1904 * receiver enable 1905 * transmitter enable (always set) 1906 */ 1907 cflag = t->c_cflag; 1908 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 1909 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 1910 if (opt != com->channel_control) { 1911 com->channel_control = opt; 1912 cd1400_channel_cmd(com, opt); 1913 } 1914 1915#ifdef Smarts 1916 /* set special chars */ 1917 /* XXX if one is _POSIX_VDISABLE, can't use some others */ 1918 if (t->c_cc[VSTOP] != _POSIX_VDISABLE) 1919 cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); 1920 if (t->c_cc[VSTART] != _POSIX_VDISABLE) 1921 cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); 1922 if (t->c_cc[VINTR] != _POSIX_VDISABLE) 1923 cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); 1924 if (t->c_cc[VSUSP] != _POSIX_VDISABLE) 1925 cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); 1926#endif 1927 1928 /* 1929 * set channel option register 1 - 1930 * parity mode 1931 * stop bits 1932 * char length 1933 */ 1934 opt = 0; 1935 /* parity */ 1936 if (cflag & PARENB) { 1937 if (cflag & PARODD) 1938 opt |= CD1400_COR1_PARODD; 1939 opt |= CD1400_COR1_PARNORMAL; 1940 } 1941 iflag = t->c_iflag; 1942 if (!(iflag & INPCK)) 1943 opt |= CD1400_COR1_NOINPCK; 1944 bits = 1 + 1; 1945 /* stop bits */ 1946 if (cflag & CSTOPB) { 1947 ++bits; 1948 opt |= CD1400_COR1_STOP2; 1949 } 1950 /* char length */ 1951 switch (cflag & CSIZE) { 1952 case CS5: 1953 bits += 5; 1954 opt |= CD1400_COR1_CS5; 1955 break; 1956 case CS6: 1957 bits += 6; 1958 opt |= CD1400_COR1_CS6; 1959 break; 1960 case CS7: 1961 bits += 7; 1962 opt |= CD1400_COR1_CS7; 1963 break; 1964 default: 1965 bits += 8; 1966 opt |= CD1400_COR1_CS8; 1967 break; 1968 } 1969 cor_change = 0; 1970 if (opt != com->cor[0]) { 1971 cor_change |= CD1400_CCR_COR1; 1972 cd_setreg(com, CD1400_COR1, com->cor[0] = opt); 1973 } 1974 1975 /* 1976 * Set receive time-out period, normally to max(one char time, 5 ms). 1977 */ 1978 if (t->c_ispeed == 0) 1979 itimeout = cd_getreg(com, CD1400_RTPR); 1980 else { 1981 itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; 1982#ifdef SOFT_HOTCHAR 1983#define MIN_RTP 1 1984#else 1985#define MIN_RTP 5 1986#endif 1987 if (itimeout < MIN_RTP) 1988 itimeout = MIN_RTP; 1989 } 1990 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 1991 && t->c_cc[VTIME] * 10 > itimeout) 1992 itimeout = t->c_cc[VTIME] * 10; 1993 if (itimeout > 255) 1994 itimeout = 255; 1995 cd_setreg(com, CD1400_RTPR, itimeout); 1996 1997 /* 1998 * set channel option register 2 - 1999 * flow control 2000 */ 2001 opt = 0; 2002#ifdef Smarts 2003 if (iflag & IXANY) 2004 opt |= CD1400_COR2_IXANY; 2005 if (iflag & IXOFF) 2006 opt |= CD1400_COR2_IXOFF; 2007#endif 2008#ifndef SOFT_CTS_OFLOW 2009 if (cflag & CCTS_OFLOW) 2010 opt |= CD1400_COR2_CCTS_OFLOW; 2011#endif 2012 disable_intr(); 2013 if (opt != com->cor[1]) { 2014 cor_change |= CD1400_CCR_COR2; 2015 cd_setreg(com, CD1400_COR2, com->cor[1] = opt); 2016 } 2017 enable_intr(); 2018 2019 /* 2020 * set channel option register 3 - 2021 * receiver FIFO interrupt threshold 2022 * flow control 2023 */ 2024 opt = RxFifoThreshold; 2025#ifdef Smarts 2026 if (t->c_lflag & ICANON) 2027 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 2028 if (iflag & IXOFF) 2029 /* detect and transparently handle START and STOP chars */ 2030 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 2031#endif 2032 if (opt != com->cor[2]) { 2033 cor_change |= CD1400_CCR_COR3; 2034 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2035 } 2036 2037 /* notify the CD1400 if COR1-3 have changed */ 2038 if (cor_change) 2039 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); 2040 2041 /* 2042 * set channel option register 4 - 2043 * CR/NL processing 2044 * break processing 2045 * received exception processing 2046 */ 2047 opt = 0; 2048 if (iflag & IGNCR) 2049 opt |= CD1400_COR4_IGNCR; 2050#ifdef Smarts 2051 /* 2052 * we need a new ttyinput() for this, as we don't want to 2053 * have ICRNL && INLCR being done in both layers, or to have 2054 * synchronisation problems 2055 */ 2056 if (iflag & ICRNL) 2057 opt |= CD1400_COR4_ICRNL; 2058 if (iflag & INLCR) 2059 opt |= CD1400_COR4_INLCR; 2060#endif 2061 if (iflag & IGNBRK) 2062 opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; 2063 /* 2064 * The `-ignbrk -brkint parmrk' case is not handled by the hardware, 2065 * so only tell the hardware about -brkint if -parmrk. 2066 */ 2067 if (!(iflag & (BRKINT | PARMRK))) 2068 opt |= CD1400_COR4_NOBRKINT; 2069#if 0 2070 /* XXX using this "intelligence" breaks reporting of overruns. */ 2071 if (iflag & IGNPAR) 2072 opt |= CD1400_COR4_PFO_DISCARD; 2073 else { 2074 if (iflag & PARMRK) 2075 opt |= CD1400_COR4_PFO_ESC; 2076 else 2077 opt |= CD1400_COR4_PFO_NUL; 2078 } 2079#else 2080 opt |= CD1400_COR4_PFO_EXCEPTION; 2081#endif 2082 cd_setreg(com, CD1400_COR4, opt); 2083 2084 /* 2085 * set channel option register 5 - 2086 */ 2087 opt = 0; 2088 if (iflag & ISTRIP) 2089 opt |= CD1400_COR5_ISTRIP; 2090 if (t->c_iflag & IEXTEN) 2091 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 2092 opt |= CD1400_COR5_LNEXT; 2093#ifdef Smarts 2094 if (t->c_oflag & ONLCR) 2095 opt |= CD1400_COR5_ONLCR; 2096 if (t->c_oflag & OCRNL) 2097 opt |= CD1400_COR5_OCRNL; 2098#endif 2099 cd_setreg(com, CD1400_COR5, opt); 2100 2101 /* 2102 * We always generate modem status change interrupts for CD changes. 2103 * Among other things, this is necessary to track TS_CARR_ON for 2104 * pstat to print even when the driver doesn't care. CD changes 2105 * should be rare so interrupts for them are not worth extra code to 2106 * avoid. We avoid interrupts for other modem status changes (except 2107 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is 2108 * simplest and best. 2109 */ 2110 2111 /* 2112 * set modem change option register 1 2113 * generate modem interrupts on which 1 -> 0 input transitions 2114 * also controls auto-DTR output flow-control, which we don't use 2115 */ 2116 opt = CD1400_MCOR1_CDzd; 2117#ifdef SOFT_CTS_OFLOW 2118 if (cflag & CCTS_OFLOW) 2119 opt |= CD1400_MCOR1_CTSzd; 2120#endif 2121 cd_setreg(com, CD1400_MCOR1, opt); 2122 2123 /* 2124 * set modem change option register 2 2125 * generate modem interrupts on specific 0 -> 1 input transitions 2126 */ 2127 opt = CD1400_MCOR2_CDod; 2128#ifdef SOFT_CTS_OFLOW 2129 if (cflag & CCTS_OFLOW) 2130 opt |= CD1400_MCOR2_CTSod; 2131#endif 2132 cd_setreg(com, CD1400_MCOR2, opt); 2133 2134 /* 2135 * XXX should have done this long ago, but there is too much state 2136 * to change all atomically. 2137 */ 2138 disable_intr(); 2139 2140 com->state &= ~CS_TTGO; 2141 if (!(tp->t_state & TS_TTSTOP)) 2142 com->state |= CS_TTGO; 2143 if (cflag & CRTS_IFLOW) { 2144 com->state |= CS_RTS_IFLOW; 2145 /* 2146 * If CS_RTS_IFLOW just changed from off to on, the change 2147 * needs to be propagated to MCR_RTS. This isn't urgent, 2148 * so do it later by calling comstart() instead of repeating 2149 * a lot of code from comstart() here. 2150 */ 2151 } else if (com->state & CS_RTS_IFLOW) { 2152 com->state &= ~CS_RTS_IFLOW; 2153 /* 2154 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2155 * on here, since comstart() won't do it later. 2156 */ 2157#if 0 2158 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2159#else 2160 cd_setreg(com, com->mcr_rts_reg, 2161 com->mcr_image |= com->mcr_rts); 2162#endif 2163 } 2164 2165 /* 2166 * Set up state to handle output flow control. 2167 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2168 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2169 */ 2170 com->state |= CS_ODEVREADY; 2171#ifdef SOFT_CTS_OFLOW 2172 com->state &= ~CS_CTS_OFLOW; 2173 if (cflag & CCTS_OFLOW) { 2174 com->state |= CS_CTS_OFLOW; 2175 if (!(com->last_modem_status & MSR_CTS)) 2176 com->state &= ~CS_ODEVREADY; 2177 } 2178#endif 2179 /* XXX shouldn't call functions while intrs are disabled. */ 2180 disc_optim(tp, t, com); 2181#if 0 2182 /* 2183 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2184 * unconditionally, but that defeated the careful discarding of 2185 * stale input in sioopen(). 2186 */ 2187 if (com->state >= (CS_BUSY | CS_TTGO)) 2188 siointr1(com); 2189#endif 2190 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2191 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 2192 cd_setreg(com, CD1400_SRER, 2193 com->intr_enable 2194 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2195 | CD1400_SRER_TXRDY); 2196 } else { 2197 if (com->intr_enable & CD1400_SRER_TXRDY) 2198 cd_setreg(com, CD1400_SRER, 2199 com->intr_enable 2200 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2201 | CD1400_SRER_TXMPTY); 2202 } 2203 2204 enable_intr(); 2205 splx(s); 2206 comstart(tp); 2207 return (0); 2208} 2209 2210static void 2211comstart(tp) 2212 struct tty *tp; 2213{ 2214 struct com_s *com; 2215 int s; 2216#ifdef CyDebug 2217 bool_t started; 2218#endif 2219 int unit; 2220 2221 unit = DEV_TO_UNIT(tp->t_dev); 2222 com = com_addr(unit); 2223 s = spltty(); 2224 2225#ifdef CyDebug 2226 ++com->start_count; 2227 started = FALSE; 2228#endif 2229 2230 disable_intr(); 2231 if (tp->t_state & TS_TTSTOP) { 2232 com->state &= ~CS_TTGO; 2233 if (com->intr_enable & CD1400_SRER_TXRDY) 2234 cd_setreg(com, CD1400_SRER, 2235 com->intr_enable 2236 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2237 | CD1400_SRER_TXMPTY); 2238 } else { 2239 com->state |= CS_TTGO; 2240 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2241 && !(com->intr_enable & CD1400_SRER_TXRDY)) 2242 cd_setreg(com, CD1400_SRER, 2243 com->intr_enable 2244 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2245 | CD1400_SRER_TXRDY); 2246 } 2247 if (tp->t_state & TS_TBLOCK) { 2248 if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) 2249#if 0 2250 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2251#else 2252 cd_setreg(com, com->mcr_rts_reg, 2253 com->mcr_image &= ~com->mcr_rts); 2254#endif 2255 } else { 2256 if (!(com->mcr_image & com->mcr_rts) 2257 && com->iptr < com->ihighwater 2258 && com->state & CS_RTS_IFLOW) 2259#if 0 2260 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2261#else 2262 cd_setreg(com, com->mcr_rts_reg, 2263 com->mcr_image |= com->mcr_rts); 2264#endif 2265 } 2266 enable_intr(); 2267 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2268 ttwwakeup(tp); 2269 splx(s); 2270 return; 2271 } 2272 if (tp->t_outq.c_cc != 0) { 2273 struct lbq *qp; 2274 struct lbq *next; 2275 2276 if (!com->obufs[0].l_queued) { 2277#ifdef CyDebug 2278 started = TRUE; 2279#endif 2280 com->obufs[0].l_tail 2281 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2282 sizeof com->obuf1); 2283 com->obufs[0].l_next = NULL; 2284 com->obufs[0].l_queued = TRUE; 2285 disable_intr(); 2286 if (com->state & CS_BUSY) { 2287 qp = com->obufq.l_next; 2288 while ((next = qp->l_next) != NULL) 2289 qp = next; 2290 qp->l_next = &com->obufs[0]; 2291 } else { 2292 com->obufq.l_head = com->obufs[0].l_head; 2293 com->obufq.l_tail = com->obufs[0].l_tail; 2294 com->obufq.l_next = &com->obufs[0]; 2295 com->state |= CS_BUSY; 2296 if (com->state >= (CS_BUSY | CS_TTGO 2297 | CS_ODEVREADY)) 2298 cd_setreg(com, CD1400_SRER, 2299 com->intr_enable 2300 = (com->intr_enable 2301 & ~CD1400_SRER_TXMPTY) 2302 | CD1400_SRER_TXRDY); 2303 } 2304 enable_intr(); 2305 } 2306 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2307#ifdef CyDebug 2308 started = TRUE; 2309#endif 2310 com->obufs[1].l_tail 2311 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2312 sizeof com->obuf2); 2313 com->obufs[1].l_next = NULL; 2314 com->obufs[1].l_queued = TRUE; 2315 disable_intr(); 2316 if (com->state & CS_BUSY) { 2317 qp = com->obufq.l_next; 2318 while ((next = qp->l_next) != NULL) 2319 qp = next; 2320 qp->l_next = &com->obufs[1]; 2321 } else { 2322 com->obufq.l_head = com->obufs[1].l_head; 2323 com->obufq.l_tail = com->obufs[1].l_tail; 2324 com->obufq.l_next = &com->obufs[1]; 2325 com->state |= CS_BUSY; 2326 if (com->state >= (CS_BUSY | CS_TTGO 2327 | CS_ODEVREADY)) 2328 cd_setreg(com, CD1400_SRER, 2329 com->intr_enable 2330 = (com->intr_enable 2331 & ~CD1400_SRER_TXMPTY) 2332 | CD1400_SRER_TXRDY); 2333 } 2334 enable_intr(); 2335 } 2336 tp->t_state |= TS_BUSY; 2337 } 2338#ifdef CyDebug 2339 if (started) 2340 ++com->start_real; 2341#endif 2342#if 0 2343 disable_intr(); 2344 if (com->state >= (CS_BUSY | CS_TTGO)) 2345 siointr1(com); /* fake interrupt to start output */ 2346 enable_intr(); 2347#endif 2348 ttwwakeup(tp); 2349 splx(s); 2350} 2351 2352static void 2353siostop(tp, rw) 2354 struct tty *tp; 2355 int rw; 2356{ 2357 struct com_s *com; 2358 bool_t wakeup_etc; 2359 2360 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2361 wakeup_etc = FALSE; 2362 disable_intr(); 2363 if (rw & FWRITE) { 2364 com->obufs[0].l_queued = FALSE; 2365 com->obufs[1].l_queued = FALSE; 2366 if (com->extra_state & CSE_ODONE) { 2367 com_events -= LOTS_OF_EVENTS; 2368 com->extra_state &= ~CSE_ODONE; 2369 if (com->etc != ETC_NONE) { 2370 if (com->etc == ETC_BREAK_ENDED) 2371 com->etc = ETC_NONE; 2372 wakeup_etc = TRUE; 2373 } 2374 } 2375 com->tp->t_state &= ~TS_BUSY; 2376 if (com->state & CS_ODONE) 2377 com_events -= LOTS_OF_EVENTS; 2378 com->state &= ~(CS_ODONE | CS_BUSY); 2379 } 2380 if (rw & FREAD) { 2381 /* XXX no way to reset only input fifo. */ 2382 com_events -= (com->iptr - com->ibuf); 2383 com->iptr = com->ibuf; 2384 } 2385 enable_intr(); 2386 if (wakeup_etc) 2387 wakeup(&com->etc); 2388 if (rw & FWRITE && com->etc == ETC_NONE) 2389 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 2390 comstart(tp); 2391} 2392 2393static struct tty * 2394siodevtotty(dev) 2395 dev_t dev; 2396{ 2397 int mynor; 2398 int unit; 2399 2400 mynor = minor(dev); 2401 if (mynor & CONTROL_MASK) 2402 return (NULL); 2403 unit = MINOR_TO_UNIT(mynor); 2404 if ((u_int) unit >= NSIO) 2405 return (NULL); 2406 return (&sio_tty[unit]); 2407} 2408 2409static int 2410commctl(com, bits, how) 2411 struct com_s *com; 2412 int bits; 2413 int how; 2414{ 2415 int mcr; 2416 int msr; 2417 2418 if (how == DMGET) { 2419 if (com->channel_control & CD1400_CCR_RCVEN) 2420 bits |= TIOCM_LE; 2421 mcr = com->mcr_image; 2422 if (mcr & com->mcr_dtr) 2423 bits |= TIOCM_DTR; 2424 if (mcr & com->mcr_rts) 2425 /* XXX wired on for Cyclom-8Ys */ 2426 bits |= TIOCM_RTS; 2427 2428 /* 2429 * We must read the modem status from the hardware because 2430 * we don't generate modem status change interrupts for all 2431 * changes, so com->prev_modem_status is not guaranteed to 2432 * be up to date. This is safe, unlike for sio, because 2433 * reading the status register doesn't clear pending modem 2434 * status change interrupts. 2435 */ 2436 msr = cd_getreg(com, CD1400_MSVR2); 2437 2438 if (msr & MSR_CTS) 2439 bits |= TIOCM_CTS; 2440 if (msr & MSR_DCD) 2441 bits |= TIOCM_CD; 2442 if (msr & MSR_DSR) 2443 bits |= TIOCM_DSR; 2444 if (msr & MSR_RI) 2445 /* XXX not connected except for Cyclom-16Y? */ 2446 bits |= TIOCM_RI; 2447 return (bits); 2448 } 2449 mcr = 0; 2450 if (bits & TIOCM_DTR) 2451 mcr |= com->mcr_dtr; 2452 if (bits & TIOCM_RTS) 2453 mcr |= com->mcr_rts; 2454 disable_intr(); 2455 switch (how) { 2456 case DMSET: 2457 com->mcr_image = mcr; 2458 cd_setreg(com, CD1400_MSVR1, mcr); 2459 cd_setreg(com, CD1400_MSVR2, mcr); 2460 break; 2461 case DMBIS: 2462 com->mcr_image = mcr = com->mcr_image | mcr; 2463 cd_setreg(com, CD1400_MSVR1, mcr); 2464 cd_setreg(com, CD1400_MSVR2, mcr); 2465 break; 2466 case DMBIC: 2467 com->mcr_image = mcr = com->mcr_image & ~mcr; 2468 cd_setreg(com, CD1400_MSVR1, mcr); 2469 cd_setreg(com, CD1400_MSVR2, mcr); 2470 break; 2471 } 2472 enable_intr(); 2473 return (0); 2474} 2475 2476static void 2477siosettimeout() 2478{ 2479 struct com_s *com; 2480 bool_t someopen; 2481 int unit; 2482 2483 /* 2484 * Set our timeout period to 1 second if no polled devices are open. 2485 * Otherwise set it to max(1/200, 1/hz). 2486 * Enable timeouts iff some device is open. 2487 */ 2488 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2489 sio_timeout = hz; 2490 someopen = FALSE; 2491 for (unit = 0; unit < NSIO; ++unit) { 2492 com = com_addr(unit); 2493 if (com != NULL && com->tp != NULL 2494 && com->tp->t_state & TS_ISOPEN) { 2495 someopen = TRUE; 2496#if 0 2497 if (com->poll || com->poll_output) { 2498 sio_timeout = hz > 200 ? hz / 200 : 1; 2499 break; 2500 } 2501#endif 2502 } 2503 } 2504 if (someopen) { 2505 sio_timeouts_until_log = hz / sio_timeout; 2506 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 2507 sio_timeout); 2508 } else { 2509 /* Flush error messages, if any. */ 2510 sio_timeouts_until_log = 1; 2511 comwakeup((void *)NULL); 2512 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2513 } 2514} 2515 2516static void 2517comwakeup(chan) 2518 void *chan; 2519{ 2520 struct com_s *com; 2521 int unit; 2522 2523 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 2524 2525#if 0 2526 /* 2527 * Recover from lost output interrupts. 2528 * Poll any lines that don't use interrupts. 2529 */ 2530 for (unit = 0; unit < NSIO; ++unit) { 2531 com = com_addr(unit); 2532 if (com != NULL 2533 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2534 disable_intr(); 2535 siointr1(com); 2536 enable_intr(); 2537 } 2538 } 2539#endif 2540 2541 /* 2542 * Check for and log errors, but not too often. 2543 */ 2544 if (--sio_timeouts_until_log > 0) 2545 return; 2546 sio_timeouts_until_log = hz / sio_timeout; 2547 for (unit = 0; unit < NSIO; ++unit) { 2548 int errnum; 2549 2550 com = com_addr(unit); 2551 if (com == NULL) 2552 continue; 2553 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2554 u_int delta; 2555 u_long total; 2556 2557 disable_intr(); 2558 delta = com->delta_error_counts[errnum]; 2559 com->delta_error_counts[errnum] = 0; 2560 enable_intr(); 2561 if (delta == 0) 2562 continue; 2563 total = com->error_counts[errnum] += delta; 2564 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 2565 unit, delta, error_desc[errnum], 2566 delta == 1 ? "" : "s", total); 2567 } 2568 } 2569} 2570 2571static void 2572disc_optim(tp, t, com) 2573 struct tty *tp; 2574 struct termios *t; 2575 struct com_s *com; 2576{ 2577#ifndef SOFT_HOTCHAR 2578 u_char opt; 2579#endif 2580 2581 /* 2582 * XXX can skip a lot more cases if Smarts. Maybe 2583 * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we 2584 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. 2585 */ 2586 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 2587 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2588 && (!(t->c_iflag & PARMRK) 2589 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 2590 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 2591 && linesw[tp->t_line].l_rint == ttyinput) 2592 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2593 else 2594 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2595 com->hotchar = linesw[tp->t_line].l_hotchar; 2596#ifndef SOFT_HOTCHAR 2597 opt = com->cor[2] & ~CD1400_COR3_SCD34; 2598 if (com->hotchar != 0) { 2599 cd_setreg(com, CD1400_SCHR3, com->hotchar); 2600 cd_setreg(com, CD1400_SCHR4, com->hotchar); 2601 opt |= CD1400_COR3_SCD34; 2602 } 2603 if (opt != com->cor[2]) { 2604 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2605 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 2606 } 2607#endif 2608} 2609 2610#ifdef Smarts 2611/* standard line discipline input routine */ 2612int 2613cyinput(c, tp) 2614 int c; 2615 struct tty *tp; 2616{ 2617 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 2618 * bits, as they are done by the CD1400. Hardly worth the effort, 2619 * given that high-throughput sessions are raw anyhow. 2620 */ 2621} 2622#endif /* Smarts */ 2623 2624static int 2625comspeed(speed, cy_clock, prescaler_io) 2626 speed_t speed; 2627 u_long cy_clock; 2628 int *prescaler_io; 2629{ 2630 int actual; 2631 int error; 2632 int divider; 2633 int prescaler; 2634 int prescaler_unit; 2635 2636 if (speed == 0) 2637 return (0); 2638 if (speed < 0 || speed > 150000) 2639 return (-1); 2640 2641 /* determine which prescaler to use */ 2642 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2643 prescaler_unit--, prescaler >>= 2) { 2644 if (cy_clock / prescaler / speed > 63) 2645 break; 2646 } 2647 2648 divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ 2649 if (divider > 255) 2650 divider = 255; 2651 actual = cy_clock/prescaler/divider; 2652 2653 /* 10 times error in percent: */ 2654 error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; 2655 2656 /* 3.0% max error tolerance */ 2657 if (error < -30 || error > 30) 2658 return (-1); 2659 2660#if 0 2661 printf("prescaler = %d (%d)\n", prescaler, prescaler_unit); 2662 printf("divider = %d (%x)\n", divider, divider); 2663 printf("actual = %d\n", actual); 2664 printf("error = %d\n", error); 2665#endif 2666 2667 *prescaler_io = prescaler_unit; 2668 return (divider); 2669} 2670 2671static void 2672cd1400_channel_cmd(com, cmd) 2673 struct com_s *com; 2674 int cmd; 2675{ 2676 cd1400_channel_cmd_wait(com); 2677 cd_setreg(com, CD1400_CCR, cmd); 2678 cd1400_channel_cmd_wait(com); 2679} 2680 2681static void 2682cd1400_channel_cmd_wait(com) 2683 struct com_s *com; 2684{ 2685 struct timeval start; 2686 struct timeval tv; 2687 long usec; 2688 2689 if (cd_getreg(com, CD1400_CCR) == 0) 2690 return; 2691 microtime(&start); 2692 for (;;) { 2693 if (cd_getreg(com, CD1400_CCR) == 0) 2694 return; 2695 microtime(&tv); 2696 usec = 1000000 * (tv.tv_sec - start.tv_sec) + 2697 tv.tv_usec - start.tv_usec; 2698 if (usec >= 5000) { 2699 log(LOG_ERR, 2700 "cy%d: channel command timeout (%ld usec)\n", 2701 com->unit, usec); 2702 return; 2703 } 2704 } 2705} 2706 2707static void 2708cd_etc(com, etc) 2709 struct com_s *com; 2710 int etc; 2711{ 2712 /* 2713 * We can't change the hardware's ETC state while there are any 2714 * characters in the tx fifo, since those characters would be 2715 * interpreted as commands! Unputting characters from the fifo 2716 * is difficult, so we wait up to 12 character times for the fifo 2717 * to drain. The command will be delayed for up to 2 character 2718 * times for the tx to become empty. Unputting characters from 2719 * the tx holding and shift registers is impossible, so we wait 2720 * for the tx to become empty so that the command is sure to be 2721 * executed soon after we issue it. 2722 */ 2723 disable_intr(); 2724 if (com->etc == etc) { 2725 enable_intr(); 2726 goto wait; 2727 } 2728 if ((etc == CD1400_ETC_SENDBREAK 2729 && (com->etc == ETC_BREAK_STARTING 2730 || com->etc == ETC_BREAK_STARTED)) 2731 || (etc == CD1400_ETC_STOPBREAK 2732 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED 2733 || com->etc == ETC_NONE))) { 2734 enable_intr(); 2735 return; 2736 } 2737 com->etc = etc; 2738 cd_setreg(com, CD1400_SRER, 2739 com->intr_enable 2740 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); 2741 enable_intr(); 2742wait: 2743 while (com->etc == etc 2744 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) 2745 continue; 2746} 2747 2748static int 2749cd_getreg(com, reg) 2750 struct com_s *com; 2751 int reg; 2752{ 2753 struct com_s *basecom; 2754 u_char car; 2755 int cy_align; 2756 u_long ef; 2757 cy_addr iobase; 2758 int val; 2759 2760 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2761 car = com->unit & CD1400_CAR_CHAN; 2762 cy_align = com->cy_align; 2763 iobase = com->iobase; 2764 ef = read_eflags(); 2765 disable_intr(); 2766 if (basecom->car != car) 2767 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2768 val = cd_inb(iobase, reg, cy_align); 2769 write_eflags(ef); 2770 return (val); 2771} 2772 2773static void 2774cd_setreg(com, reg, val) 2775 struct com_s *com; 2776 int reg; 2777 int val; 2778{ 2779 struct com_s *basecom; 2780 u_char car; 2781 int cy_align; 2782 u_long ef; 2783 cy_addr iobase; 2784 2785 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2786 car = com->unit & CD1400_CAR_CHAN; 2787 cy_align = com->cy_align; 2788 iobase = com->iobase; 2789 ef = read_eflags(); 2790 disable_intr(); 2791 if (basecom->car != car) 2792 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2793 cd_outb(iobase, reg, cy_align, val); 2794 write_eflags(ef); 2795} 2796 2797#ifdef CyDebug 2798/* useful in ddb */ 2799void 2800cystatus(unit) 2801 int unit; 2802{ 2803 struct com_s *com; 2804 cy_addr iobase; 2805 u_int ocount; 2806 struct tty *tp; 2807 2808 com = com_addr(unit); 2809 printf("info for channel %d\n", unit); 2810 printf("------------------\n"); 2811 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2812 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2813 if (com == NULL) 2814 return; 2815 iobase = com->iobase; 2816 printf("\n"); 2817 printf("cd1400 base address:\\tt%p\n", iobase); 2818 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2819 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2820 com->cor[0], com->cor[1], com->cor[2]); 2821 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2822 cd_getreg(com, CD1400_SRER), com->intr_enable); 2823 printf("service request register:\t0x%02x\n", 2824 cd_inb(iobase, CD1400_SVRR, com->cy_align)); 2825 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2826 cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); 2827 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2828 cd_inb(iobase, CD1400_RIR, com->cy_align), 2829 cd_inb(iobase, CD1400_TIR, com->cy_align), 2830 cd_inb(iobase, CD1400_MIR, com->cy_align)); 2831 printf("\n"); 2832 printf("com state:\t\t\t0x%02x\n", com->state); 2833 printf("calls to comstart():\t\t%d (%d useful)\n", 2834 com->start_count, com->start_real); 2835 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2836 ocount = 0; 2837 if (com->obufs[0].l_queued) 2838 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2839 if (com->obufs[1].l_queued) 2840 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2841 printf("tx buffer chars:\t\t%u\n", ocount); 2842 printf("received chars:\t\t\t%d\n", com->bytes_in); 2843 printf("received exceptions:\t\t%d\n", com->recv_exception); 2844 printf("modem signal deltas:\t\t%d\n", com->mdm); 2845 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2846 printf("\n"); 2847 tp = com->tp; 2848 if (tp != NULL) { 2849 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2850 printf( 2851 "upper layer queue lengths:\t%d raw, %d canon, %d output\n", 2852 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 2853 } else 2854 printf("tty state:\t\t\tclosed\n"); 2855} 2856#endif /* CyDebug */ 2857