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