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