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