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