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