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