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