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