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