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