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