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