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