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