cy_isa.c revision 41904
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.77 1998/12/17 17:40:13 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 disable_intr(); 2022 if (opt != com->cor[1]) { 2023 cor_change |= CD1400_CCR_COR2; 2024 cd_setreg(com, CD1400_COR2, com->cor[1] = opt); 2025 } 2026 enable_intr(); 2027 2028 /* 2029 * set channel option register 3 - 2030 * receiver FIFO interrupt threshold 2031 * flow control 2032 */ 2033 opt = RxFifoThreshold; 2034#ifdef Smarts 2035 if (t->c_lflag & ICANON) 2036 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 2037 if (iflag & IXOFF) 2038 /* detect and transparently handle START and STOP chars */ 2039 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 2040#endif 2041 if (opt != com->cor[2]) { 2042 cor_change |= CD1400_CCR_COR3; 2043 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2044 } 2045 2046 /* notify the CD1400 if COR1-3 have changed */ 2047 if (cor_change) 2048 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); 2049 2050 /* 2051 * set channel option register 4 - 2052 * CR/NL processing 2053 * break processing 2054 * received exception processing 2055 */ 2056 opt = 0; 2057 if (iflag & IGNCR) 2058 opt |= CD1400_COR4_IGNCR; 2059#ifdef Smarts 2060 /* 2061 * we need a new ttyinput() for this, as we don't want to 2062 * have ICRNL && INLCR being done in both layers, or to have 2063 * synchronisation problems 2064 */ 2065 if (iflag & ICRNL) 2066 opt |= CD1400_COR4_ICRNL; 2067 if (iflag & INLCR) 2068 opt |= CD1400_COR4_INLCR; 2069#endif 2070 if (iflag & IGNBRK) 2071 opt |= CD1400_COR4_IGNBRK; 2072 if (!(iflag & BRKINT)) 2073 opt |= CD1400_COR4_NOBRKINT; 2074#if 0 2075 /* XXX using this "intelligence" breaks reporting of overruns. */ 2076 if (iflag & IGNPAR) 2077 opt |= CD1400_COR4_PFO_DISCARD; 2078 else { 2079 if (iflag & PARMRK) 2080 opt |= CD1400_COR4_PFO_ESC; 2081 else 2082 opt |= CD1400_COR4_PFO_NUL; 2083 } 2084#else 2085 opt |= CD1400_COR4_PFO_EXCEPTION; 2086#endif 2087 cd_setreg(com, CD1400_COR4, opt); 2088 2089 /* 2090 * set channel option register 5 - 2091 */ 2092 opt = 0; 2093 if (iflag & ISTRIP) 2094 opt |= CD1400_COR5_ISTRIP; 2095 if (t->c_iflag & IEXTEN) 2096 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 2097 opt |= CD1400_COR5_LNEXT; 2098#ifdef Smarts 2099 if (t->c_oflag & ONLCR) 2100 opt |= CD1400_COR5_ONLCR; 2101 if (t->c_oflag & OCRNL) 2102 opt |= CD1400_COR5_OCRNL; 2103#endif 2104 cd_setreg(com, CD1400_COR5, opt); 2105 2106 /* 2107 * We always generate modem status change interrupts for CD changes. 2108 * Among other things, this is necessary to track TS_CARR_ON for 2109 * pstat to print even when the driver doesn't care. CD changes 2110 * should be rare so interrupts for them are not worth extra code to 2111 * avoid. We avoid interrupts for other modem status changes (except 2112 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is 2113 * simplest and best. 2114 */ 2115 2116 /* 2117 * set modem change option register 1 2118 * generate modem interrupts on which 1 -> 0 input transitions 2119 * also controls auto-DTR output flow-control, which we don't use 2120 */ 2121 opt = CD1400_MCOR1_CDzd; 2122#ifdef SOFT_CTS_OFLOW 2123 if (cflag & CCTS_OFLOW) 2124 opt |= CD1400_MCOR1_CTSzd; 2125#endif 2126 cd_setreg(com, CD1400_MCOR1, opt); 2127 2128 /* 2129 * set modem change option register 2 2130 * generate modem interrupts on specific 0 -> 1 input transitions 2131 */ 2132 opt = CD1400_MCOR2_CDod; 2133#ifdef SOFT_CTS_OFLOW 2134 if (cflag & CCTS_OFLOW) 2135 opt |= CD1400_MCOR2_CTSod; 2136#endif 2137 cd_setreg(com, CD1400_MCOR2, opt); 2138 2139 /* 2140 * XXX should have done this long ago, but there is too much state 2141 * to change all atomically. 2142 */ 2143 disable_intr(); 2144 2145 com->state &= ~CS_TTGO; 2146 if (!(tp->t_state & TS_TTSTOP)) 2147 com->state |= CS_TTGO; 2148 if (cflag & CRTS_IFLOW) { 2149 com->state |= CS_RTS_IFLOW; 2150 /* 2151 * If CS_RTS_IFLOW just changed from off to on, the change 2152 * needs to be propagated to MCR_RTS. This isn't urgent, 2153 * so do it later by calling comstart() instead of repeating 2154 * a lot of code from comstart() here. 2155 */ 2156 } else if (com->state & CS_RTS_IFLOW) { 2157 com->state &= ~CS_RTS_IFLOW; 2158 /* 2159 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2160 * on here, since comstart() won't do it later. 2161 */ 2162#if 0 2163 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2164#else 2165 cd_setreg(com, com->mcr_rts_reg, 2166 com->mcr_image |= com->mcr_rts); 2167#endif 2168 } 2169 2170 /* 2171 * Set up state to handle output flow control. 2172 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2173 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2174 */ 2175 com->state |= CS_ODEVREADY; 2176#ifdef SOFT_CTS_OFLOW 2177 com->state &= ~CS_CTS_OFLOW; 2178 if (cflag & CCTS_OFLOW) { 2179 com->state |= CS_CTS_OFLOW; 2180 if (!(com->last_modem_status & MSR_CTS)) 2181 com->state &= ~CS_ODEVREADY; 2182 } 2183#endif 2184 /* XXX shouldn't call functions while intrs are disabled. */ 2185 disc_optim(tp, t, com); 2186#if 0 2187 /* 2188 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2189 * unconditionally, but that defeated the careful discarding of 2190 * stale input in sioopen(). 2191 */ 2192 if (com->state >= (CS_BUSY | CS_TTGO)) 2193 siointr1(com); 2194#endif 2195 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2196 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 2197 cd_setreg(com, CD1400_SRER, 2198 com->intr_enable 2199 = com->intr_enable & ~CD1400_SRER_TXMPTY 2200 | CD1400_SRER_TXRDY); 2201 } else { 2202 if (com->intr_enable & CD1400_SRER_TXRDY) 2203 cd_setreg(com, CD1400_SRER, 2204 com->intr_enable 2205 = com->intr_enable & ~CD1400_SRER_TXRDY 2206 | CD1400_SRER_TXMPTY); 2207 } 2208 2209 enable_intr(); 2210 splx(s); 2211 comstart(tp); 2212 return (0); 2213} 2214 2215static void 2216comstart(tp) 2217 struct tty *tp; 2218{ 2219 struct com_s *com; 2220 int s; 2221#ifdef CyDebug 2222 bool_t started; 2223#endif 2224 int unit; 2225 2226 unit = DEV_TO_UNIT(tp->t_dev); 2227 com = com_addr(unit); 2228 s = spltty(); 2229 2230#ifdef CyDebug 2231 ++com->start_count; 2232 started = FALSE; 2233#endif 2234 2235 disable_intr(); 2236 if (tp->t_state & TS_TTSTOP) { 2237 com->state &= ~CS_TTGO; 2238 if (com->intr_enable & CD1400_SRER_TXRDY) 2239 cd_setreg(com, CD1400_SRER, 2240 com->intr_enable 2241 = com->intr_enable & ~CD1400_SRER_TXRDY 2242 | CD1400_SRER_TXMPTY); 2243 } else { 2244 com->state |= CS_TTGO; 2245 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2246 && !(com->intr_enable & CD1400_SRER_TXRDY)) 2247 cd_setreg(com, CD1400_SRER, 2248 com->intr_enable 2249 = com->intr_enable & ~CD1400_SRER_TXMPTY 2250 | CD1400_SRER_TXRDY); 2251 } 2252 if (tp->t_state & TS_TBLOCK) { 2253 if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) 2254#if 0 2255 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2256#else 2257 cd_setreg(com, com->mcr_rts_reg, 2258 com->mcr_image &= ~com->mcr_rts); 2259#endif 2260 } else { 2261 if (!(com->mcr_image & com->mcr_rts) 2262 && com->iptr < com->ihighwater 2263 && com->state & CS_RTS_IFLOW) 2264#if 0 2265 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2266#else 2267 cd_setreg(com, com->mcr_rts_reg, 2268 com->mcr_image |= com->mcr_rts); 2269#endif 2270 } 2271 enable_intr(); 2272 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2273 ttwwakeup(tp); 2274 splx(s); 2275 return; 2276 } 2277 if (tp->t_outq.c_cc != 0) { 2278 struct lbq *qp; 2279 struct lbq *next; 2280 2281 if (!com->obufs[0].l_queued) { 2282#ifdef CyDebug 2283 started = TRUE; 2284#endif 2285 com->obufs[0].l_tail 2286 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2287 sizeof com->obuf1); 2288 com->obufs[0].l_next = NULL; 2289 com->obufs[0].l_queued = TRUE; 2290 disable_intr(); 2291 if (com->state & CS_BUSY) { 2292 qp = com->obufq.l_next; 2293 while ((next = qp->l_next) != NULL) 2294 qp = next; 2295 qp->l_next = &com->obufs[0]; 2296 } else { 2297 com->obufq.l_head = com->obufs[0].l_head; 2298 com->obufq.l_tail = com->obufs[0].l_tail; 2299 com->obufq.l_next = &com->obufs[0]; 2300 com->state |= CS_BUSY; 2301 if (com->state >= (CS_BUSY | CS_TTGO 2302 | CS_ODEVREADY)) 2303 cd_setreg(com, CD1400_SRER, 2304 com->intr_enable 2305 = com->intr_enable 2306 & ~CD1400_SRER_TXMPTY 2307 | CD1400_SRER_TXRDY); 2308 } 2309 enable_intr(); 2310 } 2311 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2312#ifdef CyDebug 2313 started = TRUE; 2314#endif 2315 com->obufs[1].l_tail 2316 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2317 sizeof com->obuf2); 2318 com->obufs[1].l_next = NULL; 2319 com->obufs[1].l_queued = TRUE; 2320 disable_intr(); 2321 if (com->state & CS_BUSY) { 2322 qp = com->obufq.l_next; 2323 while ((next = qp->l_next) != NULL) 2324 qp = next; 2325 qp->l_next = &com->obufs[1]; 2326 } else { 2327 com->obufq.l_head = com->obufs[1].l_head; 2328 com->obufq.l_tail = com->obufs[1].l_tail; 2329 com->obufq.l_next = &com->obufs[1]; 2330 com->state |= CS_BUSY; 2331 if (com->state >= (CS_BUSY | CS_TTGO 2332 | CS_ODEVREADY)) 2333 cd_setreg(com, CD1400_SRER, 2334 com->intr_enable 2335 = com->intr_enable 2336 & ~CD1400_SRER_TXMPTY 2337 | CD1400_SRER_TXRDY); 2338 } 2339 enable_intr(); 2340 } 2341 tp->t_state |= TS_BUSY; 2342 } 2343#ifdef CyDebug 2344 if (started) 2345 ++com->start_real; 2346#endif 2347#if 0 2348 disable_intr(); 2349 if (com->state >= (CS_BUSY | CS_TTGO)) 2350 siointr1(com); /* fake interrupt to start output */ 2351 enable_intr(); 2352#endif 2353 ttwwakeup(tp); 2354 splx(s); 2355} 2356 2357static void 2358siostop(tp, rw) 2359 struct tty *tp; 2360 int rw; 2361{ 2362 struct com_s *com; 2363 bool_t wakeup_etc; 2364 2365 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2366 wakeup_etc = FALSE; 2367 disable_intr(); 2368 if (rw & FWRITE) { 2369 com->obufs[0].l_queued = FALSE; 2370 com->obufs[1].l_queued = FALSE; 2371 if (com->extra_state & CSE_ODONE) { 2372 com_events -= LOTS_OF_EVENTS; 2373 com->extra_state &= ~CSE_ODONE; 2374 if (com->etc != ETC_NONE) { 2375 if (com->etc == ETC_BREAK_ENDED) 2376 com->etc = ETC_NONE; 2377 wakeup_etc = TRUE; 2378 } 2379 } 2380 com->tp->t_state &= ~TS_BUSY; 2381 if (com->state & CS_ODONE) 2382 com_events -= LOTS_OF_EVENTS; 2383 com->state &= ~(CS_ODONE | CS_BUSY); 2384 } 2385 if (rw & FREAD) { 2386 com_events -= (com->iptr - com->ibuf); 2387 com->iptr = com->ibuf; 2388 } 2389 enable_intr(); 2390 if (wakeup_etc) 2391 wakeup(&com->etc); 2392 comstart(tp); 2393 2394 /* XXX should clear h/w fifos too. */ 2395} 2396 2397static struct tty * 2398siodevtotty(dev) 2399 dev_t dev; 2400{ 2401 int mynor; 2402 int unit; 2403 2404 mynor = minor(dev); 2405 if (mynor & CONTROL_MASK) 2406 return (NULL); 2407 unit = MINOR_TO_UNIT(mynor); 2408 if ((u_int) unit >= NSIO) 2409 return (NULL); 2410 return (&sio_tty[unit]); 2411} 2412 2413static int 2414commctl(com, bits, how) 2415 struct com_s *com; 2416 int bits; 2417 int how; 2418{ 2419 int mcr; 2420 int msr; 2421 2422 if (how == DMGET) { 2423 if (com->channel_control & CD1400_CCR_RCVEN) 2424 bits |= TIOCM_LE; 2425 mcr = com->mcr_image; 2426 if (mcr & com->mcr_dtr) 2427 bits |= TIOCM_DTR; 2428 if (mcr & com->mcr_rts) 2429 /* XXX wired on for Cyclom-8Ys */ 2430 bits |= TIOCM_RTS; 2431 2432 /* 2433 * We must read the modem status from the hardware because 2434 * we don't generate modem status change interrupts for all 2435 * changes, so com->prev_modem_status is not guaranteed to 2436 * be up to date. This is safe, unlike for sio, because 2437 * reading the status register doesn't clear pending modem 2438 * status change interrupts. 2439 */ 2440 msr = cd_getreg(com, CD1400_MSVR2); 2441 2442 if (msr & MSR_CTS) 2443 bits |= TIOCM_CTS; 2444 if (msr & MSR_DCD) 2445 bits |= TIOCM_CD; 2446 if (msr & MSR_DSR) 2447 bits |= TIOCM_DSR; 2448 if (msr & MSR_RI) 2449 /* XXX not connected except for Cyclom-16Y? */ 2450 bits |= TIOCM_RI; 2451 return (bits); 2452 } 2453 mcr = 0; 2454 if (bits & TIOCM_DTR) 2455 mcr |= com->mcr_dtr; 2456 if (bits & TIOCM_RTS) 2457 mcr |= com->mcr_rts; 2458 disable_intr(); 2459 switch (how) { 2460 case DMSET: 2461 com->mcr_image = mcr; 2462 cd_setreg(com, CD1400_MSVR1, mcr); 2463 cd_setreg(com, CD1400_MSVR2, mcr); 2464 break; 2465 case DMBIS: 2466 com->mcr_image = mcr = com->mcr_image | mcr; 2467 cd_setreg(com, CD1400_MSVR1, mcr); 2468 cd_setreg(com, CD1400_MSVR2, mcr); 2469 break; 2470 case DMBIC: 2471 com->mcr_image = mcr = com->mcr_image & ~mcr; 2472 cd_setreg(com, CD1400_MSVR1, mcr); 2473 cd_setreg(com, CD1400_MSVR2, mcr); 2474 break; 2475 } 2476 enable_intr(); 2477 return (0); 2478} 2479 2480static void 2481siosettimeout() 2482{ 2483 struct com_s *com; 2484 bool_t someopen; 2485 int unit; 2486 2487 /* 2488 * Set our timeout period to 1 second if no polled devices are open. 2489 * Otherwise set it to max(1/200, 1/hz). 2490 * Enable timeouts iff some device is open. 2491 */ 2492 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2493 sio_timeout = hz; 2494 someopen = FALSE; 2495 for (unit = 0; unit < NSIO; ++unit) { 2496 com = com_addr(unit); 2497 if (com != NULL && com->tp != NULL 2498 && com->tp->t_state & TS_ISOPEN) { 2499 someopen = TRUE; 2500#if 0 2501 if (com->poll || com->poll_output) { 2502 sio_timeout = hz > 200 ? hz / 200 : 1; 2503 break; 2504 } 2505#endif 2506 } 2507 } 2508 if (someopen) { 2509 sio_timeouts_until_log = hz / sio_timeout; 2510 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 2511 sio_timeout); 2512 } else { 2513 /* Flush error messages, if any. */ 2514 sio_timeouts_until_log = 1; 2515 comwakeup((void *)NULL); 2516 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2517 } 2518} 2519 2520static void 2521comwakeup(chan) 2522 void *chan; 2523{ 2524 struct com_s *com; 2525 int unit; 2526 2527 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 2528 2529#if 0 2530 /* 2531 * Recover from lost output interrupts. 2532 * Poll any lines that don't use interrupts. 2533 */ 2534 for (unit = 0; unit < NSIO; ++unit) { 2535 com = com_addr(unit); 2536 if (com != NULL 2537 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2538 disable_intr(); 2539 siointr1(com); 2540 enable_intr(); 2541 } 2542 } 2543#endif 2544 2545 /* 2546 * Check for and log errors, but not too often. 2547 */ 2548 if (--sio_timeouts_until_log > 0) 2549 return; 2550 sio_timeouts_until_log = hz / sio_timeout; 2551 for (unit = 0; unit < NSIO; ++unit) { 2552 int errnum; 2553 2554 com = com_addr(unit); 2555 if (com == NULL) 2556 continue; 2557 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2558 u_int delta; 2559 u_long total; 2560 2561 disable_intr(); 2562 delta = com->delta_error_counts[errnum]; 2563 com->delta_error_counts[errnum] = 0; 2564 enable_intr(); 2565 if (delta == 0) 2566 continue; 2567 total = com->error_counts[errnum] += delta; 2568 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 2569 unit, delta, error_desc[errnum], 2570 delta == 1 ? "" : "s", total); 2571 } 2572 } 2573} 2574 2575static void 2576disc_optim(tp, t, com) 2577 struct tty *tp; 2578 struct termios *t; 2579 struct com_s *com; 2580{ 2581#ifndef SOFT_HOTCHAR 2582 u_char opt; 2583#endif 2584 2585 /* 2586 * XXX can skip a lot more cases if Smarts. Maybe 2587 * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we 2588 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. 2589 */ 2590 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 2591 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2592 && (!(t->c_iflag & PARMRK) 2593 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 2594 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 2595 && linesw[tp->t_line].l_rint == ttyinput) 2596 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2597 else 2598 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2599 com->hotchar = linesw[tp->t_line].l_hotchar; 2600#ifndef SOFT_HOTCHAR 2601 opt = com->cor[2] & ~CD1400_COR3_SCD34; 2602 if (com->hotchar != 0) { 2603 cd_setreg(com, CD1400_SCHR3, com->hotchar); 2604 cd_setreg(com, CD1400_SCHR4, com->hotchar); 2605 opt |= CD1400_COR3_SCD34; 2606 } 2607 if (opt != com->cor[2]) { 2608 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2609 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 2610 } 2611#endif 2612} 2613 2614#ifdef Smarts 2615/* standard line discipline input routine */ 2616int 2617cyinput(c, tp) 2618 int c; 2619 struct tty *tp; 2620{ 2621 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 2622 * bits, as they are done by the CD1400. Hardly worth the effort, 2623 * given that high-throughput sessions are raw anyhow. 2624 */ 2625} 2626#endif /* Smarts */ 2627 2628static int 2629comspeed(speed, cy_clock, prescaler_io) 2630 speed_t speed; 2631 u_long cy_clock; 2632 int *prescaler_io; 2633{ 2634 int actual; 2635 int error; 2636 int divider; 2637 int prescaler; 2638 int prescaler_unit; 2639 2640 if (speed == 0) 2641 return (0); 2642 if (speed < 0 || speed > 150000) 2643 return (-1); 2644 2645 /* determine which prescaler to use */ 2646 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2647 prescaler_unit--, prescaler >>= 2) { 2648 if (cy_clock / prescaler / speed > 63) 2649 break; 2650 } 2651 2652 divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ 2653 if (divider > 255) 2654 divider = 255; 2655 actual = cy_clock/prescaler/divider; 2656 2657 /* 10 times error in percent: */ 2658 error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; 2659 2660 /* 3.0% max error tolerance */ 2661 if (error < -30 || error > 30) 2662 return (-1); 2663 2664#if 0 2665 printf("prescaler = %d (%d)\n", prescaler, prescaler_unit); 2666 printf("divider = %d (%x)\n", divider, divider); 2667 printf("actual = %d\n", actual); 2668 printf("error = %d\n", error); 2669#endif 2670 2671 *prescaler_io = prescaler_unit; 2672 return (divider); 2673} 2674 2675static void 2676cd1400_channel_cmd(com, cmd) 2677 struct com_s *com; 2678 int cmd; 2679{ 2680 /* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed, 2681 as the card is probed every round? Replaced delaycount with 8k. 2682 Either delaycount has to be implemented in FreeBSD or more sensible 2683 way of doing these should be implemented. DELAY isn't enough here. 2684 */ 2685 u_int maxwait = 5 * 8 * 1024; /* approx. 5 ms */ 2686 2687 /* wait for processing of previous command to complete */ 2688 while (cd_getreg(com, CD1400_CCR) && maxwait--) 2689 ; 2690 2691 if (!maxwait) 2692 log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n", 2693 5 * 8 * 1024); 2694 2695 cd_setreg(com, CD1400_CCR, cmd); 2696} 2697 2698static void 2699cd_etc(com, etc) 2700 struct com_s *com; 2701 int etc; 2702{ 2703 /* 2704 * We can't change the hardware's ETC state while there are any 2705 * characters in the tx fifo, since those characters would be 2706 * interpreted as commands! Unputting characters from the fifo 2707 * is difficult, so we wait up to 12 character times for the fifo 2708 * to drain. The command will be delayed for up to 2 character 2709 * times for the tx to become empty. Unputting characters from 2710 * the tx holding and shift registers is impossible, so we wait 2711 * for the tx to become empty so that the command is sure to be 2712 * executed soon after we issue it. 2713 */ 2714 disable_intr(); 2715 if (com->etc == etc) { 2716 enable_intr(); 2717 goto wait; 2718 } 2719 if (etc == CD1400_ETC_SENDBREAK 2720 && (com->etc == ETC_BREAK_STARTING 2721 || com->etc == ETC_BREAK_STARTED) 2722 || etc == CD1400_ETC_STOPBREAK 2723 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED 2724 || com->etc == ETC_NONE)) { 2725 enable_intr(); 2726 return; 2727 } 2728 com->etc = etc; 2729 cd_setreg(com, CD1400_SRER, 2730 com->intr_enable 2731 = com->intr_enable & ~CD1400_SRER_TXRDY | CD1400_SRER_TXMPTY); 2732 enable_intr(); 2733wait: 2734 while (com->etc == etc 2735 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) 2736 continue; 2737} 2738 2739static int 2740cd_getreg(com, reg) 2741 struct com_s *com; 2742 int reg; 2743{ 2744 struct com_s *basecom; 2745 u_char car; 2746 int cy_align; 2747 u_long ef; 2748 cy_addr iobase; 2749 int val; 2750 2751 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2752 car = com->unit & CD1400_CAR_CHAN; 2753 cy_align = com->cy_align; 2754 iobase = com->iobase; 2755 ef = read_eflags(); 2756 disable_intr(); 2757 if (basecom->car != car) 2758 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2759 val = cd_inb(iobase, reg, cy_align); 2760 write_eflags(ef); 2761 return (val); 2762} 2763 2764static void 2765cd_setreg(com, reg, val) 2766 struct com_s *com; 2767 int reg; 2768 int val; 2769{ 2770 struct com_s *basecom; 2771 u_char car; 2772 int cy_align; 2773 u_long ef; 2774 cy_addr iobase; 2775 2776 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2777 car = com->unit & CD1400_CAR_CHAN; 2778 cy_align = com->cy_align; 2779 iobase = com->iobase; 2780 ef = read_eflags(); 2781 disable_intr(); 2782 if (basecom->car != car) 2783 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2784 cd_outb(iobase, reg, cy_align, val); 2785 write_eflags(ef); 2786} 2787 2788#ifdef CyDebug 2789/* useful in ddb */ 2790void 2791cystatus(unit) 2792 int unit; 2793{ 2794 struct com_s *com; 2795 cy_addr iobase; 2796 u_int ocount; 2797 struct tty *tp; 2798 2799 com = com_addr(unit); 2800 printf("info for channel %d\n", unit); 2801 printf("------------------\n"); 2802 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2803 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2804 if (com == NULL) 2805 return; 2806 iobase = com->iobase; 2807 printf("\n"); 2808 printf("cd1400 base address:\\tt%p\n", iobase); 2809 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2810 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2811 com->cor[0], com->cor[1], com->cor[2]); 2812 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2813 cd_getreg(com, CD1400_SRER), com->intr_enable); 2814 printf("service request register:\t0x%02x\n", 2815 cd_inb(iobase, CD1400_SVRR, com->cy_align)); 2816 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2817 cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); 2818 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2819 cd_inb(iobase, CD1400_RIR, com->cy_align), 2820 cd_inb(iobase, CD1400_TIR, com->cy_align), 2821 cd_inb(iobase, CD1400_MIR, com->cy_align)); 2822 printf("\n"); 2823 printf("com state:\t\t\t0x%02x\n", com->state); 2824 printf("calls to comstart():\t\t%d (%d useful)\n", 2825 com->start_count, com->start_real); 2826 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2827 ocount = 0; 2828 if (com->obufs[0].l_queued) 2829 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2830 if (com->obufs[1].l_queued) 2831 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2832 printf("tx buffer chars:\t\t%u\n", ocount); 2833 printf("received chars:\t\t\t%d\n", com->bytes_in); 2834 printf("received exceptions:\t\t%d\n", com->recv_exception); 2835 printf("modem signal deltas:\t\t%d\n", com->mdm); 2836 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2837 printf("\n"); 2838 tp = com->tp; 2839 if (tp != NULL) { 2840 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2841 printf( 2842 "upper layer queue lengths:\t%d raw, %d canon, %d output\n", 2843 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 2844 } else 2845 printf("tty state:\t\t\tclosed\n"); 2846} 2847#endif /* CyDebug */ 2848