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