1/*- 2 * cyclades cyclom-y serial driver 3 * Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 * Copyright (c) 1993 Andrew Herbert. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name Andrew Herbert may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED 22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 24 * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD$"); 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/serial.h> 81#include <sys/syslog.h> 82#include <sys/tty.h> 83 84#include <machine/psl.h> 85 86#include <dev/ic/cd1400.h> 87 88#include <dev/cy/cyreg.h> 89#include <dev/cy/cyvar.h> 90 91#define NCY 10 /* KLUDGE */ 92 93#define NPORTS (NCY * CY_MAX_PORTS) 94 95#define CY_MAX_PORTS (CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s) 96 97/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ 98#define CD1400_xIVR_CHAN_SHIFT 3 99#define CD1400_xIVR_CHAN 0x1F 100 101/* 102 * ETC states. com->etc may also contain a hardware ETC command value, 103 * meaning that execution of that command is pending. 104 */ 105#define ETC_NONE 0 /* we depend on bzero() setting this */ 106#define ETC_BREAK_STARTING 1 107#define ETC_BREAK_STARTED 2 108#define ETC_BREAK_ENDING 3 109#define ETC_BREAK_ENDED 4 110 111#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 112 113/* 114 * com state bits. 115 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 116 * than the other bits so that they can be tested as a group without masking 117 * off the low bits. 118 * 119 * The following com and tty flags correspond closely: 120 * CS_BUSY = TS_BUSY (maintained by cystart(), cypoll() and 121 * comstop()) 122 * CS_TTGO = ~TS_TTSTOP (maintained by cyparam() and cystart()) 123 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by cyparam()) 124 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by cyparam()) 125 * TS_FLUSH is not used. 126 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 127 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 128 */ 129#define CS_BUSY 0x80 /* output in progress */ 130#define CS_TTGO 0x40 /* output not stopped by XOFF */ 131#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 132#define CS_CHECKMSR 1 /* check of MSR scheduled */ 133#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 134#define CS_ODONE 4 /* output completed */ 135#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 136#define CSE_ODONE 1 /* output transmitted */ 137 138static char const * const error_desc[] = { 139#define CE_OVERRUN 0 140 "silo overflow", 141#define CE_INTERRUPT_BUF_OVERFLOW 1 142 "interrupt-level buffer overflow", 143#define CE_TTY_BUF_OVERFLOW 2 144 "tty-level buffer overflow", 145}; 146 147#define CE_NTYPES 3 148#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 149 150#ifdef SMP 151#define COM_LOCK() mtx_lock_spin(&cy_lock) 152#define COM_UNLOCK() mtx_unlock_spin(&cy_lock) 153#else 154#define COM_LOCK() 155#define COM_UNLOCK() 156#endif 157 158/* types. XXX - should be elsewhere */ 159typedef u_char bool_t; /* boolean */ 160 161/* queue of linear buffers */ 162struct lbq { 163 u_char *l_head; /* next char to process */ 164 u_char *l_tail; /* one past the last char to process */ 165 struct lbq *l_next; /* next in queue */ 166 bool_t l_queued; /* nonzero if queued */ 167}; 168 169/* com device structure */ 170struct com_s { 171 u_char state; /* miscellaneous flag bits */ 172 u_char etc; /* pending Embedded Transmit Command */ 173 u_char extra_state; /* more flag bits, separate for order trick */ 174 u_char gfrcr_image; /* copy of value read from GFRCR */ 175 u_char mcr_dtr; /* MCR bit that is wired to DTR */ 176 u_char mcr_image; /* copy of value written to MCR */ 177 u_char mcr_rts; /* MCR bit that is wired to RTS */ 178 int unit; /* unit number */ 179 180 /* 181 * The high level of the driver never reads status registers directly 182 * because there would be too many side effects to handle conveniently. 183 * Instead, it reads copies of the registers stored here by the 184 * interrupt handler. 185 */ 186 u_char last_modem_status; /* last MSR read by intr handler */ 187 u_char prev_modem_status; /* last MSR handled by high level */ 188 189 u_char *ibuf; /* start of input buffer */ 190 u_char *ibufend; /* end of input buffer */ 191 u_char *ibufold; /* old input buffer, to be freed */ 192 u_char *ihighwater; /* threshold in input buffer */ 193 u_char *iptr; /* next free spot in input buffer */ 194 int ibufsize; /* size of ibuf (not include error bytes) */ 195 int ierroff; /* offset of error bytes in ibuf */ 196 197 struct lbq obufq; /* head of queue of output buffers */ 198 struct lbq obufs[2]; /* output buffers */ 199 200 int cy_align; /* index for register alignment */ 201 cy_addr cy_iobase; /* base address of this port's cyclom */ 202 cy_addr iobase; /* base address of this port's cd1400 */ 203 int mcr_rts_reg; /* cd1400 reg number of reg holding mcr_rts */ 204 205 struct tty *tp; /* cross reference */ 206 207 u_long bytes_in; /* statistics */ 208 u_long bytes_out; 209 u_int delta_error_counts[CE_NTYPES]; 210 u_long error_counts[CE_NTYPES]; 211 212 u_int recv_exception; /* exception chars received */ 213 u_int mdm; /* modem signal changes */ 214#ifdef CyDebug 215 u_int start_count; /* no. of calls to cystart() */ 216 u_int start_real; /* no. of calls that did something */ 217#endif 218 u_char car; /* CD1400 CAR shadow (if first unit in cd) */ 219 u_char channel_control;/* CD1400 CCR control command shadow */ 220 u_char cor[3]; /* CD1400 COR1-3 shadows */ 221 u_char intr_enable; /* CD1400 SRER shadow */ 222 223 /* 224 * Data area for output buffers. Someday we should build the output 225 * buffer queue without copying data. 226 */ 227 u_char obuf1[256]; 228 u_char obuf2[256]; 229}; 230 231devclass_t cy_devclass; 232char cy_driver_name[] = "cy"; 233 234static void cd1400_channel_cmd(struct com_s *com, int cmd); 235static void cd1400_channel_cmd_wait(struct com_s *com); 236static void cd_etc(struct com_s *com, int etc); 237static int cd_getreg(struct com_s *com, int reg); 238static void cd_setreg(struct com_s *com, int reg, int val); 239static void cyinput(struct com_s *com); 240static int cyparam(struct tty *tp, struct termios *t); 241static void cypoll(void *arg); 242static void cysettimeout(void); 243static int cysetwater(struct com_s *com, speed_t speed); 244static int cyspeed(speed_t speed, u_long cy_clock, int *prescaler_io); 245static void cystart(struct tty *tp); 246static void comstop(struct tty *tp, int rw); 247static timeout_t cywakeup; 248static void disc_optim(struct tty *tp, struct termios *t, 249 struct com_s *com); 250 251static t_break_t cybreak; 252static t_modem_t cymodem; 253static t_open_t cyopen; 254static t_close_t cyclose; 255 256#ifdef CyDebug 257void cystatus(int unit); 258#endif 259 260static struct mtx cy_lock; 261static int cy_inited; 262 263/* table and macro for fast conversion from a unit number to its com struct */ 264static struct com_s *p_cy_addr[NPORTS]; 265#define cy_addr(unit) (p_cy_addr[unit]) 266 267static u_int cy_events; /* input chars + weighted output completions */ 268static void *cy_fast_ih; 269static void *cy_slow_ih; 270static int cy_timeout; 271static int cy_timeouts_until_log; 272static struct callout_handle cy_timeout_handle 273 = CALLOUT_HANDLE_INITIALIZER(&cy_timeout_handle); 274 275#ifdef CyDebug 276static u_int cd_inbs; 277static u_int cy_inbs; 278static u_int cd_outbs; 279static u_int cy_outbs; 280static u_int cy_svrr_probes; 281static u_int cy_timeouts; 282#endif 283 284static int cy_chip_offset[] = { 285 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00, 286}; 287static int cy_nr_cd1400s[NCY]; 288static int cy_total_devices; 289#undef RxFifoThreshold 290static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); 291 292int 293cy_units(cy_addr cy_iobase, int cy_align) 294{ 295 int cyu; 296 u_char firmware_version; 297 int i; 298 cy_addr iobase; 299 300 for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { 301 iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align); 302 303 /* wait for chip to become ready for new command */ 304 for (i = 0; i < 10; i++) { 305 DELAY(50); 306 if (!cd_inb(iobase, CD1400_CCR, cy_align)) 307 break; 308 } 309 310 /* clear the GFRCR register */ 311 cd_outb(iobase, CD1400_GFRCR, cy_align, 0); 312 313 /* issue a reset command */ 314 cd_outb(iobase, CD1400_CCR, cy_align, 315 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 316 317 /* XXX bogus initialization to avoid a gcc bug/warning. */ 318 firmware_version = 0; 319 320 /* wait for the CD1400 to initialize itself */ 321 for (i = 0; i < 200; i++) { 322 DELAY(50); 323 324 /* retrieve firmware version */ 325 firmware_version = cd_inb(iobase, CD1400_GFRCR, 326 cy_align); 327 if ((firmware_version & 0xf0) == 0x40) 328 break; 329 } 330 331 /* 332 * Anything in the 0x40-0x4F range is fine. 333 * If one CD1400 is bad then we don't support higher 334 * numbered good ones on this board. 335 */ 336 if ((firmware_version & 0xf0) != 0x40) 337 break; 338 } 339 return (cyu); 340} 341 342void * 343cyattach_common(cy_addr cy_iobase, int cy_align) 344{ 345 int adapter; 346 int cyu; 347 u_char firmware_version; 348 cy_addr iobase; 349 int ncyu; 350 int unit; 351 struct tty *tp; 352 353 while (cy_inited != 2) 354 if (atomic_cmpset_int(&cy_inited, 0, 1)) { 355 mtx_init(&cy_lock, cy_driver_name, NULL, MTX_SPIN); 356 atomic_store_rel_int(&cy_inited, 2); 357 } 358 359 adapter = cy_total_devices; 360 if ((u_int)adapter >= NCY) { 361 printf( 362 "cy%d: can't attach adapter: insufficient cy devices configured\n", 363 adapter); 364 return (NULL); 365 } 366 ncyu = cy_units(cy_iobase, cy_align); 367 if (ncyu == 0) 368 return (NULL); 369 cy_nr_cd1400s[adapter] = ncyu; 370 cy_total_devices++; 371 372 unit = adapter * CY_MAX_PORTS; 373 for (cyu = 0; cyu < ncyu; ++cyu) { 374 int cdu; 375 376 iobase = (cy_addr) (cy_iobase 377 + (cy_chip_offset[cyu] << cy_align)); 378 firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); 379 380 /* Set up a receive timeout period of than 1+ ms. */ 381 cd_outb(iobase, CD1400_PPR, cy_align, 382 howmany(CY_CLOCK(firmware_version) 383 / CD1400_PPR_PRESCALER, 1000)); 384 385 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { 386 struct com_s *com; 387 int s; 388 389 com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT | M_ZERO); 390 if (com == NULL) 391 break; 392 com->unit = unit; 393 com->gfrcr_image = firmware_version; 394 if (CY_RTS_DTR_SWAPPED(firmware_version)) { 395 com->mcr_dtr = CD1400_MSVR1_RTS; 396 com->mcr_rts = CD1400_MSVR2_DTR; 397 com->mcr_rts_reg = CD1400_MSVR2; 398 } else { 399 com->mcr_dtr = CD1400_MSVR2_DTR; 400 com->mcr_rts = CD1400_MSVR1_RTS; 401 com->mcr_rts_reg = CD1400_MSVR1; 402 } 403 com->obufs[0].l_head = com->obuf1; 404 com->obufs[1].l_head = com->obuf2; 405 406 com->cy_align = cy_align; 407 com->cy_iobase = cy_iobase; 408 com->iobase = iobase; 409 com->car = ~CD1400_CAR_CHAN; 410 411 tp = com->tp = ttyalloc(); 412 tp->t_open = cyopen; 413 tp->t_close = cyclose; 414 tp->t_oproc = cystart; 415 tp->t_stop = comstop; 416 tp->t_param = cyparam; 417 tp->t_break = cybreak; 418 tp->t_modem = cymodem; 419 tp->t_sc = com; 420 421 if (cysetwater(com, tp->t_init_in.c_ispeed) != 0) { 422 free(com, M_DEVBUF); 423 return (NULL); 424 } 425 426 s = spltty(); 427 cy_addr(unit) = com; 428 splx(s); 429 430 if (cy_fast_ih == NULL) { 431 swi_add(&tty_intr_event, "cy", cypoll, NULL, SWI_TTY, 0, 432 &cy_fast_ih); 433 swi_add(&clk_intr_event, "cy", cypoll, NULL, SWI_CLOCK, 0, 434 &cy_slow_ih); 435 } 436 ttycreate(tp, TS_CALLOUT, "c%r%r", 437 adapter, unit % CY_MAX_PORTS); 438 } 439 } 440 441 /* ensure an edge for the next interrupt */ 442 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 443 444 return (cy_addr(adapter * CY_MAX_PORTS)); 445} 446 447static int 448cyopen(struct tty *tp, struct cdev *dev) 449{ 450 struct com_s *com; 451 int s; 452 453 com = tp->t_sc; 454 s = spltty(); 455 /* 456 * We jump to this label after all non-interrupted sleeps to pick 457 * up any changes of the device state. 458 */ 459 460 /* Encode per-board unit in LIVR for access in intr routines. */ 461 cd_setreg(com, CD1400_LIVR, 462 (com->unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); 463 464 /* 465 * Flush fifos. This requires a full channel reset which 466 * also disables the transmitter and receiver. Recover 467 * from this. 468 */ 469 cd1400_channel_cmd(com, 470 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); 471 cd1400_channel_cmd(com, com->channel_control); 472 473 critical_enter(); 474 COM_LOCK(); 475 com->prev_modem_status = com->last_modem_status 476 = cd_getreg(com, CD1400_MSVR2); 477 cd_setreg(com, CD1400_SRER, 478 com->intr_enable 479 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 480 COM_UNLOCK(); 481 critical_exit(); 482 cysettimeout(); 483 return (0); 484} 485 486 487static void 488cyclose(struct tty *tp) 489{ 490 cy_addr iobase; 491 struct com_s *com; 492 int s; 493 int unit; 494 495 com = tp->t_sc; 496 unit = com->unit; 497 iobase = com->iobase; 498 s = spltty(); 499 /* XXX */ 500 critical_enter(); 501 COM_LOCK(); 502 com->etc = ETC_NONE; 503 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); 504 COM_UNLOCK(); 505 critical_exit(); 506 cd_etc(com, CD1400_ETC_STOPBREAK); 507 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 508 509 { 510 critical_enter(); 511 COM_LOCK(); 512 cd_setreg(com, CD1400_SRER, com->intr_enable = 0); 513 COM_UNLOCK(); 514 critical_exit(); 515 tp = com->tp; 516 if ((tp->t_cflag & HUPCL) 517 /* 518 * XXX we will miss any carrier drop between here and the 519 * next open. Perhaps we should watch DCD even when the 520 * port is closed; it is not sufficient to check it at 521 * the next open because it might go up and down while 522 * we're not watching. 523 */ 524 || (!tp->t_actout 525 && !(com->prev_modem_status & CD1400_MSVR2_CD) 526 && !(tp->t_init_in.c_cflag & CLOCAL)) 527 || !(tp->t_state & TS_ISOPEN)) { 528 (void)cymodem(tp, 0, SER_DTR); 529 530 /* Disable receiver (leave transmitter enabled). */ 531 com->channel_control = CD1400_CCR_CMDCHANCTL 532 | CD1400_CCR_XMTEN 533 | CD1400_CCR_RCVDIS; 534 cd1400_channel_cmd(com, com->channel_control); 535 536 ttydtrwaitstart(tp); 537 } 538 } 539 tp->t_actout = FALSE; 540 wakeup(&tp->t_actout); 541 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 542 splx(s); 543} 544 545/* 546 * This function: 547 * a) needs to be called with COM_LOCK() held, and 548 * b) needs to return with COM_LOCK() held. 549 */ 550static void 551cyinput(struct com_s *com) 552{ 553 u_char *buf; 554 int incc; 555 u_char line_status; 556 int recv_data; 557 struct tty *tp; 558 559 buf = com->ibuf; 560 tp = com->tp; 561 if (!(tp->t_state & TS_ISOPEN)) { 562 cy_events -= (com->iptr - com->ibuf); 563 com->iptr = com->ibuf; 564 return; 565 } 566 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 567 /* 568 * Avoid the grotesquely inefficient lineswitch routine 569 * (ttyinput) in "raw" mode. It usually takes about 450 570 * instructions (that's without canonical processing or echo!). 571 * slinput is reasonably fast (usually 40 instructions plus 572 * call overhead). 573 */ 574 575 do { 576 /* 577 * This may look odd, but it is using save-and-enable 578 * semantics instead of the save-and-disable semantics 579 * that are used everywhere else. 580 */ 581 COM_UNLOCK(); 582 critical_exit(); 583 incc = com->iptr - buf; 584 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 585 && (com->state & CS_RTS_IFLOW 586 || tp->t_iflag & IXOFF) 587 && !(tp->t_state & TS_TBLOCK)) 588 ttyblock(tp); 589 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 590 += b_to_q((char *)buf, incc, &tp->t_rawq); 591 buf += incc; 592 tk_nin += incc; 593 tk_rawcc += incc; 594 tp->t_rawcc += incc; 595 ttwakeup(tp); 596 if (tp->t_state & TS_TTSTOP 597 && (tp->t_iflag & IXANY 598 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 599 tp->t_state &= ~TS_TTSTOP; 600 tp->t_lflag &= ~FLUSHO; 601 cystart(tp); 602 } 603 critical_enter(); 604 COM_LOCK(); 605 } while (buf < com->iptr); 606 } else { 607 do { 608 /* 609 * This may look odd, but it is using save-and-enable 610 * semantics instead of the save-and-disable semantics 611 * that are used everywhere else. 612 */ 613 COM_UNLOCK(); 614 critical_exit(); 615 line_status = buf[com->ierroff]; 616 recv_data = *buf++; 617 if (line_status 618 & (CD1400_RDSR_BREAK | CD1400_RDSR_FE | CD1400_RDSR_OE | CD1400_RDSR_PE)) { 619 if (line_status & CD1400_RDSR_BREAK) 620 recv_data |= TTY_BI; 621 if (line_status & CD1400_RDSR_FE) 622 recv_data |= TTY_FE; 623 if (line_status & CD1400_RDSR_OE) 624 recv_data |= TTY_OE; 625 if (line_status & CD1400_RDSR_PE) 626 recv_data |= TTY_PE; 627 } 628 ttyld_rint(tp, recv_data); 629 critical_enter(); 630 COM_LOCK(); 631 } while (buf < com->iptr); 632 } 633 cy_events -= (com->iptr - com->ibuf); 634 com->iptr = com->ibuf; 635 636 /* 637 * There is now room for another low-level buffer full of input, 638 * so enable RTS if it is now disabled and there is room in the 639 * high-level buffer. 640 */ 641 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) && 642 !(tp->t_state & TS_TBLOCK)) 643 cd_setreg(com, com->mcr_rts_reg, 644 com->mcr_image |= com->mcr_rts); 645} 646 647int 648cyintr(void *vcom) 649{ 650 struct com_s *basecom; 651 int baseu; 652 int cy_align; 653 cy_addr cy_iobase; 654 int cyu; 655 cy_addr iobase; 656 u_char status; 657 int unit; 658 659 COM_LOCK(); /* XXX could this be placed down lower in the loop? */ 660 661 basecom = (struct com_s *)vcom; 662 baseu = basecom->unit; 663 cy_align = basecom->cy_align; 664 cy_iobase = basecom->cy_iobase; 665 unit = baseu / CY_MAX_PORTS; 666 667 /* check each CD1400 in turn */ 668 for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { 669 iobase = (cy_addr) (cy_iobase 670 + (cy_chip_offset[cyu] << cy_align)); 671 /* poll to see if it has any work */ 672 status = cd_inb(iobase, CD1400_SVRR, cy_align); 673 if (status == 0) 674 continue; // XXX - FILTER_STRAY? 675#ifdef CyDebug 676 ++cy_svrr_probes; 677#endif 678 /* service requests as appropriate, giving priority to RX */ 679 if (status & CD1400_SVRR_RXRDY) { 680 struct com_s *com; 681 u_int count; 682 u_char *ioptr; 683 u_char line_status; 684 u_char recv_data; 685 u_char serv_type; 686#ifdef PollMode 687 u_char save_rir; 688#endif 689 690#ifdef PollMode 691 save_rir = cd_inb(iobase, CD1400_RIR, cy_align); 692 693 /* enter rx service */ 694 cd_outb(iobase, CD1400_CAR, cy_align, save_rir); 695 cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 696 = save_rir & CD1400_CAR_CHAN; 697 698 serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); 699 com = cy_addr(baseu 700 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 701 & CD1400_xIVR_CHAN)); 702#else 703 /* ack receive service */ 704 serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); 705 706 com = cy_addr(baseu + 707 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 708 & CD1400_xIVR_CHAN)); 709#endif 710 711 if (serv_type & CD1400_RIVR_EXCEPTION) { 712 ++com->recv_exception; 713 line_status = cd_inb(iobase, CD1400_RDSR, cy_align); 714 /* break/unnattached error bits or real input? */ 715 recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); 716#ifndef SOFT_HOTCHAR 717 if (line_status & CD1400_RDSR_SPECIAL 718 && com->tp->t_hotchar != 0) 719 swi_sched(cy_fast_ih, 0); 720 721#endif 722#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ 723 if (line_status & (CD1400_RDSR_PE|CD1400_RDSR_FE|CD1400_RDSR_BREAK)) { 724 /* 725 Don't store PE if IGNPAR and BI if IGNBRK, 726 this hack allows "raw" tty optimization 727 works even if IGN* is set. 728 */ 729 if ( com->tp == NULL 730 || !(com->tp->t_state & TS_ISOPEN) 731 || ((line_status & (CD1400_RDSR_PE|CD1400_RDSR_FE)) 732 && (com->tp->t_iflag & IGNPAR)) 733 || ((line_status & CD1400_RDSR_BREAK) 734 && (com->tp->t_iflag & IGNBRK))) 735 goto cont; 736 if ( (line_status & (CD1400_RDSR_PE|CD1400_RDSR_FE)) 737 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) 738 && ((line_status & CD1400_RDSR_FE) 739 || ((line_status & CD1400_RDSR_PE) 740 && (com->tp->t_iflag & INPCK)))) 741 recv_data = 0; 742 } 743#endif /* 1 */ 744 ++com->bytes_in; 745#ifdef SOFT_HOTCHAR 746 if (com->tp->t_hotchar != 0 && recv_data == com->tp->t_hotchar) 747 swi_sched(cy_fast_ih, 0); 748#endif 749 ioptr = com->iptr; 750 if (ioptr >= com->ibufend) 751 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 752 else { 753 if (com->tp != NULL && com->tp->t_do_timestamp) 754 microtime(&com->tp->t_timestamp); 755 ++cy_events; 756 ioptr[0] = recv_data; 757 ioptr[com->ierroff] = line_status; 758 com->iptr = ++ioptr; 759 if (ioptr == com->ihighwater 760 && com->state & CS_RTS_IFLOW) 761 cd_outb(iobase, com->mcr_rts_reg, 762 cy_align, 763 com->mcr_image &= 764 ~com->mcr_rts); 765 if (line_status & CD1400_RDSR_OE) 766 CE_RECORD(com, CE_OVERRUN); 767 } 768 goto cont; 769 } else { 770 int ifree; 771 772 count = cd_inb(iobase, CD1400_RDCR, cy_align); 773 if (!count) 774 goto cont; 775 com->bytes_in += count; 776 ioptr = com->iptr; 777 ifree = com->ibufend - ioptr; 778 if (count > ifree) { 779 count -= ifree; 780 cy_events += ifree; 781 if (ifree != 0) { 782 if (com->tp != NULL && com->tp->t_do_timestamp) 783 microtime(&com->tp->t_timestamp); 784 do { 785 recv_data = cd_inb(iobase, 786 CD1400_RDSR, 787 cy_align); 788#ifdef SOFT_HOTCHAR 789 if (com->tp->t_hotchar != 0 790 && recv_data 791 == com->tp->t_hotchar) 792 swi_sched(cy_fast_ih, 793 0); 794#endif 795 ioptr[0] = recv_data; 796 ioptr[com->ierroff] = 0; 797 ++ioptr; 798 } while (--ifree != 0); 799 } 800 com->delta_error_counts 801 [CE_INTERRUPT_BUF_OVERFLOW] += count; 802 do { 803 recv_data = cd_inb(iobase, CD1400_RDSR, 804 cy_align); 805#ifdef SOFT_HOTCHAR 806 if (com->tp->t_hotchar != 0 807 && recv_data == com->tp->t_hotchar) 808 swi_sched(cy_fast_ih, 0); 809#endif 810 } while (--count != 0); 811 } else { 812 if (com->tp != NULL && com->tp->t_do_timestamp) 813 microtime(&com->tp->t_timestamp); 814 if (ioptr <= com->ihighwater 815 && ioptr + count > com->ihighwater 816 && com->state & CS_RTS_IFLOW) 817 cd_outb(iobase, com->mcr_rts_reg, 818 cy_align, 819 com->mcr_image 820 &= ~com->mcr_rts); 821 cy_events += count; 822 do { 823 recv_data = cd_inb(iobase, CD1400_RDSR, 824 cy_align); 825#ifdef SOFT_HOTCHAR 826 if (com->tp->t_hotchar != 0 827 && recv_data == com->tp->t_hotchar) 828 swi_sched(cy_fast_ih, 0); 829#endif 830 ioptr[0] = recv_data; 831 ioptr[com->ierroff] = 0; 832 ++ioptr; 833 } while (--count != 0); 834 } 835 com->iptr = ioptr; 836 } 837cont: 838 839 /* terminate service context */ 840#ifdef PollMode 841 cd_outb(iobase, CD1400_RIR, cy_align, 842 save_rir 843 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); 844#else 845 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 846#endif 847 } 848 if (status & CD1400_SVRR_MDMCH) { 849 struct com_s *com; 850 u_char modem_status; 851#ifdef PollMode 852 u_char save_mir; 853#else 854 u_char vector; 855#endif 856 857#ifdef PollMode 858 save_mir = cd_inb(iobase, CD1400_MIR, cy_align); 859 860 /* enter modem service */ 861 cd_outb(iobase, CD1400_CAR, cy_align, save_mir); 862 cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 863 = save_mir & CD1400_CAR_CHAN; 864 865 com = cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS 866 + (save_mir & CD1400_MIR_CHAN)); 867#else 868 /* ack modem service */ 869 vector = cy_inb(iobase, CY8_SVCACKM, cy_align); 870 871 com = cy_addr(baseu 872 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 873 & CD1400_xIVR_CHAN)); 874#endif 875 ++com->mdm; 876 modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align); 877 if (modem_status != com->last_modem_status) { 878 /* 879 * Schedule high level to handle DCD changes. Note 880 * that we don't use the delta bits anywhere. Some 881 * UARTs mess them up, and it's easy to remember the 882 * previous bits and calculate the delta. 883 */ 884 com->last_modem_status = modem_status; 885 if (!(com->state & CS_CHECKMSR)) { 886 cy_events += LOTS_OF_EVENTS; 887 com->state |= CS_CHECKMSR; 888 swi_sched(cy_fast_ih, 0); 889 } 890 891#ifdef SOFT_CTS_OFLOW 892 /* handle CTS change immediately for crisp flow ctl */ 893 if (com->state & CS_CTS_OFLOW) { 894 if (modem_status & CD1400_MSVR2_CTS) { 895 com->state |= CS_ODEVREADY; 896 if (com->state >= (CS_BUSY | CS_TTGO 897 | CS_ODEVREADY) 898 && !(com->intr_enable 899 & CD1400_SRER_TXRDY)) 900 cd_outb(iobase, CD1400_SRER, 901 cy_align, 902 com->intr_enable 903 = com->intr_enable 904 & ~CD1400_SRER_TXMPTY 905 | CD1400_SRER_TXRDY); 906 } else { 907 com->state &= ~CS_ODEVREADY; 908 if (com->intr_enable 909 & CD1400_SRER_TXRDY) 910 cd_outb(iobase, CD1400_SRER, 911 cy_align, 912 com->intr_enable 913 = com->intr_enable 914 & ~CD1400_SRER_TXRDY 915 | CD1400_SRER_TXMPTY); 916 } 917 } 918#endif 919 } 920 921 /* terminate service context */ 922#ifdef PollMode 923 cd_outb(iobase, CD1400_MIR, cy_align, 924 save_mir 925 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); 926#else 927 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 928#endif 929 } 930 if (status & CD1400_SVRR_TXRDY) { 931 struct com_s *com; 932#ifdef PollMode 933 u_char save_tir; 934#else 935 u_char vector; 936#endif 937 938#ifdef PollMode 939 save_tir = cd_inb(iobase, CD1400_TIR, cy_align); 940 941 /* enter tx service */ 942 cd_outb(iobase, CD1400_CAR, cy_align, save_tir); 943 cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 944 = save_tir & CD1400_CAR_CHAN; 945 946 com = cy_addr(baseu 947 + cyu * CD1400_NO_OF_CHANNELS 948 + (save_tir & CD1400_TIR_CHAN)); 949#else 950 /* ack transmit service */ 951 vector = cy_inb(iobase, CY8_SVCACKT, cy_align); 952 953 com = cy_addr(baseu 954 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 955 & CD1400_xIVR_CHAN)); 956#endif 957 958 if (com->etc != ETC_NONE) { 959 if (com->intr_enable & CD1400_SRER_TXRDY) { 960 /* 961 * Here due to sloppy SRER_TXRDY 962 * enabling. Ignore. Come back when 963 * tx is empty. 964 */ 965 cd_outb(iobase, CD1400_SRER, cy_align, 966 com->intr_enable 967 = (com->intr_enable 968 & ~CD1400_SRER_TXRDY) 969 | CD1400_SRER_TXMPTY); 970 goto terminate_tx_service; 971 } 972 switch (com->etc) { 973 case CD1400_ETC_SENDBREAK: 974 case CD1400_ETC_STOPBREAK: 975 /* 976 * Start the command. Come back on 977 * next tx empty interrupt, hopefully 978 * after command has been executed. 979 */ 980 cd_outb(iobase, CD1400_COR2, cy_align, 981 com->cor[1] |= CD1400_COR2_ETC); 982 cd_outb(iobase, CD1400_TDR, cy_align, 983 CD1400_ETC_CMD); 984 cd_outb(iobase, CD1400_TDR, cy_align, 985 com->etc); 986 if (com->etc == CD1400_ETC_SENDBREAK) 987 com->etc = ETC_BREAK_STARTING; 988 else 989 com->etc = ETC_BREAK_ENDING; 990 goto terminate_tx_service; 991 case ETC_BREAK_STARTING: 992 /* 993 * BREAK is now on. Continue with 994 * SRER_TXMPTY processing, hopefully 995 * don't come back. 996 */ 997 com->etc = ETC_BREAK_STARTED; 998 break; 999 case ETC_BREAK_STARTED: 1000 /* 1001 * Came back due to sloppy SRER_TXMPTY 1002 * enabling. Hope again. 1003 */ 1004 break; 1005 case ETC_BREAK_ENDING: 1006 /* 1007 * BREAK is now off. Continue with 1008 * SRER_TXMPTY processing and don't 1009 * come back. The SWI handler will 1010 * restart tx interrupts if necessary. 1011 */ 1012 cd_outb(iobase, CD1400_COR2, cy_align, 1013 com->cor[1] 1014 &= ~CD1400_COR2_ETC); 1015 com->etc = ETC_BREAK_ENDED; 1016 if (!(com->state & CS_ODONE)) { 1017 cy_events += LOTS_OF_EVENTS; 1018 com->state |= CS_ODONE; 1019 swi_sched(cy_fast_ih, 0); 1020 } 1021 break; 1022 case ETC_BREAK_ENDED: 1023 /* 1024 * Shouldn't get here. Hope again. 1025 */ 1026 break; 1027 } 1028 } 1029 if (com->intr_enable & CD1400_SRER_TXMPTY) { 1030 if (!(com->extra_state & CSE_ODONE)) { 1031 cy_events += LOTS_OF_EVENTS; 1032 com->extra_state |= CSE_ODONE; 1033 swi_sched(cy_fast_ih, 0); 1034 } 1035 cd_outb(iobase, CD1400_SRER, cy_align, 1036 com->intr_enable 1037 &= ~CD1400_SRER_TXMPTY); 1038 goto terminate_tx_service; 1039 } 1040 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1041 u_char *ioptr; 1042 u_int ocount; 1043 1044 ioptr = com->obufq.l_head; 1045 ocount = com->obufq.l_tail - ioptr; 1046 if (ocount > CD1400_TX_FIFO_SIZE) 1047 ocount = CD1400_TX_FIFO_SIZE; 1048 com->bytes_out += ocount; 1049 do 1050 cd_outb(iobase, CD1400_TDR, cy_align, 1051 *ioptr++); 1052 while (--ocount != 0); 1053 com->obufq.l_head = ioptr; 1054 if (ioptr >= com->obufq.l_tail) { 1055 struct lbq *qp; 1056 1057 qp = com->obufq.l_next; 1058 qp->l_queued = FALSE; 1059 qp = qp->l_next; 1060 if (qp != NULL) { 1061 com->obufq.l_head = qp->l_head; 1062 com->obufq.l_tail = qp->l_tail; 1063 com->obufq.l_next = qp; 1064 } else { 1065 /* output just completed */ 1066 com->state &= ~CS_BUSY; 1067 1068 /* 1069 * The setting of CSE_ODONE may be 1070 * stale here. We currently only 1071 * use it when CS_BUSY is set, and 1072 * fixing it when we clear CS_BUSY 1073 * is easiest. 1074 */ 1075 if (com->extra_state & CSE_ODONE) { 1076 cy_events -= LOTS_OF_EVENTS; 1077 com->extra_state &= ~CSE_ODONE; 1078 } 1079 1080 cd_outb(iobase, CD1400_SRER, cy_align, 1081 com->intr_enable 1082 = (com->intr_enable 1083 & ~CD1400_SRER_TXRDY) 1084 | CD1400_SRER_TXMPTY); 1085 } 1086 if (!(com->state & CS_ODONE)) { 1087 cy_events += LOTS_OF_EVENTS; 1088 com->state |= CS_ODONE; 1089 1090 /* handle at high level ASAP */ 1091 swi_sched(cy_fast_ih, 0); 1092 } 1093 } 1094 } 1095 1096 /* terminate service context */ 1097terminate_tx_service: 1098#ifdef PollMode 1099 cd_outb(iobase, CD1400_TIR, cy_align, 1100 save_tir 1101 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); 1102#else 1103 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1104#endif 1105 } 1106 } 1107 1108 /* ensure an edge for the next interrupt */ 1109 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 1110 1111 swi_sched(cy_slow_ih, SWI_DELAY); 1112 1113 COM_UNLOCK(); 1114 return (FILTER_HANDLED); 1115} 1116 1117static void 1118cybreak(struct tty *tp, int sig) 1119{ 1120 struct com_s *com; 1121 1122 com = tp->t_sc; 1123 if (sig) 1124 cd_etc(com, CD1400_ETC_SENDBREAK); 1125 else 1126 cd_etc(com, CD1400_ETC_STOPBREAK); 1127} 1128 1129static void 1130cypoll(void *arg) 1131{ 1132 int unit; 1133 1134#ifdef CyDebug 1135 ++cy_timeouts; 1136#endif 1137 if (cy_events == 0) 1138 return; 1139repeat: 1140 for (unit = 0; unit < NPORTS; ++unit) { 1141 struct com_s *com; 1142 int incc; 1143 struct tty *tp; 1144 1145 com = cy_addr(unit); 1146 if (com == NULL) 1147 continue; 1148 tp = com->tp; 1149 if (tp == NULL) { 1150 /* 1151 * XXX forget any events related to closed devices 1152 * (actually never opened devices) so that we don't 1153 * loop. 1154 */ 1155 critical_enter(); 1156 COM_LOCK(); 1157 incc = com->iptr - com->ibuf; 1158 com->iptr = com->ibuf; 1159 if (com->state & CS_CHECKMSR) { 1160 incc += LOTS_OF_EVENTS; 1161 com->state &= ~CS_CHECKMSR; 1162 } 1163 cy_events -= incc; 1164 COM_UNLOCK(); 1165 critical_exit(); 1166 if (incc != 0) 1167 log(LOG_DEBUG, 1168 "cy%d: %d events for device with no tp\n", 1169 unit, incc); 1170 continue; 1171 } 1172 if (com->iptr != com->ibuf) { 1173 critical_enter(); 1174 COM_LOCK(); 1175 cyinput(com); 1176 COM_UNLOCK(); 1177 critical_exit(); 1178 } 1179 if (com->state & CS_CHECKMSR) { 1180 u_char delta_modem_status; 1181 1182 critical_enter(); 1183 COM_LOCK(); 1184 cyinput(com); 1185 delta_modem_status = com->last_modem_status 1186 ^ com->prev_modem_status; 1187 com->prev_modem_status = com->last_modem_status; 1188 cy_events -= LOTS_OF_EVENTS; 1189 com->state &= ~CS_CHECKMSR; 1190 COM_UNLOCK(); 1191 critical_exit(); 1192 if (delta_modem_status & CD1400_MSVR2_CD) 1193 ttyld_modem(tp, 1194 com->prev_modem_status & CD1400_MSVR2_CD); 1195 } 1196 if (com->extra_state & CSE_ODONE) { 1197 critical_enter(); 1198 COM_LOCK(); 1199 cy_events -= LOTS_OF_EVENTS; 1200 com->extra_state &= ~CSE_ODONE; 1201 COM_UNLOCK(); 1202 critical_exit(); 1203 if (!(com->state & CS_BUSY)) { 1204 tp->t_state &= ~TS_BUSY; 1205 ttwwakeup(com->tp); 1206 } 1207 if (com->etc != ETC_NONE) { 1208 if (com->etc == ETC_BREAK_ENDED) 1209 com->etc = ETC_NONE; 1210 wakeup(&com->etc); 1211 } 1212 } 1213 if (com->state & CS_ODONE) { 1214 critical_enter(); 1215 COM_LOCK(); 1216 cy_events -= LOTS_OF_EVENTS; 1217 com->state &= ~CS_ODONE; 1218 COM_UNLOCK(); 1219 critical_exit(); 1220 ttyld_start(tp); 1221 } 1222 if (cy_events == 0) 1223 break; 1224 } 1225 if (cy_events >= LOTS_OF_EVENTS) 1226 goto repeat; 1227} 1228 1229static int 1230cyparam(struct tty *tp, struct termios *t) 1231{ 1232 int bits; 1233 int cflag; 1234 struct com_s *com; 1235 u_char cor_change; 1236 u_long cy_clock; 1237 int idivisor; 1238 int iflag; 1239 int iprescaler; 1240 int itimeout; 1241 int odivisor; 1242 int oprescaler; 1243 u_char opt; 1244 int s; 1245 1246 com = tp->t_sc; 1247 1248 /* check requested parameters */ 1249 cy_clock = CY_CLOCK(com->gfrcr_image); 1250 idivisor = cyspeed(t->c_ispeed, cy_clock, &iprescaler); 1251 if (idivisor <= 0) 1252 return (EINVAL); 1253 odivisor = cyspeed(t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed, 1254 cy_clock, &oprescaler); 1255 if (odivisor <= 0) 1256 return (EINVAL); 1257 1258 /* parameters are OK, convert them to the com struct and the device */ 1259 s = spltty(); 1260 if (t->c_ospeed == 0) 1261 (void)cymodem(tp, 0, SER_DTR); 1262 else 1263 (void)cymodem(tp, SER_DTR, 0); 1264 1265 (void) cysetwater(com, t->c_ispeed); 1266 1267 /* XXX we don't actually change the speed atomically. */ 1268 1269 cd_setreg(com, CD1400_RBPR, idivisor); 1270 cd_setreg(com, CD1400_RCOR, iprescaler); 1271 cd_setreg(com, CD1400_TBPR, odivisor); 1272 cd_setreg(com, CD1400_TCOR, oprescaler); 1273 1274 /* 1275 * channel control 1276 * receiver enable 1277 * transmitter enable (always set) 1278 */ 1279 cflag = t->c_cflag; 1280 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 1281 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 1282 if (opt != com->channel_control) { 1283 com->channel_control = opt; 1284 cd1400_channel_cmd(com, opt); 1285 } 1286 1287#ifdef Smarts 1288 /* set special chars */ 1289 /* XXX if one is _POSIX_VDISABLE, can't use some others */ 1290 if (t->c_cc[VSTOP] != _POSIX_VDISABLE) 1291 cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); 1292 if (t->c_cc[VSTART] != _POSIX_VDISABLE) 1293 cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); 1294 if (t->c_cc[VINTR] != _POSIX_VDISABLE) 1295 cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); 1296 if (t->c_cc[VSUSP] != _POSIX_VDISABLE) 1297 cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); 1298#endif 1299 1300 /* 1301 * set channel option register 1 - 1302 * parity mode 1303 * stop bits 1304 * char length 1305 */ 1306 opt = 0; 1307 /* parity */ 1308 if (cflag & PARENB) { 1309 if (cflag & PARODD) 1310 opt |= CD1400_COR1_PARODD; 1311 opt |= CD1400_COR1_PARNORMAL; 1312 } 1313 iflag = t->c_iflag; 1314 if (!(iflag & INPCK)) 1315 opt |= CD1400_COR1_NOINPCK; 1316 bits = 1 + 1; 1317 /* stop bits */ 1318 if (cflag & CSTOPB) { 1319 ++bits; 1320 opt |= CD1400_COR1_STOP2; 1321 } 1322 /* char length */ 1323 switch (cflag & CSIZE) { 1324 case CS5: 1325 bits += 5; 1326 opt |= CD1400_COR1_CS5; 1327 break; 1328 case CS6: 1329 bits += 6; 1330 opt |= CD1400_COR1_CS6; 1331 break; 1332 case CS7: 1333 bits += 7; 1334 opt |= CD1400_COR1_CS7; 1335 break; 1336 default: 1337 bits += 8; 1338 opt |= CD1400_COR1_CS8; 1339 break; 1340 } 1341 cor_change = 0; 1342 if (opt != com->cor[0]) { 1343 cor_change |= CD1400_CCR_COR1; 1344 cd_setreg(com, CD1400_COR1, com->cor[0] = opt); 1345 } 1346 1347 /* 1348 * Set receive time-out period, normally to max(one char time, 5 ms). 1349 */ 1350 itimeout = howmany(1000 * bits, t->c_ispeed); 1351#ifdef SOFT_HOTCHAR 1352#define MIN_RTP 1 1353#else 1354#define MIN_RTP 5 1355#endif 1356 if (itimeout < MIN_RTP) 1357 itimeout = MIN_RTP; 1358 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 1359 && t->c_cc[VTIME] * 10 > itimeout) 1360 itimeout = t->c_cc[VTIME] * 10; 1361 if (itimeout > 255) 1362 itimeout = 255; 1363 cd_setreg(com, CD1400_RTPR, itimeout); 1364 1365 /* 1366 * set channel option register 2 - 1367 * flow control 1368 */ 1369 opt = 0; 1370#ifdef Smarts 1371 if (iflag & IXANY) 1372 opt |= CD1400_COR2_IXANY; 1373 if (iflag & IXOFF) 1374 opt |= CD1400_COR2_IXOFF; 1375#endif 1376#ifndef SOFT_CTS_OFLOW 1377 if (cflag & CCTS_OFLOW) 1378 opt |= CD1400_COR2_CCTS_OFLOW; 1379#endif 1380 critical_enter(); 1381 COM_LOCK(); 1382 if (opt != com->cor[1]) { 1383 cor_change |= CD1400_CCR_COR2; 1384 cd_setreg(com, CD1400_COR2, com->cor[1] = opt); 1385 } 1386 COM_UNLOCK(); 1387 critical_exit(); 1388 1389 /* 1390 * set channel option register 3 - 1391 * receiver FIFO interrupt threshold 1392 * flow control 1393 */ 1394 opt = RxFifoThreshold; 1395#ifdef Smarts 1396 if (t->c_lflag & ICANON) 1397 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 1398 if (iflag & IXOFF) 1399 /* detect and transparently handle START and STOP chars */ 1400 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 1401#endif 1402 if (opt != com->cor[2]) { 1403 cor_change |= CD1400_CCR_COR3; 1404 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 1405 } 1406 1407 /* notify the CD1400 if COR1-3 have changed */ 1408 if (cor_change) 1409 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); 1410 1411 /* 1412 * set channel option register 4 - 1413 * CR/NL processing 1414 * break processing 1415 * received exception processing 1416 */ 1417 opt = 0; 1418 if (iflag & IGNCR) 1419 opt |= CD1400_COR4_IGNCR; 1420#ifdef Smarts 1421 /* 1422 * we need a new ttyinput() for this, as we don't want to 1423 * have ICRNL && INLCR being done in both layers, or to have 1424 * synchronisation problems 1425 */ 1426 if (iflag & ICRNL) 1427 opt |= CD1400_COR4_ICRNL; 1428 if (iflag & INLCR) 1429 opt |= CD1400_COR4_INLCR; 1430#endif 1431 if (iflag & IGNBRK) 1432 opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; 1433 /* 1434 * The `-ignbrk -brkint parmrk' case is not handled by the hardware, 1435 * so only tell the hardware about -brkint if -parmrk. 1436 */ 1437 if (!(iflag & (BRKINT | PARMRK))) 1438 opt |= CD1400_COR4_NOBRKINT; 1439#if 0 1440 /* XXX using this "intelligence" breaks reporting of overruns. */ 1441 if (iflag & IGNPAR) 1442 opt |= CD1400_COR4_PFO_DISCARD; 1443 else { 1444 if (iflag & PARMRK) 1445 opt |= CD1400_COR4_PFO_ESC; 1446 else 1447 opt |= CD1400_COR4_PFO_NUL; 1448 } 1449#else 1450 opt |= CD1400_COR4_PFO_EXCEPTION; 1451#endif 1452 cd_setreg(com, CD1400_COR4, opt); 1453 1454 /* 1455 * set channel option register 5 - 1456 */ 1457 opt = 0; 1458 if (iflag & ISTRIP) 1459 opt |= CD1400_COR5_ISTRIP; 1460 if (t->c_iflag & IEXTEN) 1461 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 1462 opt |= CD1400_COR5_LNEXT; 1463#ifdef Smarts 1464 if (t->c_oflag & ONLCR) 1465 opt |= CD1400_COR5_ONLCR; 1466 if (t->c_oflag & OCRNL) 1467 opt |= CD1400_COR5_OCRNL; 1468#endif 1469 cd_setreg(com, CD1400_COR5, opt); 1470 1471 /* 1472 * We always generate modem status change interrupts for CD changes. 1473 * Among other things, this is necessary to track TS_CARR_ON for 1474 * pstat to print even when the driver doesn't care. CD changes 1475 * should be rare so interrupts for them are not worth extra code to 1476 * avoid. We avoid interrupts for other modem status changes (except 1477 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is 1478 * simplest and best. 1479 */ 1480 1481 /* 1482 * set modem change option register 1 1483 * generate modem interrupts on which 1 -> 0 input transitions 1484 * also controls auto-DTR output flow-control, which we don't use 1485 */ 1486 opt = CD1400_MCOR1_CDzd; 1487#ifdef SOFT_CTS_OFLOW 1488 if (cflag & CCTS_OFLOW) 1489 opt |= CD1400_MCOR1_CTSzd; 1490#endif 1491 cd_setreg(com, CD1400_MCOR1, opt); 1492 1493 /* 1494 * set modem change option register 2 1495 * generate modem interrupts on specific 0 -> 1 input transitions 1496 */ 1497 opt = CD1400_MCOR2_CDod; 1498#ifdef SOFT_CTS_OFLOW 1499 if (cflag & CCTS_OFLOW) 1500 opt |= CD1400_MCOR2_CTSod; 1501#endif 1502 cd_setreg(com, CD1400_MCOR2, opt); 1503 1504 /* 1505 * XXX should have done this long ago, but there is too much state 1506 * to change all atomically. 1507 */ 1508 critical_enter(); 1509 COM_LOCK(); 1510 1511 com->state &= ~CS_TTGO; 1512 if (!(tp->t_state & TS_TTSTOP)) 1513 com->state |= CS_TTGO; 1514 if (cflag & CRTS_IFLOW) { 1515 com->state |= CS_RTS_IFLOW; 1516 /* 1517 * If CS_RTS_IFLOW just changed from off to on, the change 1518 * needs to be propagated to CD1400_MSVR1_RTS. This isn't urgent, 1519 * so do it later by calling cystart() instead of repeating 1520 * a lot of code from cystart() here. 1521 */ 1522 } else if (com->state & CS_RTS_IFLOW) { 1523 com->state &= ~CS_RTS_IFLOW; 1524 /* 1525 * CS_RTS_IFLOW just changed from on to off. Force CD1400_MSVR1_RTS 1526 * on here, since cystart() won't do it later. 1527 */ 1528 cd_setreg(com, com->mcr_rts_reg, 1529 com->mcr_image |= com->mcr_rts); 1530 } 1531 1532 /* 1533 * Set up state to handle output flow control. 1534 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 1535 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 1536 */ 1537 com->state |= CS_ODEVREADY; 1538#ifdef SOFT_CTS_OFLOW 1539 com->state &= ~CS_CTS_OFLOW; 1540 if (cflag & CCTS_OFLOW) { 1541 com->state |= CS_CTS_OFLOW; 1542 if (!(com->last_modem_status & CD1400_MSVR2_CTS)) 1543 com->state &= ~CS_ODEVREADY; 1544 } 1545#endif 1546 /* XXX shouldn't call functions while intrs are disabled. */ 1547 disc_optim(tp, t, com); 1548#if 0 1549 /* 1550 * Recover from fiddling with CS_TTGO. We used to call cyintr1() 1551 * unconditionally, but that defeated the careful discarding of 1552 * stale input in cyopen(). 1553 */ 1554 if (com->state >= (CS_BUSY | CS_TTGO)) 1555 cyintr1(com); 1556#endif 1557 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1558 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 1559 cd_setreg(com, CD1400_SRER, 1560 com->intr_enable 1561 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 1562 | CD1400_SRER_TXRDY); 1563 } else { 1564 if (com->intr_enable & CD1400_SRER_TXRDY) 1565 cd_setreg(com, CD1400_SRER, 1566 com->intr_enable 1567 = (com->intr_enable & ~CD1400_SRER_TXRDY) 1568 | CD1400_SRER_TXMPTY); 1569 } 1570 1571 COM_UNLOCK(); 1572 critical_exit(); 1573 splx(s); 1574 cystart(tp); 1575 if (com->ibufold != NULL) { 1576 free(com->ibufold, M_DEVBUF); 1577 com->ibufold = NULL; 1578 } 1579 return (0); 1580} 1581 1582static int 1583cysetwater(struct com_s *com, speed_t speed) 1584{ 1585 int cp4ticks; 1586 u_char *ibuf; 1587 int ibufsize; 1588 struct tty *tp; 1589 1590 /* 1591 * Make the buffer size large enough to handle a softtty interrupt 1592 * latency of about 2 ticks without loss of throughput or data 1593 * (about 3 ticks if input flow control is not used or not honoured, 1594 * but a bit less for CS5-CS7 modes). 1595 */ 1596 cp4ticks = speed / 10 / hz * 4; 1597 for (ibufsize = 128; ibufsize < cp4ticks;) 1598 ibufsize <<= 1; 1599 if (ibufsize == com->ibufsize) { 1600 return (0); 1601 } 1602 1603 /* 1604 * Allocate input buffer. The extra factor of 2 in the size is 1605 * to allow for an error byte for each input byte. 1606 */ 1607 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 1608 if (ibuf == NULL) { 1609 return (ENOMEM); 1610 } 1611 1612 /* Initialize non-critical variables. */ 1613 com->ibufold = com->ibuf; 1614 com->ibufsize = ibufsize; 1615 tp = com->tp; 1616 if (tp != NULL) { 1617 tp->t_ififosize = 2 * ibufsize; 1618 tp->t_ispeedwat = (speed_t)-1; 1619 tp->t_ospeedwat = (speed_t)-1; 1620 } 1621 1622 /* 1623 * Read current input buffer, if any. Continue with interrupts 1624 * disabled. 1625 */ 1626 critical_enter(); 1627 COM_LOCK(); 1628 if (com->iptr != com->ibuf) 1629 cyinput(com); 1630 1631 /*- 1632 * Initialize critical variables, including input buffer watermarks. 1633 * The external device is asked to stop sending when the buffer 1634 * exactly reaches high water, or when the high level requests it. 1635 * The high level is notified immediately (rather than at a later 1636 * clock tick) when this watermark is reached. 1637 * The buffer size is chosen so the watermark should almost never 1638 * be reached. 1639 * The low watermark is invisibly 0 since the buffer is always 1640 * emptied all at once. 1641 */ 1642 com->iptr = com->ibuf = ibuf; 1643 com->ibufend = ibuf + ibufsize; 1644 com->ierroff = ibufsize; 1645 com->ihighwater = ibuf + 3 * ibufsize / 4; 1646 1647 COM_UNLOCK(); 1648 critical_exit(); 1649 return (0); 1650} 1651 1652static void 1653cystart(struct tty *tp) 1654{ 1655 struct com_s *com; 1656 int s; 1657#ifdef CyDebug 1658 bool_t started; 1659#endif 1660 1661 com = tp->t_sc; 1662 s = spltty(); 1663 1664#ifdef CyDebug 1665 ++com->start_count; 1666 started = FALSE; 1667#endif 1668 1669 critical_enter(); 1670 COM_LOCK(); 1671 if (tp->t_state & TS_TTSTOP) { 1672 com->state &= ~CS_TTGO; 1673 if (com->intr_enable & CD1400_SRER_TXRDY) 1674 cd_setreg(com, CD1400_SRER, 1675 com->intr_enable 1676 = (com->intr_enable & ~CD1400_SRER_TXRDY) 1677 | CD1400_SRER_TXMPTY); 1678 } else { 1679 com->state |= CS_TTGO; 1680 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 1681 && !(com->intr_enable & CD1400_SRER_TXRDY)) 1682 cd_setreg(com, CD1400_SRER, 1683 com->intr_enable 1684 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 1685 | CD1400_SRER_TXRDY); 1686 } 1687 if (tp->t_state & TS_TBLOCK) { 1688 if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) 1689#if 0 1690 outb(com->modem_ctl_port, com->mcr_image &= ~CD1400_MSVR1_RTS); 1691#else 1692 cd_setreg(com, com->mcr_rts_reg, 1693 com->mcr_image &= ~com->mcr_rts); 1694#endif 1695 } else { 1696 if (!(com->mcr_image & com->mcr_rts) 1697 && com->iptr < com->ihighwater 1698 && com->state & CS_RTS_IFLOW) 1699#if 0 1700 outb(com->modem_ctl_port, com->mcr_image |= CD1400_MSVR1_RTS); 1701#else 1702 cd_setreg(com, com->mcr_rts_reg, 1703 com->mcr_image |= com->mcr_rts); 1704#endif 1705 } 1706 COM_UNLOCK(); 1707 critical_exit(); 1708 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 1709 ttwwakeup(tp); 1710 splx(s); 1711 return; 1712 } 1713 if (tp->t_outq.c_cc != 0) { 1714 struct lbq *qp; 1715 struct lbq *next; 1716 1717 if (!com->obufs[0].l_queued) { 1718#ifdef CyDebug 1719 started = TRUE; 1720#endif 1721 com->obufs[0].l_tail 1722 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 1723 sizeof com->obuf1); 1724 com->obufs[0].l_next = NULL; 1725 com->obufs[0].l_queued = TRUE; 1726 critical_enter(); 1727 COM_LOCK(); 1728 if (com->state & CS_BUSY) { 1729 qp = com->obufq.l_next; 1730 while ((next = qp->l_next) != NULL) 1731 qp = next; 1732 qp->l_next = &com->obufs[0]; 1733 } else { 1734 com->obufq.l_head = com->obufs[0].l_head; 1735 com->obufq.l_tail = com->obufs[0].l_tail; 1736 com->obufq.l_next = &com->obufs[0]; 1737 com->state |= CS_BUSY; 1738 if (com->state >= (CS_BUSY | CS_TTGO 1739 | CS_ODEVREADY)) 1740 cd_setreg(com, CD1400_SRER, 1741 com->intr_enable 1742 = (com->intr_enable 1743 & ~CD1400_SRER_TXMPTY) 1744 | CD1400_SRER_TXRDY); 1745 } 1746 COM_UNLOCK(); 1747 critical_exit(); 1748 } 1749 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 1750#ifdef CyDebug 1751 started = TRUE; 1752#endif 1753 com->obufs[1].l_tail 1754 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 1755 sizeof com->obuf2); 1756 com->obufs[1].l_next = NULL; 1757 com->obufs[1].l_queued = TRUE; 1758 critical_enter(); 1759 COM_LOCK(); 1760 if (com->state & CS_BUSY) { 1761 qp = com->obufq.l_next; 1762 while ((next = qp->l_next) != NULL) 1763 qp = next; 1764 qp->l_next = &com->obufs[1]; 1765 } else { 1766 com->obufq.l_head = com->obufs[1].l_head; 1767 com->obufq.l_tail = com->obufs[1].l_tail; 1768 com->obufq.l_next = &com->obufs[1]; 1769 com->state |= CS_BUSY; 1770 if (com->state >= (CS_BUSY | CS_TTGO 1771 | CS_ODEVREADY)) 1772 cd_setreg(com, CD1400_SRER, 1773 com->intr_enable 1774 = (com->intr_enable 1775 & ~CD1400_SRER_TXMPTY) 1776 | CD1400_SRER_TXRDY); 1777 } 1778 COM_UNLOCK(); 1779 critical_exit(); 1780 } 1781 tp->t_state |= TS_BUSY; 1782 } 1783#ifdef CyDebug 1784 if (started) 1785 ++com->start_real; 1786#endif 1787#if 0 1788 critical_enter(); 1789 COM_LOCK(); 1790 if (com->state >= (CS_BUSY | CS_TTGO)) 1791 cyintr1(com); /* fake interrupt to start output */ 1792 COM_UNLOCK(); 1793 critical_exit(); 1794#endif 1795 ttwwakeup(tp); 1796 splx(s); 1797} 1798 1799static void 1800comstop(struct tty *tp, int rw) 1801{ 1802 struct com_s *com; 1803 bool_t wakeup_etc; 1804 1805 com = tp->t_sc; 1806 wakeup_etc = FALSE; 1807 critical_enter(); 1808 COM_LOCK(); 1809 if (rw & FWRITE) { 1810 com->obufs[0].l_queued = FALSE; 1811 com->obufs[1].l_queued = FALSE; 1812 if (com->extra_state & CSE_ODONE) { 1813 cy_events -= LOTS_OF_EVENTS; 1814 com->extra_state &= ~CSE_ODONE; 1815 if (com->etc != ETC_NONE) { 1816 if (com->etc == ETC_BREAK_ENDED) 1817 com->etc = ETC_NONE; 1818 wakeup_etc = TRUE; 1819 } 1820 } 1821 com->tp->t_state &= ~TS_BUSY; 1822 if (com->state & CS_ODONE) 1823 cy_events -= LOTS_OF_EVENTS; 1824 com->state &= ~(CS_ODONE | CS_BUSY); 1825 } 1826 if (rw & FREAD) { 1827 /* XXX no way to reset only input fifo. */ 1828 cy_events -= (com->iptr - com->ibuf); 1829 com->iptr = com->ibuf; 1830 } 1831 COM_UNLOCK(); 1832 critical_exit(); 1833 if (wakeup_etc) 1834 wakeup(&com->etc); 1835 if (rw & FWRITE && com->etc == ETC_NONE) 1836 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 1837 cystart(tp); 1838} 1839 1840static int 1841cymodem(struct tty *tp, int sigon, int sigoff) 1842{ 1843 struct com_s *com; 1844 int mcr; 1845 int msr; 1846 1847 com = tp->t_sc; 1848 if (sigon == 0 && sigoff == 0) { 1849 sigon = 0; 1850 mcr = com->mcr_image; 1851 if (mcr & com->mcr_dtr) 1852 sigon |= SER_DTR; 1853 if (mcr & com->mcr_rts) 1854 /* XXX wired on for Cyclom-8Ys */ 1855 sigon |= SER_RTS; 1856 1857 /* 1858 * We must read the modem status from the hardware because 1859 * we don't generate modem status change interrupts for all 1860 * changes, so com->prev_modem_status is not guaranteed to 1861 * be up to date. This is safe, unlike for sio, because 1862 * reading the status register doesn't clear pending modem 1863 * status change interrupts. 1864 */ 1865 msr = cd_getreg(com, CD1400_MSVR2); 1866 1867 if (msr & CD1400_MSVR2_CTS) 1868 sigon |= SER_CTS; 1869 if (msr & CD1400_MSVR2_CD) 1870 sigon |= SER_DCD; 1871 if (msr & CD1400_MSVR2_DSR) 1872 sigon |= SER_DSR; 1873 if (msr & CD1400_MSVR2_RI) 1874 /* XXX not connected except for Cyclom-16Y? */ 1875 sigon |= SER_RI; 1876 return (sigon); 1877 } 1878 mcr = com->mcr_image; 1879 if (sigon & SER_DTR) 1880 mcr |= com->mcr_dtr; 1881 if (sigoff & SER_DTR) 1882 mcr &= ~com->mcr_dtr; 1883 if (sigon & SER_RTS) 1884 mcr |= com->mcr_rts; 1885 if (sigoff & SER_RTS) 1886 mcr &= ~com->mcr_rts; 1887 critical_enter(); 1888 COM_LOCK(); 1889 com->mcr_image = mcr; 1890 cd_setreg(com, CD1400_MSVR1, mcr); 1891 cd_setreg(com, CD1400_MSVR2, mcr); 1892 COM_UNLOCK(); 1893 critical_exit(); 1894 return (0); 1895} 1896 1897static void 1898cysettimeout() 1899{ 1900 struct com_s *com; 1901 bool_t someopen; 1902 int unit; 1903 1904 /* 1905 * Set our timeout period to 1 second if no polled devices are open. 1906 * Otherwise set it to max(1/200, 1/hz). 1907 * Enable timeouts iff some device is open. 1908 */ 1909 untimeout(cywakeup, (void *)NULL, cy_timeout_handle); 1910 cy_timeout = hz; 1911 someopen = FALSE; 1912 for (unit = 0; unit < NPORTS; ++unit) { 1913 com = cy_addr(unit); 1914 if (com != NULL && com->tp != NULL 1915 && com->tp->t_state & TS_ISOPEN) { 1916 someopen = TRUE; 1917 } 1918 } 1919 if (someopen) { 1920 cy_timeouts_until_log = hz / cy_timeout; 1921 cy_timeout_handle = timeout(cywakeup, (void *)NULL, 1922 cy_timeout); 1923 } else { 1924 /* Flush error messages, if any. */ 1925 cy_timeouts_until_log = 1; 1926 cywakeup((void *)NULL); 1927 untimeout(cywakeup, (void *)NULL, cy_timeout_handle); 1928 } 1929} 1930 1931static void 1932cywakeup(void *chan) 1933{ 1934 struct com_s *com; 1935 int unit; 1936 1937 cy_timeout_handle = timeout(cywakeup, (void *)NULL, cy_timeout); 1938 1939 /* 1940 * Check for and log errors, but not too often. 1941 */ 1942 if (--cy_timeouts_until_log > 0) 1943 return; 1944 cy_timeouts_until_log = hz / cy_timeout; 1945 for (unit = 0; unit < NPORTS; ++unit) { 1946 int errnum; 1947 1948 com = cy_addr(unit); 1949 if (com == NULL) 1950 continue; 1951 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 1952 u_int delta; 1953 u_long total; 1954 1955 critical_enter(); 1956 COM_LOCK(); 1957 delta = com->delta_error_counts[errnum]; 1958 com->delta_error_counts[errnum] = 0; 1959 COM_UNLOCK(); 1960 critical_exit(); 1961 if (delta == 0) 1962 continue; 1963 total = com->error_counts[errnum] += delta; 1964 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 1965 unit, delta, error_desc[errnum], 1966 delta == 1 ? "" : "s", total); 1967 } 1968 } 1969} 1970 1971static void 1972disc_optim(struct tty *tp, struct termios *t, struct com_s *com) 1973{ 1974#ifndef SOFT_HOTCHAR 1975 u_char opt; 1976#endif 1977 1978 ttyldoptim(tp); 1979#ifndef SOFT_HOTCHAR 1980 opt = com->cor[2] & ~CD1400_COR3_SCD34; 1981 if (com->tp->t_hotchar != 0) { 1982 cd_setreg(com, CD1400_SCHR3, com->tp->t_hotchar); 1983 cd_setreg(com, CD1400_SCHR4, com->tp->t_hotchar); 1984 opt |= CD1400_COR3_SCD34; 1985 } 1986 if (opt != com->cor[2]) { 1987 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 1988 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 1989 } 1990#endif 1991} 1992 1993#ifdef Smarts 1994/* standard line discipline input routine */ 1995int 1996cyinput(int c, struct tty *tp) 1997{ 1998 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 1999 * bits, as they are done by the CD1400. Hardly worth the effort, 2000 * given that high-throughput session are raw anyhow. 2001 */ 2002} 2003#endif /* Smarts */ 2004 2005static int 2006cyspeed(speed_t speed, u_long cy_clock, int *prescaler_io) 2007{ 2008 int actual; 2009 int error; 2010 int divider; 2011 int prescaler; 2012 int prescaler_unit; 2013 2014 if (speed == 0) 2015 return (0); 2016 if (speed < 0 || speed > 150000) 2017 return (-1); 2018 2019 /* determine which prescaler to use */ 2020 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2021 prescaler_unit--, prescaler >>= 2) { 2022 if (cy_clock / prescaler / speed > 63) 2023 break; 2024 } 2025 2026 divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ 2027 if (divider > 255) 2028 divider = 255; 2029 actual = cy_clock/prescaler/divider; 2030 2031 /* 10 times error in percent: */ 2032 error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; 2033 2034 /* 3.0% max error tolerance */ 2035 if (error < -30 || error > 30) 2036 return (-1); 2037 2038 *prescaler_io = prescaler_unit; 2039 return (divider); 2040} 2041 2042static void 2043cd1400_channel_cmd(struct com_s *com, int cmd) 2044{ 2045 cd1400_channel_cmd_wait(com); 2046 cd_setreg(com, CD1400_CCR, cmd); 2047 cd1400_channel_cmd_wait(com); 2048} 2049 2050static void 2051cd1400_channel_cmd_wait(struct com_s *com) 2052{ 2053 struct timeval start; 2054 struct timeval tv; 2055 long usec; 2056 2057 if (cd_getreg(com, CD1400_CCR) == 0) 2058 return; 2059 microtime(&start); 2060 for (;;) { 2061 if (cd_getreg(com, CD1400_CCR) == 0) 2062 return; 2063 microtime(&tv); 2064 usec = 1000000 * (tv.tv_sec - start.tv_sec) + 2065 tv.tv_usec - start.tv_usec; 2066 if (usec >= 5000) { 2067 log(LOG_ERR, 2068 "cy%d: channel command timeout (%ld usec)\n", 2069 com->unit, usec); 2070 return; 2071 } 2072 } 2073} 2074 2075static void 2076cd_etc(struct com_s *com, int etc) 2077{ 2078 2079 /* 2080 * We can't change the hardware's ETC state while there are any 2081 * characters in the tx fifo, since those characters would be 2082 * interpreted as commands! Unputting characters from the fifo 2083 * is difficult, so we wait up to 12 character times for the fifo 2084 * to drain. The command will be delayed for up to 2 character 2085 * times for the tx to become empty. Unputting characters from 2086 * the tx holding and shift registers is impossible, so we wait 2087 * for the tx to become empty so that the command is sure to be 2088 * executed soon after we issue it. 2089 */ 2090 critical_enter(); 2091 COM_LOCK(); 2092 if (com->etc == etc) 2093 goto wait; 2094 if ((etc == CD1400_ETC_SENDBREAK 2095 && (com->etc == ETC_BREAK_STARTING 2096 || com->etc == ETC_BREAK_STARTED)) 2097 || (etc == CD1400_ETC_STOPBREAK 2098 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED 2099 || com->etc == ETC_NONE))) { 2100 COM_UNLOCK(); 2101 critical_exit(); 2102 return; 2103 } 2104 com->etc = etc; 2105 cd_setreg(com, CD1400_SRER, 2106 com->intr_enable 2107 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); 2108wait: 2109 COM_UNLOCK(); 2110 critical_exit(); 2111 while (com->etc == etc 2112 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) 2113 continue; 2114} 2115 2116static int 2117cd_getreg(struct com_s *com, int reg) 2118{ 2119 struct com_s *basecom; 2120 u_char car; 2121 int cy_align; 2122 cy_addr iobase; 2123#ifdef SMP 2124 int need_unlock; 2125#endif 2126 int val; 2127 2128 basecom = cy_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2129 car = com->unit & CD1400_CAR_CHAN; 2130 cy_align = com->cy_align; 2131 iobase = com->iobase; 2132 critical_enter(); 2133#ifdef SMP 2134 need_unlock = 0; 2135 if (!mtx_owned(&cy_lock)) { 2136 COM_LOCK(); 2137 need_unlock = 1; 2138 } 2139#endif 2140 if (basecom->car != car) 2141 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2142 val = cd_inb(iobase, reg, cy_align); 2143#ifdef SMP 2144 if (need_unlock) 2145 COM_UNLOCK(); 2146#endif 2147 critical_exit(); 2148 return (val); 2149} 2150 2151static void 2152cd_setreg(struct com_s *com, int reg, int val) 2153{ 2154 struct com_s *basecom; 2155 u_char car; 2156 int cy_align; 2157 cy_addr iobase; 2158#ifdef SMP 2159 int need_unlock; 2160#endif 2161 2162 basecom = cy_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2163 car = com->unit & CD1400_CAR_CHAN; 2164 cy_align = com->cy_align; 2165 iobase = com->iobase; 2166 critical_enter(); 2167#ifdef SMP 2168 need_unlock = 0; 2169 if (!mtx_owned(&cy_lock)) { 2170 COM_LOCK(); 2171 need_unlock = 1; 2172 } 2173#endif 2174 if (basecom->car != car) 2175 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2176 cd_outb(iobase, reg, cy_align, val); 2177#ifdef SMP 2178 if (need_unlock) 2179 COM_UNLOCK(); 2180#endif 2181 critical_exit(); 2182} 2183 2184#ifdef CyDebug 2185/* useful in ddb */ 2186void 2187cystatus(int unit) 2188{ 2189 struct com_s *com; 2190 cy_addr iobase; 2191 u_int ocount; 2192 struct tty *tp; 2193 2194 com = cy_addr(unit); 2195 printf("info for channel %d\n", unit); 2196 printf("------------------\n"); 2197 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2198 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2199 if (com == NULL) 2200 return; 2201 iobase = com->iobase; 2202 printf("\n"); 2203 printf("cd1400 base address:\\tt%p\n", iobase); 2204 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2205 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2206 com->cor[0], com->cor[1], com->cor[2]); 2207 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2208 cd_getreg(com, CD1400_SRER), com->intr_enable); 2209 printf("service request register:\t0x%02x\n", 2210 cd_inb(iobase, CD1400_SVRR, com->cy_align)); 2211 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2212 cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); 2213 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2214 cd_inb(iobase, CD1400_RIR, com->cy_align), 2215 cd_inb(iobase, CD1400_TIR, com->cy_align), 2216 cd_inb(iobase, CD1400_MIR, com->cy_align)); 2217 printf("\n"); 2218 printf("com state:\t\t\t0x%02x\n", com->state); 2219 printf("calls to cystart():\t\t%d (%d useful)\n", 2220 com->start_count, com->start_real); 2221 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2222 ocount = 0; 2223 if (com->obufs[0].l_queued) 2224 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2225 if (com->obufs[1].l_queued) 2226 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2227 printf("tx buffer chars:\t\t%u\n", ocount); 2228 printf("received chars:\t\t\t%d\n", com->bytes_in); 2229 printf("received exceptions:\t\t%d\n", com->recv_exception); 2230 printf("modem signal deltas:\t\t%d\n", com->mdm); 2231 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2232 printf("\n"); 2233 tp = com->tp; 2234 if (tp != NULL) { 2235 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2236 printf( 2237 "upper layer queue lengths:\t%d raw, %d canon, %d output\n", 2238 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 2239 } else 2240 printf("tty state:\t\t\tclosed\n"); 2241} 2242#endif /* CyDebug */ 2243