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