cy.c revision 127885
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 31#include <sys/cdefs.h> 32__FBSDID("$FreeBSD: head/sys/dev/cy/cy.c 127885 2004-04-05 08:16:23Z bde $"); 33 34#include "opt_compat.h" 35 36/* 37 * TODO: 38 * Atomic COR change. 39 * Consoles. 40 */ 41 42/* 43 * Temporary compile-time configuration options. 44 */ 45#define RxFifoThreshold (CD1400_RX_FIFO_SIZE / 2) 46 /* Number of chars in the receiver FIFO before an 47 * an interrupt is generated. Should depend on 48 * line speed. Needs to be about 6 on a 486DX33 49 * for 4 active ports at 115200 bps. Why doesn't 50 * 10 work? 51 */ 52#define PollMode /* Use polling-based irq service routine, not the 53 * hardware svcack lines. Must be defined for 54 * Cyclom-16Y boards. Less efficient for Cyclom-8Ys, 55 * and stops 4 * 115200 bps from working. 56 */ 57#undef Smarts /* Enable slightly more CD1400 intelligence. Mainly 58 * the output CR/LF processing, plus we can avoid a 59 * few checks usually done in ttyinput(). 60 * 61 * XXX not fully implemented, and not particularly 62 * worthwhile. 63 */ 64#undef CyDebug /* Include debugging code (not very expensive). */ 65 66/* These will go away. */ 67#undef SOFT_CTS_OFLOW 68#define SOFT_HOTCHAR 69 70#include <sys/param.h> 71#include <sys/systm.h> 72#include <sys/bus.h> 73#include <sys/conf.h> 74#include <sys/fcntl.h> 75#include <sys/interrupt.h> 76#include <sys/kernel.h> 77#include <sys/lock.h> 78#include <sys/malloc.h> 79#include <sys/mutex.h> 80#include <sys/syslog.h> 81#include <sys/tty.h> 82 83#include <machine/bus.h> 84#include <machine/psl.h> 85#include <sys/rman.h> 86#include <machine/resource.h> 87 88#include <isa/isavar.h> 89 90#include <i386/isa/cyreg.h> 91#include <i386/isa/ic/cd1400.h> 92 93#define NCY 10 /* KLUDGE */ 94 95/* 96 * Dictionary so that I can name everything *sio* or *com* to compare with 97 * sio.c. There is also lots of ugly formatting and unnecessary ifdefs to 98 * simplify the comparision. These will go away. 99 */ 100#define LSR_BI CD1400_RDSR_BREAK 101#define LSR_FE CD1400_RDSR_FE 102#define LSR_OE CD1400_RDSR_OE 103#define LSR_PE CD1400_RDSR_PE 104#define MCR_DTR CD1400_MSVR2_DTR 105#define MCR_RTS CD1400_MSVR1_RTS 106#define MSR_CTS CD1400_MSVR2_CTS 107#define MSR_DCD CD1400_MSVR2_CD 108#define MSR_DSR CD1400_MSVR2_DSR 109#define MSR_RI CD1400_MSVR2_RI 110#define NSIO (NCY * CY_MAX_PORTS) 111#define comconsole cyconsole 112#define comdefaultrate cydefaultrate 113#define com_events cy_events 114#define comhardclose cyhardclose 115#define commctl cymctl 116#define comparam cyparam 117#define comspeed cyspeed 118#define comstart cystart 119#define comwakeup cywakeup 120#define p_com_addr p_cy_addr 121#define sioclose cyclose 122#define siodriver cydriver 123#define siodtrwakeup cydtrwakeup 124#define sioinput cyinput 125#define siointr1 cyintr 126#define sioioctl cyioctl 127#define sioopen cyopen 128#define siopoll cypoll 129#define siosettimeout cysettimeout 130#define siosetwater cysetwater 131#define comstop cystop 132#define siowrite cywrite 133#define sio_fast_ih cy_fast_ih 134#define sio_inited cy_inited 135#define sio_irec cy_irec 136#define sio_lock cy_lock 137#define sio_slow_ih cy_slow_ih 138#define sio_timeout cy_timeout 139#define sio_timeout_handle cy_timeout_handle 140#define sio_timeouts_until_log cy_timeouts_until_log 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 147 148/* 149 * ETC states. com->etc may also contain a hardware ETC command value, 150 * meaning that execution of that command is pending. 151 */ 152#define ETC_NONE 0 /* we depend on bzero() setting this */ 153#define ETC_BREAK_STARTING 1 154#define ETC_BREAK_STARTED 2 155#define ETC_BREAK_ENDING 3 156#define ETC_BREAK_ENDED 4 157 158#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 159 160#define CALLOUT_MASK 0x80 161#define CONTROL_MASK 0x60 162#define CONTROL_INIT_STATE 0x20 163#define CONTROL_LOCK_STATE 0x40 164#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 165#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 166/* 167 * Not all of the magic is parametrized in the following macros. 16 and 168 * 0xff are related to the bitfields in a udev_t. CY_MAX_PORTS must be 169 * ((0xff & ~MINOR_MAGIC_MASK) + 1) for things to work. 170 */ 171#define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS \ 172 | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK)) 173#define UNIT_TO_MINOR(unit) (((unit) / CY_MAX_PORTS) << 16 \ 174 | (((unit) & 0xff) & ~MINOR_MAGIC_MASK)) 175 176/* 177 * com state bits. 178 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 179 * than the other bits so that they can be tested as a group without masking 180 * off the low bits. 181 * 182 * The following com and tty flags correspond closely: 183 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and 184 * comstop()) 185 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) 186 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 187 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 188 * TS_FLUSH is not used. 189 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 190 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 191 */ 192#define CS_BUSY 0x80 /* output in progress */ 193#define CS_TTGO 0x40 /* output not stopped by XOFF */ 194#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 195#define CS_CHECKMSR 1 /* check of MSR scheduled */ 196#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 197#define CS_DTR_OFF 0x10 /* DTR held off */ 198#define CS_ODONE 4 /* output completed */ 199#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 200#define CSE_ODONE 1 /* output transmitted */ 201 202static char const * const error_desc[] = { 203#define CE_OVERRUN 0 204 "silo overflow", 205#define CE_INTERRUPT_BUF_OVERFLOW 1 206 "interrupt-level buffer overflow", 207#define CE_TTY_BUF_OVERFLOW 2 208 "tty-level buffer overflow", 209}; 210 211#define CE_NTYPES 3 212#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 213 214#ifdef SMP 215#define COM_LOCK() mtx_lock_spin(&sio_lock) 216#define COM_UNLOCK() mtx_unlock_spin(&sio_lock) 217#else 218#define COM_LOCK() 219#define COM_UNLOCK() 220#endif 221 222/* types. XXX - should be elsewhere */ 223typedef u_char bool_t; /* boolean */ 224typedef u_char volatile *cy_addr; 225 226/* queue of linear buffers */ 227struct lbq { 228 u_char *l_head; /* next char to process */ 229 u_char *l_tail; /* one past the last char to process */ 230 struct lbq *l_next; /* next in queue */ 231 bool_t l_queued; /* nonzero if queued */ 232}; 233 234/* com device structure */ 235struct com_s { 236 u_char state; /* miscellaneous flag bits */ 237 bool_t active_out; /* nonzero if the callout device is open */ 238#if 0 239 u_char cfcr_image; /* copy of value written to CFCR */ 240#endif 241 u_char etc; /* pending Embedded Transmit Command */ 242 u_char extra_state; /* more flag bits, separate for order trick */ 243#if 0 244 u_char fifo_image; /* copy of value written to FIFO */ 245#endif 246 u_char gfrcr_image; /* copy of value read from GFRCR */ 247#if 0 248 bool_t hasfifo; /* nonzero for 16550 UARTs */ 249 bool_t loses_outints; /* nonzero if device loses output interrupts */ 250#endif 251 u_char mcr_dtr; /* MCR bit that is wired to DTR */ 252 u_char mcr_image; /* copy of value written to MCR */ 253 u_char mcr_rts; /* MCR bit that is wired to RTS */ 254#if 0 255#ifdef COM_MULTIPORT 256 bool_t multiport; /* is this unit part of a multiport device? */ 257#endif /* COM_MULTIPORT */ 258 bool_t no_irq; /* nonzero if irq is not attached */ 259 bool_t poll; /* nonzero if polling is required */ 260 bool_t poll_output; /* nonzero if polling for output is required */ 261#endif 262 int unit; /* unit number */ 263 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 264#if 0 265 u_int tx_fifo_size; 266#endif 267 u_int wopeners; /* # processes waiting for DCD in open() */ 268 269 /* 270 * The high level of the driver never reads status registers directly 271 * because there would be too many side effects to handle conveniently. 272 * Instead, it reads copies of the registers stored here by the 273 * interrupt handler. 274 */ 275 u_char last_modem_status; /* last MSR read by intr handler */ 276 u_char prev_modem_status; /* last MSR handled by high level */ 277 278 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 279 u_char *ibuf; /* start of input buffer */ 280 u_char *ibufend; /* end of input buffer */ 281 u_char *ibufold; /* old input buffer, to be freed */ 282 u_char *ihighwater; /* threshold in input buffer */ 283 u_char *iptr; /* next free spot in input buffer */ 284 int ibufsize; /* size of ibuf (not include error bytes) */ 285 int ierroff; /* offset of error bytes in ibuf */ 286 287 struct lbq obufq; /* head of queue of output buffers */ 288 struct lbq obufs[2]; /* output buffers */ 289 290 int cy_align; /* index for register alignment */ 291 cy_addr cy_iobase; /* base address of this port's cyclom */ 292 cy_addr iobase; /* base address of this port's cd1400 */ 293 int mcr_rts_reg; /* cd1400 reg number of reg holding mcr_rts */ 294 295 struct tty *tp; /* cross reference */ 296 297 /* Initial state. */ 298 struct termios it_in; /* should be in struct tty */ 299 struct termios it_out; 300 301 /* Lock state. */ 302 struct termios lt_in; /* should be in struct tty */ 303 struct termios lt_out; 304 305 bool_t do_timestamp; 306 bool_t do_dcd_timestamp; 307 struct timeval timestamp; 308 struct timeval dcd_timestamp; 309 310 u_long bytes_in; /* statistics */ 311 u_long bytes_out; 312 u_int delta_error_counts[CE_NTYPES]; 313 u_long error_counts[CE_NTYPES]; 314 315 u_int recv_exception; /* exception chars received */ 316 u_int mdm; /* modem signal changes */ 317#ifdef CyDebug 318 u_int start_count; /* no. of calls to comstart() */ 319 u_int start_real; /* no. of calls that did something */ 320#endif 321 u_char car; /* CD1400 CAR shadow (if first unit in cd) */ 322 u_char channel_control;/* CD1400 CCR control command shadow */ 323 u_char cor[3]; /* CD1400 COR1-3 shadows */ 324 u_char intr_enable; /* CD1400 SRER shadow */ 325 326 /* 327 * Data area for output buffers. Someday we should build the output 328 * buffer queue without copying data. 329 */ 330 u_char obuf1[256]; 331 u_char obuf2[256]; 332}; 333 334devclass_t cy_devclass; 335 336/* PCI driver entry points. */ 337void *cyattach_common(cy_addr cy_iobase, int cy_align); 338driver_intr_t siointr1; 339 340static int cy_units(cy_addr cy_iobase, int cy_align); 341static void cd1400_channel_cmd(struct com_s *com, int cmd); 342static void cd1400_channel_cmd_wait(struct com_s *com); 343static void cd_etc(struct com_s *com, int etc); 344static int cd_getreg(struct com_s *com, int reg); 345static void cd_setreg(struct com_s *com, int reg, int val); 346static int cy_isa_attach(device_t dev); 347static int cy_isa_probe(device_t dev); 348static timeout_t siodtrwakeup; 349static void comhardclose(struct com_s *com); 350static void sioinput(struct com_s *com); 351static int commctl(struct com_s *com, int bits, int how); 352static int comparam(struct tty *tp, struct termios *t); 353static void siopoll(void *arg); 354static void siosettimeout(void); 355static int siosetwater(struct com_s *com, speed_t speed); 356static int comspeed(speed_t speed, u_long cy_clock, int *prescaler_io); 357static void comstart(struct tty *tp); 358static void comstop(struct tty *tp, int rw); 359static timeout_t comwakeup; 360static void disc_optim(struct tty *tp, struct termios *t, 361 struct com_s *com); 362 363#ifdef CyDebug 364void cystatus(int unit); 365#endif 366 367static char driver_name[] = "cy"; 368static struct mtx sio_lock; 369static int sio_inited; 370 371/* table and macro for fast conversion from a unit number to its com struct */ 372static struct com_s *p_com_addr[NSIO]; 373#define com_addr(unit) (p_com_addr[unit]) 374 375static device_method_t cy_isa_methods[] = { 376 /* Device interface. */ 377 DEVMETHOD(device_probe, cy_isa_probe), 378 DEVMETHOD(device_attach, cy_isa_attach), 379 380 { 0, 0 } 381}; 382 383static driver_t cy_isa_driver = { 384 driver_name, 385 cy_isa_methods, 386 0, 387}; 388 389DRIVER_MODULE(cy, isa, cy_isa_driver, cy_devclass, 0, 0); 390 391static d_open_t sioopen; 392static d_close_t sioclose; 393static d_write_t siowrite; 394static d_ioctl_t sioioctl; 395 396static struct cdevsw sio_cdevsw = { 397 .d_version = D_VERSION, 398 .d_open = sioopen, 399 .d_close = sioclose, 400 .d_write = siowrite, 401 .d_ioctl = sioioctl, 402 .d_name = driver_name, 403 .d_flags = D_TTY | D_NEEDGIANT, 404}; 405 406static int comconsole = -1; 407static speed_t comdefaultrate = TTYDEF_SPEED; 408static u_int com_events; /* input chars + weighted output completions */ 409static void *sio_fast_ih; 410static void *sio_slow_ih; 411static int sio_timeout; 412static int sio_timeouts_until_log; 413static struct callout_handle sio_timeout_handle 414 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 415 416#ifdef CyDebug 417static u_int cd_inbs; 418static u_int cy_inbs; 419static u_int cd_outbs; 420static u_int cy_outbs; 421static u_int cy_svrr_probes; 422static u_int cy_timeouts; 423#endif 424 425static int cy_chip_offset[] = { 426 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00, 427}; 428static int cy_nr_cd1400s[NCY]; 429static int cy_total_devices; 430#undef RxFifoThreshold 431static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); 432 433static int 434cy_isa_probe(device_t dev) 435{ 436 struct resource *mem_res; 437 cy_addr iobase; 438 int mem_rid; 439 440 if (isa_get_logicalid(dev) != 0) /* skip PnP probes */ 441 return (ENXIO); 442 443 mem_rid = 0; 444 mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &mem_rid, 445 0ul, ~0ul, 0ul, RF_ACTIVE); 446 if (mem_res == NULL) { 447 device_printf(dev, "ioport resource allocation failed\n"); 448 return (ENXIO); 449 } 450 iobase = rman_get_virtual(mem_res); 451 452 /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ 453 cy_inb(iobase, CY16_RESET, 0); /* XXX? */ 454 DELAY(500); /* wait for the board to get its act together */ 455 456 /* this is needed to get the board out of reset */ 457 cy_outb(iobase, CY_CLEAR_INTR, 0, 0); 458 DELAY(500); 459 460 bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res); 461 return (cy_units(iobase, 0) == 0 ? ENXIO : 0); 462} 463 464static int 465cy_units(cy_iobase, cy_align) 466 cy_addr cy_iobase; 467 int cy_align; 468{ 469 int cyu; 470 u_char firmware_version; 471 int i; 472 cy_addr iobase; 473 474 for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { 475 iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align); 476 477 /* wait for chip to become ready for new command */ 478 for (i = 0; i < 10; i++) { 479 DELAY(50); 480 if (!cd_inb(iobase, CD1400_CCR, cy_align)) 481 break; 482 } 483 484 /* clear the GFRCR register */ 485 cd_outb(iobase, CD1400_GFRCR, cy_align, 0); 486 487 /* issue a reset command */ 488 cd_outb(iobase, CD1400_CCR, cy_align, 489 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 490 491 /* XXX bogus initialization to avoid a gcc bug/warning. */ 492 firmware_version = 0; 493 494 /* wait for the CD1400 to initialize itself */ 495 for (i = 0; i < 200; i++) { 496 DELAY(50); 497 498 /* retrieve firmware version */ 499 firmware_version = cd_inb(iobase, CD1400_GFRCR, 500 cy_align); 501 if ((firmware_version & 0xf0) == 0x40) 502 break; 503 } 504 505 /* 506 * Anything in the 0x40-0x4F range is fine. 507 * If one CD1400 is bad then we don't support higher 508 * numbered good ones on this board. 509 */ 510 if ((firmware_version & 0xf0) != 0x40) 511 break; 512 } 513 return (cyu); 514} 515 516static int 517cy_isa_attach(device_t dev) 518{ 519 struct resource *irq_res, *mem_res; 520 void *irq_cookie, *vaddr, *vsc; 521 int irq_rid, mem_rid; 522 523 irq_res = NULL; 524 mem_res = NULL; 525 526 mem_rid = 0; 527 mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &mem_rid, 528 0ul, ~0ul, 0ul, RF_ACTIVE); 529 if (mem_res == NULL) { 530 device_printf(dev, "memory resource allocation failed\n"); 531 goto fail; 532 } 533 vaddr = rman_get_virtual(mem_res); 534 535 vsc = cyattach_common(vaddr, 0); 536 if (vsc == NULL) { 537 device_printf(dev, "no ports found!\n"); 538 goto fail; 539 } 540 541 irq_rid = 0; 542 irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, 0ul, ~0ul, 0ul, 543 RF_SHAREABLE | RF_ACTIVE); 544 if (irq_res == NULL) { 545 device_printf(dev, "interrupt resource allocation failed\n"); 546 goto fail; 547 } 548 if (bus_setup_intr(dev, irq_res, INTR_TYPE_TTY | INTR_FAST, cyintr, 549 vsc, &irq_cookie) != 0) { 550 device_printf(dev, "interrupt setup failed\n"); 551 goto fail; 552 } 553 554 return (0); 555 556fail: 557 if (irq_res != NULL) 558 bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res); 559 if (mem_res != NULL) 560 bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res); 561 return (ENXIO); 562} 563 564void * 565cyattach_common(cy_iobase, cy_align) 566 cy_addr cy_iobase; 567 int cy_align; 568{ 569 int adapter; 570 int cyu; 571 u_char firmware_version; 572 cy_addr iobase; 573 int minorbase; 574 int ncyu; 575 int unit; 576 577 while (sio_inited != 2) 578 if (atomic_cmpset_int(&sio_inited, 0, 1)) { 579 mtx_init(&sio_lock, driver_name, NULL, MTX_SPIN); 580 atomic_store_rel_int(&sio_inited, 2); 581 } 582 583 adapter = cy_total_devices; 584 if ((u_int)adapter >= NCY) { 585 printf( 586 "cy%d: can't attach adapter: insufficient cy devices configured\n", 587 adapter); 588 return (NULL); 589 } 590 ncyu = cy_units(cy_iobase, cy_align); 591 if (ncyu == 0) 592 return (NULL); 593 cy_nr_cd1400s[adapter] = ncyu; 594 cy_total_devices++; 595 596 unit = adapter * CY_MAX_PORTS; 597 for (cyu = 0; cyu < ncyu; ++cyu) { 598 int cdu; 599 600 iobase = (cy_addr) (cy_iobase 601 + (cy_chip_offset[cyu] << cy_align)); 602 firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); 603 604 /* Set up a receive timeout period of than 1+ ms. */ 605 cd_outb(iobase, CD1400_PPR, cy_align, 606 howmany(CY_CLOCK(firmware_version) 607 / CD1400_PPR_PRESCALER, 1000)); 608 609 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { 610 struct com_s *com; 611 int s; 612 613 com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT | M_ZERO); 614 if (com == NULL) 615 break; 616 com->unit = unit; 617 com->gfrcr_image = firmware_version; 618 if (CY_RTS_DTR_SWAPPED(firmware_version)) { 619 com->mcr_dtr = MCR_RTS; 620 com->mcr_rts = MCR_DTR; 621 com->mcr_rts_reg = CD1400_MSVR2; 622 } else { 623 com->mcr_dtr = MCR_DTR; 624 com->mcr_rts = MCR_RTS; 625 com->mcr_rts_reg = CD1400_MSVR1; 626 } 627 com->dtr_wait = 3 * hz; 628 com->obufs[0].l_head = com->obuf1; 629 com->obufs[1].l_head = com->obuf2; 630 631 com->cy_align = cy_align; 632 com->cy_iobase = cy_iobase; 633 com->iobase = iobase; 634 com->car = ~CD1400_CAR_CHAN; 635 636 /* 637 * We don't use all the flags from <sys/ttydefaults.h> since they 638 * are only relevant for logins. It's important to have echo off 639 * initially so that the line doesn't start blathering before the 640 * echo flag can be turned off. 641 */ 642 com->it_in.c_iflag = 0; 643 com->it_in.c_oflag = 0; 644 com->it_in.c_cflag = TTYDEF_CFLAG; 645 com->it_in.c_lflag = 0; 646 if (unit == comconsole) { 647 com->it_in.c_iflag = TTYDEF_IFLAG; 648 com->it_in.c_oflag = TTYDEF_OFLAG; 649 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 650 com->it_in.c_lflag = TTYDEF_LFLAG; 651 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 652 } 653 if (siosetwater(com, com->it_in.c_ispeed) != 0) { 654 free(com, M_DEVBUF); 655 return (NULL); 656 } 657 termioschars(&com->it_in); 658 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 659 com->it_out = com->it_in; 660 661 s = spltty(); 662 com_addr(unit) = com; 663 splx(s); 664 665 if (sio_fast_ih == NULL) { 666 swi_add(&tty_ithd, "tty:cy", siopoll, NULL, SWI_TTY, 0, 667 &sio_fast_ih); 668 swi_add(&clk_ithd, "tty:cy", siopoll, NULL, SWI_TTY, 0, 669 &sio_slow_ih); 670 } 671 minorbase = UNIT_TO_MINOR(unit); 672 make_dev(&sio_cdevsw, minorbase, 673 UID_ROOT, GID_WHEEL, 0600, "ttyc%r%r", adapter, 674 unit % CY_MAX_PORTS); 675 make_dev(&sio_cdevsw, minorbase | CONTROL_INIT_STATE, 676 UID_ROOT, GID_WHEEL, 0600, "ttyic%r%r", adapter, 677 unit % CY_MAX_PORTS); 678 make_dev(&sio_cdevsw, minorbase | CONTROL_LOCK_STATE, 679 UID_ROOT, GID_WHEEL, 0600, "ttylc%r%r", adapter, 680 unit % CY_MAX_PORTS); 681 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK, 682 UID_UUCP, GID_DIALER, 0660, "cuac%r%r", adapter, 683 unit % CY_MAX_PORTS); 684 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK | CONTROL_INIT_STATE, 685 UID_UUCP, GID_DIALER, 0660, "cuaic%r%r", adapter, 686 unit % CY_MAX_PORTS); 687 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK | CONTROL_LOCK_STATE, 688 UID_UUCP, GID_DIALER, 0660, "cualc%r%r", adapter, 689 unit % CY_MAX_PORTS); 690 } 691 } 692 693 /* ensure an edge for the next interrupt */ 694 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 695 696 return (com_addr(adapter * CY_MAX_PORTS)); 697} 698 699static int 700sioopen(dev, flag, mode, td) 701 dev_t dev; 702 int flag; 703 int mode; 704 struct thread *td; 705{ 706 struct com_s *com; 707 int error; 708 int mynor; 709 int s; 710 struct tty *tp; 711 int unit; 712 713 mynor = minor(dev); 714 unit = MINOR_TO_UNIT(mynor); 715 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) 716 return (ENXIO); 717 if (mynor & CONTROL_MASK) 718 return (0); 719 tp = dev->si_tty = com->tp = ttymalloc(com->tp); 720 s = spltty(); 721 /* 722 * We jump to this label after all non-interrupted sleeps to pick 723 * up any changes of the device state. 724 */ 725open_top: 726 while (com->state & CS_DTR_OFF) { 727 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0); 728 if (error != 0) 729 goto out; 730 } 731 if (tp->t_state & TS_ISOPEN) { 732 /* 733 * The device is open, so everything has been initialized. 734 * Handle conflicts. 735 */ 736 if (mynor & CALLOUT_MASK) { 737 if (!com->active_out) { 738 error = EBUSY; 739 goto out; 740 } 741 } else { 742 if (com->active_out) { 743 if (flag & O_NONBLOCK) { 744 error = EBUSY; 745 goto out; 746 } 747 error = tsleep(&com->active_out, 748 TTIPRI | PCATCH, "cybi", 0); 749 if (error != 0) 750 goto out; 751 goto open_top; 752 } 753 } 754 if (tp->t_state & TS_XCLUDE && 755 suser(td)) { 756 error = EBUSY; 757 goto out; 758 } 759 } else { 760 /* 761 * The device isn't open, so there are no conflicts. 762 * Initialize it. Initialization is done twice in many 763 * cases: to preempt sleeping callin opens if we are 764 * callout, and to complete a callin open after DCD rises. 765 */ 766 tp->t_oproc = comstart; 767 tp->t_stop = comstop; 768 tp->t_param = comparam; 769 tp->t_dev = dev; 770 tp->t_termios = mynor & CALLOUT_MASK 771 ? com->it_out : com->it_in; 772 773 /* Encode per-board unit in LIVR for access in intr routines. */ 774 cd_setreg(com, CD1400_LIVR, 775 (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); 776 777 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 778#if 0 779 com->poll = com->no_irq; 780 com->poll_output = com->loses_outints; 781#endif 782 ++com->wopeners; 783 error = comparam(tp, &tp->t_termios); 784 --com->wopeners; 785 if (error != 0) 786 goto out; 787#if 0 788 if (com->hasfifo) { 789 /* 790 * (Re)enable and flush fifos. 791 * 792 * Certain SMC chips cause problems if the fifos 793 * are enabled while input is ready. Turn off the 794 * fifo if necessary to clear the input. We test 795 * the input ready bit after enabling the fifos 796 * since we've already enabled them in comparam() 797 * and to handle races between enabling and fresh 798 * input. 799 */ 800 while (TRUE) { 801 outb(iobase + com_fifo, 802 FIFO_RCV_RST | FIFO_XMT_RST 803 | com->fifo_image); 804 DELAY(100); 805 if (!(inb(com->line_status_port) & LSR_RXRDY)) 806 break; 807 outb(iobase + com_fifo, 0); 808 DELAY(100); 809 (void) inb(com->data_port); 810 } 811 } 812 813 critical_enter(); 814 COM_LOCK(); 815 (void) inb(com->line_status_port); 816 (void) inb(com->data_port); 817 com->prev_modem_status = com->last_modem_status 818 = inb(com->modem_status_port); 819 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS 820 | IER_EMSC); 821 COM_UNLOCK(); 822 critical_exit(); 823#else /* !0 */ 824 /* 825 * Flush fifos. This requires a full channel reset which 826 * also disables the transmitter and receiver. Recover 827 * from this. 828 */ 829 cd1400_channel_cmd(com, 830 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); 831 cd1400_channel_cmd(com, com->channel_control); 832 833 critical_enter(); 834 COM_LOCK(); 835 com->prev_modem_status = com->last_modem_status 836 = cd_getreg(com, CD1400_MSVR2); 837 cd_setreg(com, CD1400_SRER, 838 com->intr_enable 839 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 840 COM_UNLOCK(); 841 critical_exit(); 842#endif /* 0 */ 843 /* 844 * Handle initial DCD. Callout devices get a fake initial 845 * DCD (trapdoor DCD). If we are callout, then any sleeping 846 * callin opens get woken up and resume sleeping on "cybi" 847 * instead of "cydcd". 848 */ 849 /* 850 * XXX `mynor & CALLOUT_MASK' should be 851 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 852 * TRAPDOOR_CARRIER is the default initial state for callout 853 * devices and SOFT_CARRIER is like CLOCAL except it hides 854 * the true carrier. 855 */ 856 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 857 (*linesw[tp->t_line].l_modem)(tp, 1); 858 } 859 /* 860 * Wait for DCD if necessary. 861 */ 862 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 863 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 864 ++com->wopeners; 865 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0); 866 --com->wopeners; 867 if (error != 0) 868 goto out; 869 goto open_top; 870 } 871 error = (*linesw[tp->t_line].l_open)(dev, tp); 872 disc_optim(tp, &tp->t_termios, com); 873 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 874 com->active_out = TRUE; 875 siosettimeout(); 876out: 877 splx(s); 878 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 879 comhardclose(com); 880 return (error); 881} 882 883static int 884sioclose(dev, flag, mode, td) 885 dev_t dev; 886 int flag; 887 int mode; 888 struct thread *td; 889{ 890 struct com_s *com; 891 int mynor; 892 int s; 893 struct tty *tp; 894 895 mynor = minor(dev); 896 if (mynor & CONTROL_MASK) 897 return (0); 898 com = com_addr(MINOR_TO_UNIT(mynor)); 899 tp = com->tp; 900 s = spltty(); 901 cd_etc(com, CD1400_ETC_STOPBREAK); 902 (*linesw[tp->t_line].l_close)(tp, flag); 903 disc_optim(tp, &tp->t_termios, com); 904 comstop(tp, FREAD | FWRITE); 905 comhardclose(com); 906 ttyclose(tp); 907 siosettimeout(); 908 splx(s); 909#ifdef broken /* session holds a ref to the tty; can't deallocate */ 910 ttyfree(tp); 911 com->tp = NULL; 912#endif 913 return (0); 914} 915 916static void 917comhardclose(com) 918 struct com_s *com; 919{ 920 cy_addr iobase; 921 int s; 922 struct tty *tp; 923 int unit; 924 925 unit = com->unit; 926 iobase = com->iobase; 927 s = spltty(); 928#if 0 929 com->poll = FALSE; 930 com->poll_output = FALSE; 931#endif 932 com->do_timestamp = 0; 933#if 0 934 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 935#else 936 /* XXX */ 937 critical_enter(); 938 COM_LOCK(); 939 com->etc = ETC_NONE; 940 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); 941 COM_UNLOCK(); 942 critical_exit(); 943 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 944#endif 945 946 { 947#if 0 948 outb(iobase + com_ier, 0); 949#else 950 critical_enter(); 951 COM_LOCK(); 952 cd_setreg(com, CD1400_SRER, com->intr_enable = 0); 953 COM_UNLOCK(); 954 critical_exit(); 955#endif 956 tp = com->tp; 957 if ((tp->t_cflag & HUPCL) 958 /* 959 * XXX we will miss any carrier drop between here and the 960 * next open. Perhaps we should watch DCD even when the 961 * port is closed; it is not sufficient to check it at 962 * the next open because it might go up and down while 963 * we're not watching. 964 */ 965 || (!com->active_out 966 && !(com->prev_modem_status & MSR_DCD) 967 && !(com->it_in.c_cflag & CLOCAL)) 968 || !(tp->t_state & TS_ISOPEN)) { 969 (void)commctl(com, TIOCM_DTR, DMBIC); 970 971 /* Disable receiver (leave transmitter enabled). */ 972 com->channel_control = CD1400_CCR_CMDCHANCTL 973 | CD1400_CCR_XMTEN 974 | CD1400_CCR_RCVDIS; 975 cd1400_channel_cmd(com, com->channel_control); 976 977 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 978 timeout(siodtrwakeup, com, com->dtr_wait); 979 com->state |= CS_DTR_OFF; 980 } 981 } 982 } 983#if 0 984 if (com->hasfifo) { 985 /* 986 * Disable fifos so that they are off after controlled 987 * reboots. Some BIOSes fail to detect 16550s when the 988 * fifos are enabled. 989 */ 990 outb(iobase + com_fifo, 0); 991 } 992#endif 993 com->active_out = FALSE; 994 wakeup(&com->active_out); 995 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 996 splx(s); 997} 998 999static int 1000siowrite(dev, uio, flag) 1001 dev_t dev; 1002 struct uio *uio; 1003 int flag; 1004{ 1005 int mynor; 1006 struct tty *tp; 1007 int unit; 1008 1009 mynor = minor(dev); 1010 if (mynor & CONTROL_MASK) 1011 return (ENODEV); 1012 1013 unit = MINOR_TO_UNIT(mynor); 1014 tp = com_addr(unit)->tp; 1015 /* 1016 * (XXX) We disallow virtual consoles if the physical console is 1017 * a serial port. This is in case there is a display attached that 1018 * is not the console. In that situation we don't need/want the X 1019 * server taking over the console. 1020 */ 1021 if (constty != NULL && unit == comconsole) 1022 constty = NULL; 1023#ifdef Smarts 1024 /* XXX duplicate ttwrite(), but without so much output processing on 1025 * CR & LF chars. Hardly worth the effort, given that high-throughput 1026 * sessions are raw anyhow. 1027 */ 1028#else 1029 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1030#endif 1031} 1032 1033static void 1034siodtrwakeup(chan) 1035 void *chan; 1036{ 1037 struct com_s *com; 1038 1039 com = (struct com_s *)chan; 1040 com->state &= ~CS_DTR_OFF; 1041 wakeup(&com->dtr_wait); 1042} 1043 1044/* 1045 * This function: 1046 * a) needs to be called with COM_LOCK() held, and 1047 * b) needs to return with COM_LOCK() held. 1048 */ 1049static void 1050sioinput(com) 1051 struct com_s *com; 1052{ 1053 u_char *buf; 1054 int incc; 1055 u_char line_status; 1056 int recv_data; 1057 struct tty *tp; 1058 1059 buf = com->ibuf; 1060 tp = com->tp; 1061 if (!(tp->t_state & TS_ISOPEN)) { 1062 com_events -= (com->iptr - com->ibuf); 1063 com->iptr = com->ibuf; 1064 return; 1065 } 1066 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 1067 /* 1068 * Avoid the grotesquely inefficient lineswitch routine 1069 * (ttyinput) in "raw" mode. It usually takes about 450 1070 * instructions (that's without canonical processing or echo!). 1071 * slinput is reasonably fast (usually 40 instructions plus 1072 * call overhead). 1073 */ 1074 1075 do { 1076 /* 1077 * This may look odd, but it is using save-and-enable 1078 * semantics instead of the save-and-disable semantics 1079 * that are used everywhere else. 1080 */ 1081 COM_UNLOCK(); 1082 critical_exit(); 1083 incc = com->iptr - buf; 1084 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 1085 && (com->state & CS_RTS_IFLOW 1086 || tp->t_iflag & IXOFF) 1087 && !(tp->t_state & TS_TBLOCK)) 1088 ttyblock(tp); 1089 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 1090 += b_to_q((char *)buf, incc, &tp->t_rawq); 1091 buf += incc; 1092 tk_nin += incc; 1093 tk_rawcc += incc; 1094 tp->t_rawcc += incc; 1095 ttwakeup(tp); 1096 if (tp->t_state & TS_TTSTOP 1097 && (tp->t_iflag & IXANY 1098 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 1099 tp->t_state &= ~TS_TTSTOP; 1100 tp->t_lflag &= ~FLUSHO; 1101 comstart(tp); 1102 } 1103 critical_enter(); 1104 COM_LOCK(); 1105 } while (buf < com->iptr); 1106 } else { 1107 do { 1108 /* 1109 * This may look odd, but it is using save-and-enable 1110 * semantics instead of the save-and-disable semantics 1111 * that are used everywhere else. 1112 */ 1113 COM_UNLOCK(); 1114 critical_exit(); 1115 line_status = buf[com->ierroff]; 1116 recv_data = *buf++; 1117 if (line_status 1118 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 1119 if (line_status & LSR_BI) 1120 recv_data |= TTY_BI; 1121 if (line_status & LSR_FE) 1122 recv_data |= TTY_FE; 1123 if (line_status & LSR_OE) 1124 recv_data |= TTY_OE; 1125 if (line_status & LSR_PE) 1126 recv_data |= TTY_PE; 1127 } 1128 (*linesw[tp->t_line].l_rint)(recv_data, tp); 1129 critical_enter(); 1130 COM_LOCK(); 1131 } while (buf < com->iptr); 1132 } 1133 com_events -= (com->iptr - com->ibuf); 1134 com->iptr = com->ibuf; 1135 1136 /* 1137 * There is now room for another low-level buffer full of input, 1138 * so enable RTS if it is now disabled and there is room in the 1139 * high-level buffer. 1140 */ 1141 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) && 1142 !(tp->t_state & TS_TBLOCK)) 1143#if 0 1144 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 1145#else 1146 cd_setreg(com, com->mcr_rts_reg, 1147 com->mcr_image |= com->mcr_rts); 1148#endif 1149} 1150 1151void 1152siointr1(vcom) 1153 void *vcom; 1154{ 1155 struct com_s *basecom; 1156 int baseu; 1157 int cy_align; 1158 cy_addr cy_iobase; 1159 int cyu; 1160 cy_addr iobase; 1161 u_char status; 1162 int unit; 1163 1164 COM_LOCK(); /* XXX could this be placed down lower in the loop? */ 1165 1166 basecom = (struct com_s *)vcom; 1167 baseu = basecom->unit; 1168 cy_align = basecom->cy_align; 1169 cy_iobase = basecom->cy_iobase; 1170 unit = baseu / CY_MAX_PORTS; 1171 1172 /* check each CD1400 in turn */ 1173 for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { 1174 iobase = (cy_addr) (cy_iobase 1175 + (cy_chip_offset[cyu] << cy_align)); 1176 /* poll to see if it has any work */ 1177 status = cd_inb(iobase, CD1400_SVRR, cy_align); 1178 if (status == 0) 1179 continue; 1180#ifdef CyDebug 1181 ++cy_svrr_probes; 1182#endif 1183 /* service requests as appropriate, giving priority to RX */ 1184 if (status & CD1400_SVRR_RXRDY) { 1185 struct com_s *com; 1186 u_int count; 1187 u_char *ioptr; 1188 u_char line_status; 1189 u_char recv_data; 1190 u_char serv_type; 1191#ifdef PollMode 1192 u_char save_rir; 1193#endif 1194 1195#ifdef PollMode 1196 save_rir = cd_inb(iobase, CD1400_RIR, cy_align); 1197 1198 /* enter rx service */ 1199 cd_outb(iobase, CD1400_CAR, cy_align, save_rir); 1200 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1201 = save_rir & CD1400_CAR_CHAN; 1202 1203 serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); 1204 com = com_addr(baseu 1205 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1206 & CD1400_xIVR_CHAN)); 1207#else 1208 /* ack receive service */ 1209 serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); 1210 1211 com = com_addr(baseu + 1212 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1213 & CD1400_xIVR_CHAN)); 1214#endif 1215 1216 if (serv_type & CD1400_RIVR_EXCEPTION) { 1217 ++com->recv_exception; 1218 line_status = cd_inb(iobase, CD1400_RDSR, cy_align); 1219 /* break/unnattached error bits or real input? */ 1220 recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); 1221#ifndef SOFT_HOTCHAR 1222 if (line_status & CD1400_RDSR_SPECIAL 1223 && com->hotchar != 0) 1224 swi_sched(sio_fast_ih, 0); 1225 1226#endif 1227#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ 1228 if (line_status & (LSR_PE|LSR_FE|LSR_BI)) { 1229 /* 1230 Don't store PE if IGNPAR and BI if IGNBRK, 1231 this hack allows "raw" tty optimization 1232 works even if IGN* is set. 1233 */ 1234 if ( com->tp == NULL 1235 || !(com->tp->t_state & TS_ISOPEN) 1236 || ((line_status & (LSR_PE|LSR_FE)) 1237 && (com->tp->t_iflag & IGNPAR)) 1238 || ((line_status & LSR_BI) 1239 && (com->tp->t_iflag & IGNBRK))) 1240 goto cont; 1241 if ( (line_status & (LSR_PE|LSR_FE)) 1242 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) 1243 && ((line_status & LSR_FE) 1244 || ((line_status & LSR_PE) 1245 && (com->tp->t_iflag & INPCK)))) 1246 recv_data = 0; 1247 } 1248#endif /* 1 */ 1249 ++com->bytes_in; 1250#ifdef SOFT_HOTCHAR 1251 if (com->hotchar != 0 && recv_data == com->hotchar) 1252 swi_sched(sio_fast_ih, 0); 1253#endif 1254 ioptr = com->iptr; 1255 if (ioptr >= com->ibufend) 1256 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1257 else { 1258 if (com->do_timestamp) 1259 microtime(&com->timestamp); 1260 ++com_events; 1261 ioptr[0] = recv_data; 1262 ioptr[com->ierroff] = line_status; 1263 com->iptr = ++ioptr; 1264 if (ioptr == com->ihighwater 1265 && com->state & CS_RTS_IFLOW) 1266#if 0 1267 outb(com->modem_ctl_port, 1268 com->mcr_image &= ~MCR_RTS); 1269#else 1270 cd_outb(iobase, com->mcr_rts_reg, 1271 cy_align, 1272 com->mcr_image &= 1273 ~com->mcr_rts); 1274#endif 1275 if (line_status & LSR_OE) 1276 CE_RECORD(com, CE_OVERRUN); 1277 } 1278 goto cont; 1279 } else { 1280 int ifree; 1281 1282 count = cd_inb(iobase, CD1400_RDCR, cy_align); 1283 if (!count) 1284 goto cont; 1285 com->bytes_in += count; 1286 ioptr = com->iptr; 1287 ifree = com->ibufend - ioptr; 1288 if (count > ifree) { 1289 count -= ifree; 1290 com_events += ifree; 1291 if (ifree != 0) { 1292 if (com->do_timestamp) 1293 microtime(&com->timestamp); 1294 do { 1295 recv_data = cd_inb(iobase, 1296 CD1400_RDSR, 1297 cy_align); 1298#ifdef SOFT_HOTCHAR 1299 if (com->hotchar != 0 1300 && recv_data 1301 == com->hotchar) 1302 swi_sched(sio_fast_ih, 1303 0); 1304#endif 1305 ioptr[0] = recv_data; 1306 ioptr[com->ierroff] = 0; 1307 ++ioptr; 1308 } while (--ifree != 0); 1309 } 1310 com->delta_error_counts 1311 [CE_INTERRUPT_BUF_OVERFLOW] += count; 1312 do { 1313 recv_data = cd_inb(iobase, CD1400_RDSR, 1314 cy_align); 1315#ifdef SOFT_HOTCHAR 1316 if (com->hotchar != 0 1317 && recv_data == com->hotchar) 1318 swi_sched(sio_fast_ih, 0); 1319#endif 1320 } while (--count != 0); 1321 } else { 1322 if (com->do_timestamp) 1323 microtime(&com->timestamp); 1324 if (ioptr <= com->ihighwater 1325 && ioptr + count > com->ihighwater 1326 && com->state & CS_RTS_IFLOW) 1327#if 0 1328 outb(com->modem_ctl_port, 1329 com->mcr_image &= ~MCR_RTS); 1330#else 1331 cd_outb(iobase, com->mcr_rts_reg, 1332 cy_align, 1333 com->mcr_image 1334 &= ~com->mcr_rts); 1335#endif 1336 com_events += count; 1337 do { 1338 recv_data = cd_inb(iobase, CD1400_RDSR, 1339 cy_align); 1340#ifdef SOFT_HOTCHAR 1341 if (com->hotchar != 0 1342 && recv_data == com->hotchar) 1343 swi_sched(sio_fast_ih, 0); 1344#endif 1345 ioptr[0] = recv_data; 1346 ioptr[com->ierroff] = 0; 1347 ++ioptr; 1348 } while (--count != 0); 1349 } 1350 com->iptr = ioptr; 1351 } 1352cont: 1353 1354 /* terminate service context */ 1355#ifdef PollMode 1356 cd_outb(iobase, CD1400_RIR, cy_align, 1357 save_rir 1358 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); 1359#else 1360 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1361#endif 1362 } 1363 if (status & CD1400_SVRR_MDMCH) { 1364 struct com_s *com; 1365 u_char modem_status; 1366#ifdef PollMode 1367 u_char save_mir; 1368#else 1369 u_char vector; 1370#endif 1371 1372#ifdef PollMode 1373 save_mir = cd_inb(iobase, CD1400_MIR, cy_align); 1374 1375 /* enter modem service */ 1376 cd_outb(iobase, CD1400_CAR, cy_align, save_mir); 1377 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1378 = save_mir & CD1400_CAR_CHAN; 1379 1380 com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS 1381 + (save_mir & CD1400_MIR_CHAN)); 1382#else 1383 /* ack modem service */ 1384 vector = cy_inb(iobase, CY8_SVCACKM, cy_align); 1385 1386 com = com_addr(baseu 1387 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1388 & CD1400_xIVR_CHAN)); 1389#endif 1390 ++com->mdm; 1391 modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align); 1392 if (modem_status != com->last_modem_status) { 1393 if (com->do_dcd_timestamp 1394 && !(com->last_modem_status & MSR_DCD) 1395 && modem_status & MSR_DCD) 1396 microtime(&com->dcd_timestamp); 1397 1398 /* 1399 * Schedule high level to handle DCD changes. Note 1400 * that we don't use the delta bits anywhere. Some 1401 * UARTs mess them up, and it's easy to remember the 1402 * previous bits and calculate the delta. 1403 */ 1404 com->last_modem_status = modem_status; 1405 if (!(com->state & CS_CHECKMSR)) { 1406 com_events += LOTS_OF_EVENTS; 1407 com->state |= CS_CHECKMSR; 1408 swi_sched(sio_fast_ih, 0); 1409 } 1410 1411#ifdef SOFT_CTS_OFLOW 1412 /* handle CTS change immediately for crisp flow ctl */ 1413 if (com->state & CS_CTS_OFLOW) { 1414 if (modem_status & MSR_CTS) { 1415 com->state |= CS_ODEVREADY; 1416 if (com->state >= (CS_BUSY | CS_TTGO 1417 | CS_ODEVREADY) 1418 && !(com->intr_enable 1419 & CD1400_SRER_TXRDY)) 1420 cd_outb(iobase, CD1400_SRER, 1421 cy_align, 1422 com->intr_enable 1423 = com->intr_enable 1424 & ~CD1400_SRER_TXMPTY 1425 | CD1400_SRER_TXRDY); 1426 } else { 1427 com->state &= ~CS_ODEVREADY; 1428 if (com->intr_enable 1429 & CD1400_SRER_TXRDY) 1430 cd_outb(iobase, CD1400_SRER, 1431 cy_align, 1432 com->intr_enable 1433 = com->intr_enable 1434 & ~CD1400_SRER_TXRDY 1435 | CD1400_SRER_TXMPTY); 1436 } 1437 } 1438#endif 1439 } 1440 1441 /* terminate service context */ 1442#ifdef PollMode 1443 cd_outb(iobase, CD1400_MIR, cy_align, 1444 save_mir 1445 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); 1446#else 1447 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1448#endif 1449 } 1450 if (status & CD1400_SVRR_TXRDY) { 1451 struct com_s *com; 1452#ifdef PollMode 1453 u_char save_tir; 1454#else 1455 u_char vector; 1456#endif 1457 1458#ifdef PollMode 1459 save_tir = cd_inb(iobase, CD1400_TIR, cy_align); 1460 1461 /* enter tx service */ 1462 cd_outb(iobase, CD1400_CAR, cy_align, save_tir); 1463 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1464 = save_tir & CD1400_CAR_CHAN; 1465 1466 com = com_addr(baseu 1467 + cyu * CD1400_NO_OF_CHANNELS 1468 + (save_tir & CD1400_TIR_CHAN)); 1469#else 1470 /* ack transmit service */ 1471 vector = cy_inb(iobase, CY8_SVCACKT, cy_align); 1472 1473 com = com_addr(baseu 1474 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1475 & CD1400_xIVR_CHAN)); 1476#endif 1477 1478 if (com->etc != ETC_NONE) { 1479 if (com->intr_enable & CD1400_SRER_TXRDY) { 1480 /* 1481 * Here due to sloppy SRER_TXRDY 1482 * enabling. Ignore. Come back when 1483 * tx is empty. 1484 */ 1485 cd_outb(iobase, CD1400_SRER, cy_align, 1486 com->intr_enable 1487 = (com->intr_enable 1488 & ~CD1400_SRER_TXRDY) 1489 | CD1400_SRER_TXMPTY); 1490 goto terminate_tx_service; 1491 } 1492 switch (com->etc) { 1493 case CD1400_ETC_SENDBREAK: 1494 case CD1400_ETC_STOPBREAK: 1495 /* 1496 * Start the command. Come back on 1497 * next tx empty interrupt, hopefully 1498 * after command has been executed. 1499 */ 1500 cd_outb(iobase, CD1400_COR2, cy_align, 1501 com->cor[1] |= CD1400_COR2_ETC); 1502 cd_outb(iobase, CD1400_TDR, cy_align, 1503 CD1400_ETC_CMD); 1504 cd_outb(iobase, CD1400_TDR, cy_align, 1505 com->etc); 1506 if (com->etc == CD1400_ETC_SENDBREAK) 1507 com->etc = ETC_BREAK_STARTING; 1508 else 1509 com->etc = ETC_BREAK_ENDING; 1510 goto terminate_tx_service; 1511 case ETC_BREAK_STARTING: 1512 /* 1513 * BREAK is now on. Continue with 1514 * SRER_TXMPTY processing, hopefully 1515 * don't come back. 1516 */ 1517 com->etc = ETC_BREAK_STARTED; 1518 break; 1519 case ETC_BREAK_STARTED: 1520 /* 1521 * Came back due to sloppy SRER_TXMPTY 1522 * enabling. Hope again. 1523 */ 1524 break; 1525 case ETC_BREAK_ENDING: 1526 /* 1527 * BREAK is now off. Continue with 1528 * SRER_TXMPTY processing and don't 1529 * come back. The SWI handler will 1530 * restart tx interrupts if necessary. 1531 */ 1532 cd_outb(iobase, CD1400_COR2, cy_align, 1533 com->cor[1] 1534 &= ~CD1400_COR2_ETC); 1535 com->etc = ETC_BREAK_ENDED; 1536 if (!(com->state & CS_ODONE)) { 1537 com_events += LOTS_OF_EVENTS; 1538 com->state |= CS_ODONE; 1539 swi_sched(sio_fast_ih, 0); 1540 } 1541 break; 1542 case ETC_BREAK_ENDED: 1543 /* 1544 * Shouldn't get here. Hope again. 1545 */ 1546 break; 1547 } 1548 } 1549 if (com->intr_enable & CD1400_SRER_TXMPTY) { 1550 if (!(com->extra_state & CSE_ODONE)) { 1551 com_events += LOTS_OF_EVENTS; 1552 com->extra_state |= CSE_ODONE; 1553 swi_sched(sio_fast_ih, 0); 1554 } 1555 cd_outb(iobase, CD1400_SRER, cy_align, 1556 com->intr_enable 1557 &= ~CD1400_SRER_TXMPTY); 1558 goto terminate_tx_service; 1559 } 1560 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1561 u_char *ioptr; 1562 u_int ocount; 1563 1564 ioptr = com->obufq.l_head; 1565 ocount = com->obufq.l_tail - ioptr; 1566 if (ocount > CD1400_TX_FIFO_SIZE) 1567 ocount = CD1400_TX_FIFO_SIZE; 1568 com->bytes_out += ocount; 1569 do 1570 cd_outb(iobase, CD1400_TDR, cy_align, 1571 *ioptr++); 1572 while (--ocount != 0); 1573 com->obufq.l_head = ioptr; 1574 if (ioptr >= com->obufq.l_tail) { 1575 struct lbq *qp; 1576 1577 qp = com->obufq.l_next; 1578 qp->l_queued = FALSE; 1579 qp = qp->l_next; 1580 if (qp != NULL) { 1581 com->obufq.l_head = qp->l_head; 1582 com->obufq.l_tail = qp->l_tail; 1583 com->obufq.l_next = qp; 1584 } else { 1585 /* output just completed */ 1586 com->state &= ~CS_BUSY; 1587 1588 /* 1589 * The setting of CSE_ODONE may be 1590 * stale here. We currently only 1591 * use it when CS_BUSY is set, and 1592 * fixing it when we clear CS_BUSY 1593 * is easiest. 1594 */ 1595 if (com->extra_state & CSE_ODONE) { 1596 com_events -= LOTS_OF_EVENTS; 1597 com->extra_state &= ~CSE_ODONE; 1598 } 1599 1600 cd_outb(iobase, CD1400_SRER, cy_align, 1601 com->intr_enable 1602 = (com->intr_enable 1603 & ~CD1400_SRER_TXRDY) 1604 | CD1400_SRER_TXMPTY); 1605 } 1606 if (!(com->state & CS_ODONE)) { 1607 com_events += LOTS_OF_EVENTS; 1608 com->state |= CS_ODONE; 1609 1610 /* handle at high level ASAP */ 1611 swi_sched(sio_fast_ih, 0); 1612 } 1613 } 1614 } 1615 1616 /* terminate service context */ 1617terminate_tx_service: 1618#ifdef PollMode 1619 cd_outb(iobase, CD1400_TIR, cy_align, 1620 save_tir 1621 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); 1622#else 1623 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1624#endif 1625 } 1626 } 1627 1628 /* ensure an edge for the next interrupt */ 1629 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 1630 1631 swi_sched(sio_slow_ih, SWI_DELAY); 1632 1633 COM_UNLOCK(); 1634} 1635 1636static int 1637sioioctl(dev, cmd, data, flag, td) 1638 dev_t dev; 1639 u_long cmd; 1640 caddr_t data; 1641 int flag; 1642 struct thread *td; 1643{ 1644 struct com_s *com; 1645 int error; 1646 int mynor; 1647 int s; 1648 struct tty *tp; 1649#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1650 int oldcmd; 1651 struct termios term; 1652#endif 1653 1654 mynor = minor(dev); 1655 com = com_addr(MINOR_TO_UNIT(mynor)); 1656 if (mynor & CONTROL_MASK) { 1657 struct termios *ct; 1658 1659 switch (mynor & CONTROL_MASK) { 1660 case CONTROL_INIT_STATE: 1661 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 1662 break; 1663 case CONTROL_LOCK_STATE: 1664 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 1665 break; 1666 default: 1667 return (ENODEV); /* /dev/nodev */ 1668 } 1669 switch (cmd) { 1670 case TIOCSETA: 1671 error = suser(td); 1672 if (error != 0) 1673 return (error); 1674 *ct = *(struct termios *)data; 1675 return (0); 1676 case TIOCGETA: 1677 *(struct termios *)data = *ct; 1678 return (0); 1679 case TIOCGETD: 1680 *(int *)data = TTYDISC; 1681 return (0); 1682 case TIOCGWINSZ: 1683 bzero(data, sizeof(struct winsize)); 1684 return (0); 1685 default: 1686 return (ENOTTY); 1687 } 1688 } 1689 tp = com->tp; 1690#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1691 term = tp->t_termios; 1692 oldcmd = cmd; 1693 error = ttsetcompat(tp, &cmd, data, &term); 1694 if (error != 0) 1695 return (error); 1696 if (cmd != oldcmd) 1697 data = (caddr_t)&term; 1698#endif 1699 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1700 int cc; 1701 struct termios *dt = (struct termios *)data; 1702 struct termios *lt = mynor & CALLOUT_MASK 1703 ? &com->lt_out : &com->lt_in; 1704 1705 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1706 | (dt->c_iflag & ~lt->c_iflag); 1707 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1708 | (dt->c_oflag & ~lt->c_oflag); 1709 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1710 | (dt->c_cflag & ~lt->c_cflag); 1711 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1712 | (dt->c_lflag & ~lt->c_lflag); 1713 for (cc = 0; cc < NCCS; ++cc) 1714 if (lt->c_cc[cc] != 0) 1715 dt->c_cc[cc] = tp->t_cc[cc]; 1716 if (lt->c_ispeed != 0) 1717 dt->c_ispeed = tp->t_ispeed; 1718 if (lt->c_ospeed != 0) 1719 dt->c_ospeed = tp->t_ospeed; 1720 } 1721 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); 1722 if (error != ENOIOCTL) 1723 return (error); 1724 s = spltty(); 1725 error = ttioctl(tp, cmd, data, flag); 1726 disc_optim(tp, &tp->t_termios, com); 1727 if (error != ENOIOCTL) { 1728 splx(s); 1729 return (error); 1730 } 1731 switch (cmd) { 1732 case TIOCSBRK: 1733#if 0 1734 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 1735#else 1736 cd_etc(com, CD1400_ETC_SENDBREAK); 1737#endif 1738 break; 1739 case TIOCCBRK: 1740#if 0 1741 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1742#else 1743 cd_etc(com, CD1400_ETC_STOPBREAK); 1744#endif 1745 break; 1746 case TIOCSDTR: 1747 (void)commctl(com, TIOCM_DTR, DMBIS); 1748 break; 1749 case TIOCCDTR: 1750 (void)commctl(com, TIOCM_DTR, DMBIC); 1751 break; 1752 /* 1753 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 1754 * changes get undone on the next call to comparam(). 1755 */ 1756 case TIOCMSET: 1757 (void)commctl(com, *(int *)data, DMSET); 1758 break; 1759 case TIOCMBIS: 1760 (void)commctl(com, *(int *)data, DMBIS); 1761 break; 1762 case TIOCMBIC: 1763 (void)commctl(com, *(int *)data, DMBIC); 1764 break; 1765 case TIOCMGET: 1766 *(int *)data = commctl(com, 0, DMGET); 1767 break; 1768 case TIOCMSDTRWAIT: 1769 /* must be root since the wait applies to following logins */ 1770 error = suser(td); 1771 if (error != 0) { 1772 splx(s); 1773 return (error); 1774 } 1775 com->dtr_wait = *(int *)data * hz / 100; 1776 break; 1777 case TIOCMGDTRWAIT: 1778 *(int *)data = com->dtr_wait * 100 / hz; 1779 break; 1780 case TIOCTIMESTAMP: 1781 com->do_timestamp = TRUE; 1782 *(struct timeval *)data = com->timestamp; 1783 break; 1784 case TIOCDCDTIMESTAMP: 1785 com->do_dcd_timestamp = TRUE; 1786 *(struct timeval *)data = com->dcd_timestamp; 1787 break; 1788 default: 1789 splx(s); 1790 return (ENOTTY); 1791 } 1792 splx(s); 1793 return (0); 1794} 1795 1796static void 1797siopoll(void *arg) 1798{ 1799 int unit; 1800 1801#ifdef CyDebug 1802 ++cy_timeouts; 1803#endif 1804 if (com_events == 0) 1805 return; 1806repeat: 1807 for (unit = 0; unit < NSIO; ++unit) { 1808 struct com_s *com; 1809 int incc; 1810 struct tty *tp; 1811 1812 com = com_addr(unit); 1813 if (com == NULL) 1814 continue; 1815 tp = com->tp; 1816 if (tp == NULL) { 1817 /* 1818 * XXX forget any events related to closed devices 1819 * (actually never opened devices) so that we don't 1820 * loop. 1821 */ 1822 critical_enter(); 1823 COM_LOCK(); 1824 incc = com->iptr - com->ibuf; 1825 com->iptr = com->ibuf; 1826 if (com->state & CS_CHECKMSR) { 1827 incc += LOTS_OF_EVENTS; 1828 com->state &= ~CS_CHECKMSR; 1829 } 1830 com_events -= incc; 1831 COM_UNLOCK(); 1832 critical_exit(); 1833 if (incc != 0) 1834 log(LOG_DEBUG, 1835 "sio%d: %d events for device with no tp\n", 1836 unit, incc); 1837 continue; 1838 } 1839 if (com->iptr != com->ibuf) { 1840 critical_enter(); 1841 COM_LOCK(); 1842 sioinput(com); 1843 COM_UNLOCK(); 1844 critical_exit(); 1845 } 1846 if (com->state & CS_CHECKMSR) { 1847 u_char delta_modem_status; 1848 1849 critical_enter(); 1850 COM_LOCK(); 1851 sioinput(com); 1852 delta_modem_status = com->last_modem_status 1853 ^ com->prev_modem_status; 1854 com->prev_modem_status = com->last_modem_status; 1855 com_events -= LOTS_OF_EVENTS; 1856 com->state &= ~CS_CHECKMSR; 1857 COM_UNLOCK(); 1858 critical_exit(); 1859 if (delta_modem_status & MSR_DCD) 1860 (*linesw[tp->t_line].l_modem) 1861 (tp, com->prev_modem_status & MSR_DCD); 1862 } 1863 if (com->extra_state & CSE_ODONE) { 1864 critical_enter(); 1865 COM_LOCK(); 1866 com_events -= LOTS_OF_EVENTS; 1867 com->extra_state &= ~CSE_ODONE; 1868 COM_UNLOCK(); 1869 critical_exit(); 1870 if (!(com->state & CS_BUSY)) { 1871 tp->t_state &= ~TS_BUSY; 1872 ttwwakeup(com->tp); 1873 } 1874 if (com->etc != ETC_NONE) { 1875 if (com->etc == ETC_BREAK_ENDED) 1876 com->etc = ETC_NONE; 1877 wakeup(&com->etc); 1878 } 1879 } 1880 if (com->state & CS_ODONE) { 1881 critical_enter(); 1882 COM_LOCK(); 1883 com_events -= LOTS_OF_EVENTS; 1884 com->state &= ~CS_ODONE; 1885 COM_UNLOCK(); 1886 critical_exit(); 1887 (*linesw[tp->t_line].l_start)(tp); 1888 } 1889 if (com_events == 0) 1890 break; 1891 } 1892 if (com_events >= LOTS_OF_EVENTS) 1893 goto repeat; 1894} 1895 1896static int 1897comparam(tp, t) 1898 struct tty *tp; 1899 struct termios *t; 1900{ 1901 int bits; 1902 int cflag; 1903 struct com_s *com; 1904 u_char cor_change; 1905 u_long cy_clock; 1906 int idivisor; 1907 int iflag; 1908 int iprescaler; 1909 int itimeout; 1910 int odivisor; 1911 int oprescaler; 1912 u_char opt; 1913 int s; 1914 int unit; 1915 1916 unit = DEV_TO_UNIT(tp->t_dev); 1917 com = com_addr(unit); 1918 1919 /* check requested parameters */ 1920 cy_clock = CY_CLOCK(com->gfrcr_image); 1921 idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler); 1922 if (idivisor <= 0) 1923 return (EINVAL); 1924 odivisor = comspeed(t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed, 1925 cy_clock, &oprescaler); 1926 if (odivisor <= 0) 1927 return (EINVAL); 1928 1929 /* parameters are OK, convert them to the com struct and the device */ 1930 s = spltty(); 1931 if (t->c_ospeed == 0) 1932 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 1933 else 1934 (void)commctl(com, TIOCM_DTR, DMBIS); 1935 1936 (void) siosetwater(com, t->c_ispeed); 1937 1938 /* XXX we don't actually change the speed atomically. */ 1939 1940 cd_setreg(com, CD1400_RBPR, idivisor); 1941 cd_setreg(com, CD1400_RCOR, iprescaler); 1942 cd_setreg(com, CD1400_TBPR, odivisor); 1943 cd_setreg(com, CD1400_TCOR, oprescaler); 1944 1945 /* 1946 * channel control 1947 * receiver enable 1948 * transmitter enable (always set) 1949 */ 1950 cflag = t->c_cflag; 1951 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 1952 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 1953 if (opt != com->channel_control) { 1954 com->channel_control = opt; 1955 cd1400_channel_cmd(com, opt); 1956 } 1957 1958#ifdef Smarts 1959 /* set special chars */ 1960 /* XXX if one is _POSIX_VDISABLE, can't use some others */ 1961 if (t->c_cc[VSTOP] != _POSIX_VDISABLE) 1962 cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); 1963 if (t->c_cc[VSTART] != _POSIX_VDISABLE) 1964 cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); 1965 if (t->c_cc[VINTR] != _POSIX_VDISABLE) 1966 cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); 1967 if (t->c_cc[VSUSP] != _POSIX_VDISABLE) 1968 cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); 1969#endif 1970 1971 /* 1972 * set channel option register 1 - 1973 * parity mode 1974 * stop bits 1975 * char length 1976 */ 1977 opt = 0; 1978 /* parity */ 1979 if (cflag & PARENB) { 1980 if (cflag & PARODD) 1981 opt |= CD1400_COR1_PARODD; 1982 opt |= CD1400_COR1_PARNORMAL; 1983 } 1984 iflag = t->c_iflag; 1985 if (!(iflag & INPCK)) 1986 opt |= CD1400_COR1_NOINPCK; 1987 bits = 1 + 1; 1988 /* stop bits */ 1989 if (cflag & CSTOPB) { 1990 ++bits; 1991 opt |= CD1400_COR1_STOP2; 1992 } 1993 /* char length */ 1994 switch (cflag & CSIZE) { 1995 case CS5: 1996 bits += 5; 1997 opt |= CD1400_COR1_CS5; 1998 break; 1999 case CS6: 2000 bits += 6; 2001 opt |= CD1400_COR1_CS6; 2002 break; 2003 case CS7: 2004 bits += 7; 2005 opt |= CD1400_COR1_CS7; 2006 break; 2007 default: 2008 bits += 8; 2009 opt |= CD1400_COR1_CS8; 2010 break; 2011 } 2012 cor_change = 0; 2013 if (opt != com->cor[0]) { 2014 cor_change |= CD1400_CCR_COR1; 2015 cd_setreg(com, CD1400_COR1, com->cor[0] = opt); 2016 } 2017 2018 /* 2019 * Set receive time-out period, normally to max(one char time, 5 ms). 2020 */ 2021 itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; 2022#ifdef SOFT_HOTCHAR 2023#define MIN_RTP 1 2024#else 2025#define MIN_RTP 5 2026#endif 2027 if (itimeout < MIN_RTP) 2028 itimeout = MIN_RTP; 2029 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 2030 && t->c_cc[VTIME] * 10 > itimeout) 2031 itimeout = t->c_cc[VTIME] * 10; 2032 if (itimeout > 255) 2033 itimeout = 255; 2034 cd_setreg(com, CD1400_RTPR, itimeout); 2035 2036 /* 2037 * set channel option register 2 - 2038 * flow control 2039 */ 2040 opt = 0; 2041#ifdef Smarts 2042 if (iflag & IXANY) 2043 opt |= CD1400_COR2_IXANY; 2044 if (iflag & IXOFF) 2045 opt |= CD1400_COR2_IXOFF; 2046#endif 2047#ifndef SOFT_CTS_OFLOW 2048 if (cflag & CCTS_OFLOW) 2049 opt |= CD1400_COR2_CCTS_OFLOW; 2050#endif 2051 critical_enter(); 2052 COM_LOCK(); 2053 if (opt != com->cor[1]) { 2054 cor_change |= CD1400_CCR_COR2; 2055 cd_setreg(com, CD1400_COR2, com->cor[1] = opt); 2056 } 2057 COM_UNLOCK(); 2058 critical_exit(); 2059 2060 /* 2061 * set channel option register 3 - 2062 * receiver FIFO interrupt threshold 2063 * flow control 2064 */ 2065 opt = RxFifoThreshold; 2066#ifdef Smarts 2067 if (t->c_lflag & ICANON) 2068 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 2069 if (iflag & IXOFF) 2070 /* detect and transparently handle START and STOP chars */ 2071 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 2072#endif 2073 if (opt != com->cor[2]) { 2074 cor_change |= CD1400_CCR_COR3; 2075 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2076 } 2077 2078 /* notify the CD1400 if COR1-3 have changed */ 2079 if (cor_change) 2080 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); 2081 2082 /* 2083 * set channel option register 4 - 2084 * CR/NL processing 2085 * break processing 2086 * received exception processing 2087 */ 2088 opt = 0; 2089 if (iflag & IGNCR) 2090 opt |= CD1400_COR4_IGNCR; 2091#ifdef Smarts 2092 /* 2093 * we need a new ttyinput() for this, as we don't want to 2094 * have ICRNL && INLCR being done in both layers, or to have 2095 * synchronisation problems 2096 */ 2097 if (iflag & ICRNL) 2098 opt |= CD1400_COR4_ICRNL; 2099 if (iflag & INLCR) 2100 opt |= CD1400_COR4_INLCR; 2101#endif 2102 if (iflag & IGNBRK) 2103 opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; 2104 /* 2105 * The `-ignbrk -brkint parmrk' case is not handled by the hardware, 2106 * so only tell the hardware about -brkint if -parmrk. 2107 */ 2108 if (!(iflag & (BRKINT | PARMRK))) 2109 opt |= CD1400_COR4_NOBRKINT; 2110#if 0 2111 /* XXX using this "intelligence" breaks reporting of overruns. */ 2112 if (iflag & IGNPAR) 2113 opt |= CD1400_COR4_PFO_DISCARD; 2114 else { 2115 if (iflag & PARMRK) 2116 opt |= CD1400_COR4_PFO_ESC; 2117 else 2118 opt |= CD1400_COR4_PFO_NUL; 2119 } 2120#else 2121 opt |= CD1400_COR4_PFO_EXCEPTION; 2122#endif 2123 cd_setreg(com, CD1400_COR4, opt); 2124 2125 /* 2126 * set channel option register 5 - 2127 */ 2128 opt = 0; 2129 if (iflag & ISTRIP) 2130 opt |= CD1400_COR5_ISTRIP; 2131 if (t->c_iflag & IEXTEN) 2132 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 2133 opt |= CD1400_COR5_LNEXT; 2134#ifdef Smarts 2135 if (t->c_oflag & ONLCR) 2136 opt |= CD1400_COR5_ONLCR; 2137 if (t->c_oflag & OCRNL) 2138 opt |= CD1400_COR5_OCRNL; 2139#endif 2140 cd_setreg(com, CD1400_COR5, opt); 2141 2142 /* 2143 * We always generate modem status change interrupts for CD changes. 2144 * Among other things, this is necessary to track TS_CARR_ON for 2145 * pstat to print even when the driver doesn't care. CD changes 2146 * should be rare so interrupts for them are not worth extra code to 2147 * avoid. We avoid interrupts for other modem status changes (except 2148 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is 2149 * simplest and best. 2150 */ 2151 2152 /* 2153 * set modem change option register 1 2154 * generate modem interrupts on which 1 -> 0 input transitions 2155 * also controls auto-DTR output flow-control, which we don't use 2156 */ 2157 opt = CD1400_MCOR1_CDzd; 2158#ifdef SOFT_CTS_OFLOW 2159 if (cflag & CCTS_OFLOW) 2160 opt |= CD1400_MCOR1_CTSzd; 2161#endif 2162 cd_setreg(com, CD1400_MCOR1, opt); 2163 2164 /* 2165 * set modem change option register 2 2166 * generate modem interrupts on specific 0 -> 1 input transitions 2167 */ 2168 opt = CD1400_MCOR2_CDod; 2169#ifdef SOFT_CTS_OFLOW 2170 if (cflag & CCTS_OFLOW) 2171 opt |= CD1400_MCOR2_CTSod; 2172#endif 2173 cd_setreg(com, CD1400_MCOR2, opt); 2174 2175 /* 2176 * XXX should have done this long ago, but there is too much state 2177 * to change all atomically. 2178 */ 2179 critical_enter(); 2180 COM_LOCK(); 2181 2182 com->state &= ~CS_TTGO; 2183 if (!(tp->t_state & TS_TTSTOP)) 2184 com->state |= CS_TTGO; 2185 if (cflag & CRTS_IFLOW) { 2186 com->state |= CS_RTS_IFLOW; 2187 /* 2188 * If CS_RTS_IFLOW just changed from off to on, the change 2189 * needs to be propagated to MCR_RTS. This isn't urgent, 2190 * so do it later by calling comstart() instead of repeating 2191 * a lot of code from comstart() here. 2192 */ 2193 } else if (com->state & CS_RTS_IFLOW) { 2194 com->state &= ~CS_RTS_IFLOW; 2195 /* 2196 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2197 * on here, since comstart() won't do it later. 2198 */ 2199#if 0 2200 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2201#else 2202 cd_setreg(com, com->mcr_rts_reg, 2203 com->mcr_image |= com->mcr_rts); 2204#endif 2205 } 2206 2207 /* 2208 * Set up state to handle output flow control. 2209 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2210 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2211 */ 2212 com->state |= CS_ODEVREADY; 2213#ifdef SOFT_CTS_OFLOW 2214 com->state &= ~CS_CTS_OFLOW; 2215 if (cflag & CCTS_OFLOW) { 2216 com->state |= CS_CTS_OFLOW; 2217 if (!(com->last_modem_status & MSR_CTS)) 2218 com->state &= ~CS_ODEVREADY; 2219 } 2220#endif 2221 /* XXX shouldn't call functions while intrs are disabled. */ 2222 disc_optim(tp, t, com); 2223#if 0 2224 /* 2225 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2226 * unconditionally, but that defeated the careful discarding of 2227 * stale input in sioopen(). 2228 */ 2229 if (com->state >= (CS_BUSY | CS_TTGO)) 2230 siointr1(com); 2231#endif 2232 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2233 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 2234 cd_setreg(com, CD1400_SRER, 2235 com->intr_enable 2236 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2237 | CD1400_SRER_TXRDY); 2238 } else { 2239 if (com->intr_enable & CD1400_SRER_TXRDY) 2240 cd_setreg(com, CD1400_SRER, 2241 com->intr_enable 2242 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2243 | CD1400_SRER_TXMPTY); 2244 } 2245 2246 COM_UNLOCK(); 2247 critical_exit(); 2248 splx(s); 2249 comstart(tp); 2250 if (com->ibufold != NULL) { 2251 free(com->ibufold, M_DEVBUF); 2252 com->ibufold = NULL; 2253 } 2254 return (0); 2255} 2256 2257static int 2258siosetwater(com, speed) 2259 struct com_s *com; 2260 speed_t speed; 2261{ 2262 int cp4ticks; 2263 u_char *ibuf; 2264 int ibufsize; 2265 struct tty *tp; 2266 2267 /* 2268 * Make the buffer size large enough to handle a softtty interrupt 2269 * latency of about 2 ticks without loss of throughput or data 2270 * (about 3 ticks if input flow control is not used or not honoured, 2271 * but a bit less for CS5-CS7 modes). 2272 */ 2273 cp4ticks = speed / 10 / hz * 4; 2274 for (ibufsize = 128; ibufsize < cp4ticks;) 2275 ibufsize <<= 1; 2276 if (ibufsize == com->ibufsize) { 2277 return (0); 2278 } 2279 2280 /* 2281 * Allocate input buffer. The extra factor of 2 in the size is 2282 * to allow for an error byte for each input byte. 2283 */ 2284 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 2285 if (ibuf == NULL) { 2286 return (ENOMEM); 2287 } 2288 2289 /* Initialize non-critical variables. */ 2290 com->ibufold = com->ibuf; 2291 com->ibufsize = ibufsize; 2292 tp = com->tp; 2293 if (tp != NULL) { 2294 tp->t_ififosize = 2 * ibufsize; 2295 tp->t_ispeedwat = (speed_t)-1; 2296 tp->t_ospeedwat = (speed_t)-1; 2297 } 2298 2299 /* 2300 * Read current input buffer, if any. Continue with interrupts 2301 * disabled. 2302 */ 2303 critical_enter(); 2304 COM_LOCK(); 2305 if (com->iptr != com->ibuf) 2306 sioinput(com); 2307 2308 /*- 2309 * Initialize critical variables, including input buffer watermarks. 2310 * The external device is asked to stop sending when the buffer 2311 * exactly reaches high water, or when the high level requests it. 2312 * The high level is notified immediately (rather than at a later 2313 * clock tick) when this watermark is reached. 2314 * The buffer size is chosen so the watermark should almost never 2315 * be reached. 2316 * The low watermark is invisibly 0 since the buffer is always 2317 * emptied all at once. 2318 */ 2319 com->iptr = com->ibuf = ibuf; 2320 com->ibufend = ibuf + ibufsize; 2321 com->ierroff = ibufsize; 2322 com->ihighwater = ibuf + 3 * ibufsize / 4; 2323 2324 COM_UNLOCK(); 2325 critical_exit(); 2326 return (0); 2327} 2328 2329static void 2330comstart(tp) 2331 struct tty *tp; 2332{ 2333 struct com_s *com; 2334 int s; 2335#ifdef CyDebug 2336 bool_t started; 2337#endif 2338 int unit; 2339 2340 unit = DEV_TO_UNIT(tp->t_dev); 2341 com = com_addr(unit); 2342 s = spltty(); 2343 2344#ifdef CyDebug 2345 ++com->start_count; 2346 started = FALSE; 2347#endif 2348 2349 critical_enter(); 2350 COM_LOCK(); 2351 if (tp->t_state & TS_TTSTOP) { 2352 com->state &= ~CS_TTGO; 2353 if (com->intr_enable & CD1400_SRER_TXRDY) 2354 cd_setreg(com, CD1400_SRER, 2355 com->intr_enable 2356 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2357 | CD1400_SRER_TXMPTY); 2358 } else { 2359 com->state |= CS_TTGO; 2360 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2361 && !(com->intr_enable & CD1400_SRER_TXRDY)) 2362 cd_setreg(com, CD1400_SRER, 2363 com->intr_enable 2364 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2365 | CD1400_SRER_TXRDY); 2366 } 2367 if (tp->t_state & TS_TBLOCK) { 2368 if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) 2369#if 0 2370 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2371#else 2372 cd_setreg(com, com->mcr_rts_reg, 2373 com->mcr_image &= ~com->mcr_rts); 2374#endif 2375 } else { 2376 if (!(com->mcr_image & com->mcr_rts) 2377 && com->iptr < com->ihighwater 2378 && com->state & CS_RTS_IFLOW) 2379#if 0 2380 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2381#else 2382 cd_setreg(com, com->mcr_rts_reg, 2383 com->mcr_image |= com->mcr_rts); 2384#endif 2385 } 2386 COM_UNLOCK(); 2387 critical_exit(); 2388 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2389 ttwwakeup(tp); 2390 splx(s); 2391 return; 2392 } 2393 if (tp->t_outq.c_cc != 0) { 2394 struct lbq *qp; 2395 struct lbq *next; 2396 2397 if (!com->obufs[0].l_queued) { 2398#ifdef CyDebug 2399 started = TRUE; 2400#endif 2401 com->obufs[0].l_tail 2402 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2403 sizeof com->obuf1); 2404 com->obufs[0].l_next = NULL; 2405 com->obufs[0].l_queued = TRUE; 2406 critical_enter(); 2407 COM_LOCK(); 2408 if (com->state & CS_BUSY) { 2409 qp = com->obufq.l_next; 2410 while ((next = qp->l_next) != NULL) 2411 qp = next; 2412 qp->l_next = &com->obufs[0]; 2413 } else { 2414 com->obufq.l_head = com->obufs[0].l_head; 2415 com->obufq.l_tail = com->obufs[0].l_tail; 2416 com->obufq.l_next = &com->obufs[0]; 2417 com->state |= CS_BUSY; 2418 if (com->state >= (CS_BUSY | CS_TTGO 2419 | CS_ODEVREADY)) 2420 cd_setreg(com, CD1400_SRER, 2421 com->intr_enable 2422 = (com->intr_enable 2423 & ~CD1400_SRER_TXMPTY) 2424 | CD1400_SRER_TXRDY); 2425 } 2426 COM_UNLOCK(); 2427 critical_exit(); 2428 } 2429 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2430#ifdef CyDebug 2431 started = TRUE; 2432#endif 2433 com->obufs[1].l_tail 2434 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2435 sizeof com->obuf2); 2436 com->obufs[1].l_next = NULL; 2437 com->obufs[1].l_queued = TRUE; 2438 critical_enter(); 2439 COM_LOCK(); 2440 if (com->state & CS_BUSY) { 2441 qp = com->obufq.l_next; 2442 while ((next = qp->l_next) != NULL) 2443 qp = next; 2444 qp->l_next = &com->obufs[1]; 2445 } else { 2446 com->obufq.l_head = com->obufs[1].l_head; 2447 com->obufq.l_tail = com->obufs[1].l_tail; 2448 com->obufq.l_next = &com->obufs[1]; 2449 com->state |= CS_BUSY; 2450 if (com->state >= (CS_BUSY | CS_TTGO 2451 | CS_ODEVREADY)) 2452 cd_setreg(com, CD1400_SRER, 2453 com->intr_enable 2454 = (com->intr_enable 2455 & ~CD1400_SRER_TXMPTY) 2456 | CD1400_SRER_TXRDY); 2457 } 2458 COM_UNLOCK(); 2459 critical_exit(); 2460 } 2461 tp->t_state |= TS_BUSY; 2462 } 2463#ifdef CyDebug 2464 if (started) 2465 ++com->start_real; 2466#endif 2467#if 0 2468 critical_enter(); 2469 COM_LOCK(); 2470 if (com->state >= (CS_BUSY | CS_TTGO)) 2471 siointr1(com); /* fake interrupt to start output */ 2472 COM_UNLOCK(); 2473 critical_exit(); 2474#endif 2475 ttwwakeup(tp); 2476 splx(s); 2477} 2478 2479static void 2480comstop(tp, rw) 2481 struct tty *tp; 2482 int rw; 2483{ 2484 struct com_s *com; 2485 bool_t wakeup_etc; 2486 2487 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2488 wakeup_etc = FALSE; 2489 critical_enter(); 2490 COM_LOCK(); 2491 if (rw & FWRITE) { 2492 com->obufs[0].l_queued = FALSE; 2493 com->obufs[1].l_queued = FALSE; 2494 if (com->extra_state & CSE_ODONE) { 2495 com_events -= LOTS_OF_EVENTS; 2496 com->extra_state &= ~CSE_ODONE; 2497 if (com->etc != ETC_NONE) { 2498 if (com->etc == ETC_BREAK_ENDED) 2499 com->etc = ETC_NONE; 2500 wakeup_etc = TRUE; 2501 } 2502 } 2503 com->tp->t_state &= ~TS_BUSY; 2504 if (com->state & CS_ODONE) 2505 com_events -= LOTS_OF_EVENTS; 2506 com->state &= ~(CS_ODONE | CS_BUSY); 2507 } 2508 if (rw & FREAD) { 2509 /* XXX no way to reset only input fifo. */ 2510 com_events -= (com->iptr - com->ibuf); 2511 com->iptr = com->ibuf; 2512 } 2513 COM_UNLOCK(); 2514 critical_exit(); 2515 if (wakeup_etc) 2516 wakeup(&com->etc); 2517 if (rw & FWRITE && com->etc == ETC_NONE) 2518 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 2519 comstart(tp); 2520} 2521 2522static int 2523commctl(com, bits, how) 2524 struct com_s *com; 2525 int bits; 2526 int how; 2527{ 2528 int mcr; 2529 int msr; 2530 2531 if (how == DMGET) { 2532 if (com->channel_control & CD1400_CCR_RCVEN) 2533 bits |= TIOCM_LE; 2534 mcr = com->mcr_image; 2535 if (mcr & com->mcr_dtr) 2536 bits |= TIOCM_DTR; 2537 if (mcr & com->mcr_rts) 2538 /* XXX wired on for Cyclom-8Ys */ 2539 bits |= TIOCM_RTS; 2540 2541 /* 2542 * We must read the modem status from the hardware because 2543 * we don't generate modem status change interrupts for all 2544 * changes, so com->prev_modem_status is not guaranteed to 2545 * be up to date. This is safe, unlike for sio, because 2546 * reading the status register doesn't clear pending modem 2547 * status change interrupts. 2548 */ 2549 msr = cd_getreg(com, CD1400_MSVR2); 2550 2551 if (msr & MSR_CTS) 2552 bits |= TIOCM_CTS; 2553 if (msr & MSR_DCD) 2554 bits |= TIOCM_CD; 2555 if (msr & MSR_DSR) 2556 bits |= TIOCM_DSR; 2557 if (msr & MSR_RI) 2558 /* XXX not connected except for Cyclom-16Y? */ 2559 bits |= TIOCM_RI; 2560 return (bits); 2561 } 2562 mcr = 0; 2563 if (bits & TIOCM_DTR) 2564 mcr |= com->mcr_dtr; 2565 if (bits & TIOCM_RTS) 2566 mcr |= com->mcr_rts; 2567 critical_enter(); 2568 COM_LOCK(); 2569 switch (how) { 2570 case DMSET: 2571 com->mcr_image = mcr; 2572 cd_setreg(com, CD1400_MSVR1, mcr); 2573 cd_setreg(com, CD1400_MSVR2, mcr); 2574 break; 2575 case DMBIS: 2576 com->mcr_image = mcr = com->mcr_image | mcr; 2577 cd_setreg(com, CD1400_MSVR1, mcr); 2578 cd_setreg(com, CD1400_MSVR2, mcr); 2579 break; 2580 case DMBIC: 2581 com->mcr_image = mcr = com->mcr_image & ~mcr; 2582 cd_setreg(com, CD1400_MSVR1, mcr); 2583 cd_setreg(com, CD1400_MSVR2, mcr); 2584 break; 2585 } 2586 COM_UNLOCK(); 2587 critical_exit(); 2588 return (0); 2589} 2590 2591static void 2592siosettimeout() 2593{ 2594 struct com_s *com; 2595 bool_t someopen; 2596 int unit; 2597 2598 /* 2599 * Set our timeout period to 1 second if no polled devices are open. 2600 * Otherwise set it to max(1/200, 1/hz). 2601 * Enable timeouts iff some device is open. 2602 */ 2603 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2604 sio_timeout = hz; 2605 someopen = FALSE; 2606 for (unit = 0; unit < NSIO; ++unit) { 2607 com = com_addr(unit); 2608 if (com != NULL && com->tp != NULL 2609 && com->tp->t_state & TS_ISOPEN) { 2610 someopen = TRUE; 2611#if 0 2612 if (com->poll || com->poll_output) { 2613 sio_timeout = hz > 200 ? hz / 200 : 1; 2614 break; 2615 } 2616#endif 2617 } 2618 } 2619 if (someopen) { 2620 sio_timeouts_until_log = hz / sio_timeout; 2621 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 2622 sio_timeout); 2623 } else { 2624 /* Flush error messages, if any. */ 2625 sio_timeouts_until_log = 1; 2626 comwakeup((void *)NULL); 2627 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2628 } 2629} 2630 2631static void 2632comwakeup(chan) 2633 void *chan; 2634{ 2635 struct com_s *com; 2636 int unit; 2637 2638 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 2639 2640#if 0 2641 /* 2642 * Recover from lost output interrupts. 2643 * Poll any lines that don't use interrupts. 2644 */ 2645 for (unit = 0; unit < NSIO; ++unit) { 2646 com = com_addr(unit); 2647 if (com != NULL 2648 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2649 critical_enter(); 2650 COM_LOCK(); 2651 siointr1(com); 2652 COM_UNLOCK(); 2653 critical_exit(); 2654 } 2655 } 2656#endif 2657 2658 /* 2659 * Check for and log errors, but not too often. 2660 */ 2661 if (--sio_timeouts_until_log > 0) 2662 return; 2663 sio_timeouts_until_log = hz / sio_timeout; 2664 for (unit = 0; unit < NSIO; ++unit) { 2665 int errnum; 2666 2667 com = com_addr(unit); 2668 if (com == NULL) 2669 continue; 2670 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2671 u_int delta; 2672 u_long total; 2673 2674 critical_enter(); 2675 COM_LOCK(); 2676 delta = com->delta_error_counts[errnum]; 2677 com->delta_error_counts[errnum] = 0; 2678 COM_UNLOCK(); 2679 critical_exit(); 2680 if (delta == 0) 2681 continue; 2682 total = com->error_counts[errnum] += delta; 2683 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 2684 unit, delta, error_desc[errnum], 2685 delta == 1 ? "" : "s", total); 2686 } 2687 } 2688} 2689 2690static void 2691disc_optim(tp, t, com) 2692 struct tty *tp; 2693 struct termios *t; 2694 struct com_s *com; 2695{ 2696#ifndef SOFT_HOTCHAR 2697 u_char opt; 2698#endif 2699 2700 /* 2701 * XXX can skip a lot more cases if Smarts. Maybe 2702 * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we 2703 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. 2704 */ 2705 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 2706 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2707 && (!(t->c_iflag & PARMRK) 2708 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 2709 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 2710 && linesw[tp->t_line].l_rint == ttyinput) 2711 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2712 else 2713 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2714 com->hotchar = linesw[tp->t_line].l_hotchar; 2715#ifndef SOFT_HOTCHAR 2716 opt = com->cor[2] & ~CD1400_COR3_SCD34; 2717 if (com->hotchar != 0) { 2718 cd_setreg(com, CD1400_SCHR3, com->hotchar); 2719 cd_setreg(com, CD1400_SCHR4, com->hotchar); 2720 opt |= CD1400_COR3_SCD34; 2721 } 2722 if (opt != com->cor[2]) { 2723 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2724 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 2725 } 2726#endif 2727} 2728 2729#ifdef Smarts 2730/* standard line discipline input routine */ 2731int 2732cyinput(c, tp) 2733 int c; 2734 struct tty *tp; 2735{ 2736 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 2737 * bits, as they are done by the CD1400. Hardly worth the effort, 2738 * given that high-throughput sessions are raw anyhow. 2739 */ 2740} 2741#endif /* Smarts */ 2742 2743static int 2744comspeed(speed, cy_clock, prescaler_io) 2745 speed_t speed; 2746 u_long cy_clock; 2747 int *prescaler_io; 2748{ 2749 int actual; 2750 int error; 2751 int divider; 2752 int prescaler; 2753 int prescaler_unit; 2754 2755 if (speed == 0) 2756 return (0); 2757 if (speed < 0 || speed > 150000) 2758 return (-1); 2759 2760 /* determine which prescaler to use */ 2761 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2762 prescaler_unit--, prescaler >>= 2) { 2763 if (cy_clock / prescaler / speed > 63) 2764 break; 2765 } 2766 2767 divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ 2768 if (divider > 255) 2769 divider = 255; 2770 actual = cy_clock/prescaler/divider; 2771 2772 /* 10 times error in percent: */ 2773 error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; 2774 2775 /* 3.0% max error tolerance */ 2776 if (error < -30 || error > 30) 2777 return (-1); 2778 2779#if 0 2780 printf("prescaler = %d (%d)\n", prescaler, prescaler_unit); 2781 printf("divider = %d (%x)\n", divider, divider); 2782 printf("actual = %d\n", actual); 2783 printf("error = %d\n", error); 2784#endif 2785 2786 *prescaler_io = prescaler_unit; 2787 return (divider); 2788} 2789 2790static void 2791cd1400_channel_cmd(com, cmd) 2792 struct com_s *com; 2793 int cmd; 2794{ 2795 cd1400_channel_cmd_wait(com); 2796 cd_setreg(com, CD1400_CCR, cmd); 2797 cd1400_channel_cmd_wait(com); 2798} 2799 2800static void 2801cd1400_channel_cmd_wait(com) 2802 struct com_s *com; 2803{ 2804 struct timeval start; 2805 struct timeval tv; 2806 long usec; 2807 2808 if (cd_getreg(com, CD1400_CCR) == 0) 2809 return; 2810 microtime(&start); 2811 for (;;) { 2812 if (cd_getreg(com, CD1400_CCR) == 0) 2813 return; 2814 microtime(&tv); 2815 usec = 1000000 * (tv.tv_sec - start.tv_sec) + 2816 tv.tv_usec - start.tv_usec; 2817 if (usec >= 5000) { 2818 log(LOG_ERR, 2819 "cy%d: channel command timeout (%ld usec)\n", 2820 com->unit, usec); 2821 return; 2822 } 2823 } 2824} 2825 2826static void 2827cd_etc(com, etc) 2828 struct com_s *com; 2829 int etc; 2830{ 2831 2832 /* 2833 * We can't change the hardware's ETC state while there are any 2834 * characters in the tx fifo, since those characters would be 2835 * interpreted as commands! Unputting characters from the fifo 2836 * is difficult, so we wait up to 12 character times for the fifo 2837 * to drain. The command will be delayed for up to 2 character 2838 * times for the tx to become empty. Unputting characters from 2839 * the tx holding and shift registers is impossible, so we wait 2840 * for the tx to become empty so that the command is sure to be 2841 * executed soon after we issue it. 2842 */ 2843 critical_enter(); 2844 COM_LOCK(); 2845 if (com->etc == etc) 2846 goto wait; 2847 if ((etc == CD1400_ETC_SENDBREAK 2848 && (com->etc == ETC_BREAK_STARTING 2849 || com->etc == ETC_BREAK_STARTED)) 2850 || (etc == CD1400_ETC_STOPBREAK 2851 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED 2852 || com->etc == ETC_NONE))) { 2853 COM_UNLOCK(); 2854 critical_exit(); 2855 return; 2856 } 2857 com->etc = etc; 2858 cd_setreg(com, CD1400_SRER, 2859 com->intr_enable 2860 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); 2861wait: 2862 COM_UNLOCK(); 2863 critical_exit(); 2864 while (com->etc == etc 2865 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) 2866 continue; 2867} 2868 2869static int 2870cd_getreg(com, reg) 2871 struct com_s *com; 2872 int reg; 2873{ 2874 struct com_s *basecom; 2875 u_char car; 2876 int cy_align; 2877 register_t eflags; 2878 cy_addr iobase; 2879#ifdef SMP 2880 int need_unlock; 2881#endif 2882 int val; 2883 2884 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2885 car = com->unit & CD1400_CAR_CHAN; 2886 cy_align = com->cy_align; 2887 iobase = com->iobase; 2888 eflags = read_eflags(); 2889 critical_enter(); 2890#ifdef SMP 2891 need_unlock = 0; 2892 if (!mtx_owned(&sio_lock)) { 2893 COM_LOCK(); 2894 need_unlock = 1; 2895 } 2896#endif 2897 if (basecom->car != car) 2898 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2899 val = cd_inb(iobase, reg, cy_align); 2900#ifdef SMP 2901 if (need_unlock) 2902 COM_UNLOCK(); 2903#endif 2904 critical_exit(); 2905 return (val); 2906} 2907 2908static void 2909cd_setreg(com, reg, val) 2910 struct com_s *com; 2911 int reg; 2912 int val; 2913{ 2914 struct com_s *basecom; 2915 u_char car; 2916 int cy_align; 2917 register_t eflags; 2918 cy_addr iobase; 2919#ifdef SMP 2920 int need_unlock; 2921#endif 2922 2923 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2924 car = com->unit & CD1400_CAR_CHAN; 2925 cy_align = com->cy_align; 2926 iobase = com->iobase; 2927 eflags = read_eflags(); 2928 critical_enter(); 2929#ifdef SMP 2930 need_unlock = 0; 2931 if (!mtx_owned(&sio_lock)) { 2932 COM_LOCK(); 2933 need_unlock = 1; 2934 } 2935#endif 2936 if (basecom->car != car) 2937 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2938 cd_outb(iobase, reg, cy_align, val); 2939#ifdef SMP 2940 if (need_unlock) 2941 COM_UNLOCK(); 2942#endif 2943 critical_exit(); 2944} 2945 2946#ifdef CyDebug 2947/* useful in ddb */ 2948void 2949cystatus(unit) 2950 int unit; 2951{ 2952 struct com_s *com; 2953 cy_addr iobase; 2954 u_int ocount; 2955 struct tty *tp; 2956 2957 com = com_addr(unit); 2958 printf("info for channel %d\n", unit); 2959 printf("------------------\n"); 2960 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2961 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2962 if (com == NULL) 2963 return; 2964 iobase = com->iobase; 2965 printf("\n"); 2966 printf("cd1400 base address:\\tt%p\n", iobase); 2967 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2968 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2969 com->cor[0], com->cor[1], com->cor[2]); 2970 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2971 cd_getreg(com, CD1400_SRER), com->intr_enable); 2972 printf("service request register:\t0x%02x\n", 2973 cd_inb(iobase, CD1400_SVRR, com->cy_align)); 2974 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2975 cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); 2976 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2977 cd_inb(iobase, CD1400_RIR, com->cy_align), 2978 cd_inb(iobase, CD1400_TIR, com->cy_align), 2979 cd_inb(iobase, CD1400_MIR, com->cy_align)); 2980 printf("\n"); 2981 printf("com state:\t\t\t0x%02x\n", com->state); 2982 printf("calls to comstart():\t\t%d (%d useful)\n", 2983 com->start_count, com->start_real); 2984 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2985 ocount = 0; 2986 if (com->obufs[0].l_queued) 2987 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2988 if (com->obufs[1].l_queued) 2989 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2990 printf("tx buffer chars:\t\t%u\n", ocount); 2991 printf("received chars:\t\t\t%d\n", com->bytes_in); 2992 printf("received exceptions:\t\t%d\n", com->recv_exception); 2993 printf("modem signal deltas:\t\t%d\n", com->mdm); 2994 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2995 printf("\n"); 2996 tp = com->tp; 2997 if (tp != NULL) { 2998 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2999 printf( 3000 "upper layer queue lengths:\t%d raw, %d canon, %d output\n", 3001 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 3002 } else 3003 printf("tty state:\t\t\tclosed\n"); 3004} 3005#endif /* CyDebug */ 3006