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