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