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