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