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