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