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