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