sio.c revision 38439
1/*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)com.c 7.5 (Berkeley) 5/16/91 34 * $Id: sio.c,v 1.64 1998/08/13 07:36:40 kato Exp $ 35 */ 36 37#include "opt_comconsole.h" 38#include "opt_compat.h" 39#include "opt_ddb.h" 40#include "opt_devfs.h" 41#include "opt_sio.h" 42#include "sio.h" 43#include "pnp.h" 44 45#ifndef EXTRA_SIO 46#if NPNP > 0 47#define EXTRA_SIO 2 48#else 49#define EXTRA_SIO 0 50#endif 51#endif 52 53#define NSIOTOT (NSIO + EXTRA_SIO) 54 55/* 56 * Serial driver, based on 386BSD-0.1 com driver. 57 * Mostly rewritten to use pseudo-DMA. 58 * Works for National Semiconductor NS8250-NS16550AF UARTs. 59 * COM driver, based on HP dca driver. 60 * 61 * Changes for PC-Card integration: 62 * - Added PC-Card driver table and handlers 63 */ 64/*=============================================================== 65 * 386BSD(98),FreeBSD-1.1x(98) com driver. 66 * ----- 67 * modified for PC9801 by M.Ishii 68 * Kyoto University Microcomputer Club (KMC) 69 * Chou "TEFUTEFU" Hirotomi 70 * Kyoto Univ. the faculty of medicine 71 *=============================================================== 72 * FreeBSD-2.0.1(98) sio driver. 73 * ----- 74 * modified for pc98 Internal i8251 and MICRO CORE MC16550II 75 * T.Koike(hfc01340@niftyserve.or.jp) 76 * implement kernel device configuration 77 * aizu@orient.center.nitech.ac.jp 78 * 79 * Notes. 80 * ----- 81 * PC98 localization based on 386BSD(98) com driver. Using its PC98 local 82 * functions. 83 * This driver is under debugging,has bugs. 84 * 85 * 1) config 86 * options COM_MULTIPORT #if using MC16550II 87 * device sio0 at nec? port 0x30 tty irq 4 vector siointr #internal 88 * device sio1 at nec? port 0xd2 tty irq 5 flags 0x101 vector siointr #mc1 89 * device sio2 at nec? port 0x8d2 tty flags 0x101 vector siointr #mc2 90 * # ~~~~~iobase ~~multi port flag 91 * # ~ master device is sio1 92 * 2) device 93 * cd /dev; MAKEDEV ttyd0 ttyd1 .. 94 * 3) /etc/rc.serial 95 * 57600bps is too fast for sio0(internal8251) 96 * my ex. 97 * #set default speed 9600 98 * modem() 99 * : 100 * stty </dev/ttyid$i crtscts 9600 101 * : # ~~~~ default speed(can change after init.) 102 * modem 0 1 2 103 * 4) COMCONSOLE 104 * not changed. 105 * 5) PC9861K,PIO9032B,B98_01 106 * not tested. 107 */ 108/* 109 * modified for AIWA B98-01 110 * by T.Hatanou <hatanou@yasuda.comm.waseda.ac.jp> last update: 15 Sep.1995 111 * 112 * How to configure... 113 * # options COM_MULTIPORT # support for MICROCORE MC16550II 114 * ... comment-out this line, which will conflict with B98_01. 115 * options "B98_01" # support for AIWA B98-01 116 * device sio1 at nec? port 0x00d1 tty irq ? vector siointr 117 * device sio2 at nec? port 0x00d5 tty irq ? vector siointr 118 * ... you can leave these lines `irq ?', irq will be autodetected. 119 */ 120#ifdef PC98 121#define MC16550 0 122#define COM_IF_INTERNAL 1 123#if 0 124#define COM_IF_PC9861K 2 125#define COM_IF_PIO9032B 3 126#endif 127#ifdef B98_01 128#undef COM_MULTIPORT /* COM_MULTIPORT will conflict with B98_01 */ 129#define COM_IF_B98_01 4 130#endif /* B98_01 */ 131#endif /* PC98 */ 132 133#include <sys/param.h> 134#include <sys/systm.h> 135#include <sys/reboot.h> 136#include <sys/malloc.h> 137#include <sys/tty.h> 138#include <sys/proc.h> 139#include <sys/conf.h> 140#include <sys/dkstat.h> 141#include <sys/fcntl.h> 142#include <sys/interrupt.h> 143#include <sys/kernel.h> 144#include <sys/syslog.h> 145#include <sys/sysctl.h> 146#ifdef DEVFS 147#include <sys/devfsext.h> 148#endif 149 150#include <machine/clock.h> 151#include <machine/ipl.h> 152 153#ifdef PC98 154#include <pc98/pc98/pc98.h> 155#include <pc98/pc98/pc98_machdep.h> 156#include <i386/isa/icu.h> 157#include <i386/isa/isa_device.h> 158#include <pc98/pc98/sioreg.h> 159#include <i386/isa/ic/i8251.h> 160#else 161#include <i386/isa/isa.h> 162#include <i386/isa/isa_device.h> 163#include <i386/isa/sioreg.h> 164#endif 165#include <i386/isa/intr_machdep.h> 166 167#ifdef COM_ESP 168#include <i386/isa/ic/esp.h> 169#endif 170#include <i386/isa/ic/ns16550.h> 171 172#include "card.h" 173#if NCARD > 0 174#include <pccard/cardinfo.h> 175#include <pccard/slot.h> 176#endif 177 178#if NPNP > 0 179#include <i386/isa/pnp.h> 180#endif 181 182#ifdef SMP 183#define disable_intr() COM_DISABLE_INTR() 184#define enable_intr() COM_ENABLE_INTR() 185#endif /* SMP */ 186 187#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 188#define RS_IBUFSIZE 256 189 190#define CALLOUT_MASK 0x80 191#define CONTROL_MASK 0x60 192#define CONTROL_INIT_STATE 0x20 193#define CONTROL_LOCK_STATE 0x40 194#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 195#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 196#define MINOR_TO_UNIT(mynor) ((mynor) & ~MINOR_MAGIC_MASK) 197 198#ifdef COM_MULTIPORT 199/* checks in flags for multiport and which is multiport "master chip" 200 * for a given card 201 */ 202#define COM_ISMULTIPORT(dev) ((dev)->id_flags & 0x01) 203#define COM_MPMASTER(dev) (((dev)->id_flags >> 8) & 0x0ff) 204#define COM_NOTAST4(dev) ((dev)->id_flags & 0x04) 205#endif /* COM_MULTIPORT */ 206 207#define COM_CONSOLE(dev) ((dev)->id_flags & 0x10) 208#define COM_FORCECONSOLE(dev) ((dev)->id_flags & 0x20) 209#define COM_LLCONSOLE(dev) ((dev)->id_flags & 0x40) 210#define COM_LOSESOUTINTS(dev) ((dev)->id_flags & 0x08) 211#define COM_NOFIFO(dev) ((dev)->id_flags & 0x02) 212#define COM_ST16650A(dev) ((dev)->id_flags & 0x20000) 213#define COM_C_NOPROBE (0x40000) 214#define COM_NOPROBE(dev) ((dev)->id_flags & COM_C_NOPROBE) 215#define COM_C_IIR_TXRDYBUG (0x80000) 216#define COM_IIR_TXRDYBUG(dev) ((dev)->id_flags & COM_C_IIR_TXRDYBUG) 217#define COM_FIFOSIZE(dev) (((dev)->id_flags & 0xff000000) >> 24) 218 219#ifndef PC98 220#define com_scr 7 /* scratch register for 16450-16550 (R/W) */ 221#endif /* !PC98 */ 222 223/* 224 * Input buffer watermarks. 225 * The external device is asked to stop sending when the buffer exactly reaches 226 * high water, or when the high level requests it. 227 * The high level is notified immediately (rather than at a later clock tick) 228 * when this watermark is reached. 229 * The buffer size is chosen so the watermark should almost never be reached. 230 * The low watermark is invisibly 0 since the buffer is always emptied all at 231 * once. 232 */ 233#define RS_IHIGHWATER (3 * RS_IBUFSIZE / 4) 234 235/* 236 * com state bits. 237 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 238 * than the other bits so that they can be tested as a group without masking 239 * off the low bits. 240 * 241 * The following com and tty flags correspond closely: 242 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and 243 * siostop()) 244 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) 245 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 246 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 247 * TS_FLUSH is not used. 248 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 249 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 250 */ 251#define CS_BUSY 0x80 /* output in progress */ 252#define CS_TTGO 0x40 /* output not stopped by XOFF */ 253#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 254#define CS_CHECKMSR 1 /* check of MSR scheduled */ 255#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 256#define CS_DTR_OFF 0x10 /* DTR held off */ 257#define CS_ODONE 4 /* output completed */ 258#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 259#define CSE_BUSYCHECK 1 /* siobusycheck() scheduled */ 260 261static char const * const error_desc[] = { 262#define CE_OVERRUN 0 263 "silo overflow", 264#define CE_INTERRUPT_BUF_OVERFLOW 1 265 "interrupt-level buffer overflow", 266#define CE_TTY_BUF_OVERFLOW 2 267 "tty-level buffer overflow", 268}; 269 270#define CE_NTYPES 3 271#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 272 273/* types. XXX - should be elsewhere */ 274typedef u_int Port_t; /* hardware port */ 275typedef u_char bool_t; /* boolean */ 276 277/* queue of linear buffers */ 278struct lbq { 279 u_char *l_head; /* next char to process */ 280 u_char *l_tail; /* one past the last char to process */ 281 struct lbq *l_next; /* next in queue */ 282 bool_t l_queued; /* nonzero if queued */ 283}; 284 285/* com device structure */ 286struct com_s { 287 u_int id_flags; /* Copy isa device falgas */ 288 u_char state; /* miscellaneous flag bits */ 289 bool_t active_out; /* nonzero if the callout device is open */ 290 u_char cfcr_image; /* copy of value written to CFCR */ 291#ifdef COM_ESP 292 bool_t esp; /* is this unit a hayes esp board? */ 293#endif 294 u_char extra_state; /* more flag bits, separate for order trick */ 295 u_char fifo_image; /* copy of value written to FIFO */ 296 bool_t hasfifo; /* nonzero for 16550 UARTs */ 297 bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */ 298 bool_t loses_outints; /* nonzero if device loses output interrupts */ 299 u_char mcr_image; /* copy of value written to MCR */ 300#ifdef COM_MULTIPORT 301 bool_t multiport; /* is this unit part of a multiport device? */ 302#endif /* COM_MULTIPORT */ 303 bool_t no_irq; /* nonzero if irq is not attached */ 304 bool_t gone; /* hardware disappeared */ 305 bool_t poll; /* nonzero if polling is required */ 306 bool_t poll_output; /* nonzero if polling for output is required */ 307 int unit; /* unit number */ 308 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 309 u_int tx_fifo_size; 310 u_int wopeners; /* # processes waiting for DCD in open() */ 311 312 /* 313 * The high level of the driver never reads status registers directly 314 * because there would be too many side effects to handle conveniently. 315 * Instead, it reads copies of the registers stored here by the 316 * interrupt handler. 317 */ 318 u_char last_modem_status; /* last MSR read by intr handler */ 319 u_char prev_modem_status; /* last MSR handled by high level */ 320 321 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 322 u_char *ibuf; /* start of input buffer */ 323 u_char *ibufend; /* end of input buffer */ 324 u_char *ihighwater; /* threshold in input buffer */ 325 u_char *iptr; /* next free spot in input buffer */ 326 327 struct lbq obufq; /* head of queue of output buffers */ 328 struct lbq obufs[2]; /* output buffers */ 329 330#ifdef PC98 331 Port_t cmd_port; 332 Port_t sts_port; 333 Port_t in_modem_port; 334 Port_t intr_ctrl_port; 335 int intr_enable; 336 int pc98_prev_modem_status; 337 int pc98_modem_delta; 338 int modem_car_chg_timer; 339 int pc98_prev_siocmd; 340 int pc98_prev_siomod; 341 int modem_checking; 342 int pc98_if_type; 343#endif /* PC98 */ 344 Port_t data_port; /* i/o ports */ 345#ifdef COM_ESP 346 Port_t esp_port; 347#endif 348 Port_t int_id_port; 349 Port_t iobase; 350 Port_t modem_ctl_port; 351 Port_t line_status_port; 352 Port_t modem_status_port; 353 Port_t intr_ctl_port; /* Ports of IIR register */ 354 355 struct tty *tp; /* cross reference */ 356 357 /* Initial state. */ 358 struct termios it_in; /* should be in struct tty */ 359 struct termios it_out; 360 361 /* Lock state. */ 362 struct termios lt_in; /* should be in struct tty */ 363 struct termios lt_out; 364 365 bool_t do_timestamp; 366 bool_t do_dcd_timestamp; 367 struct timeval timestamp; 368 struct timeval dcd_timestamp; 369 370 u_long bytes_in; /* statistics */ 371 u_long bytes_out; 372 u_int delta_error_counts[CE_NTYPES]; 373 u_long error_counts[CE_NTYPES]; 374 375 /* 376 * Ping-pong input buffers. The extra factor of 2 in the sizes is 377 * to allow for an error byte for each input byte. 378 */ 379#define CE_INPUT_OFFSET RS_IBUFSIZE 380 u_char ibuf1[2 * RS_IBUFSIZE]; 381 u_char ibuf2[2 * RS_IBUFSIZE]; 382 383 /* 384 * Data area for output buffers. Someday we should build the output 385 * buffer queue without copying data. 386 */ 387 u_char obuf1[256]; 388 u_char obuf2[256]; 389#ifdef DEVFS 390 void *devfs_token_ttyd; 391 void *devfs_token_ttyl; 392 void *devfs_token_ttyi; 393 void *devfs_token_cuaa; 394 void *devfs_token_cual; 395 void *devfs_token_cuai; 396#endif 397}; 398 399#ifdef COM_ESP 400static int espattach __P((struct isa_device *isdp, struct com_s *com, 401 Port_t esp_port)); 402#endif 403static int sioattach __P((struct isa_device *dev)); 404static timeout_t siobusycheck; 405static timeout_t siodtrwakeup; 406static void comhardclose __P((struct com_s *com)); 407static void siointr1 __P((struct com_s *com)); 408static int commctl __P((struct com_s *com, int bits, int how)); 409static int comparam __P((struct tty *tp, struct termios *t)); 410static swihand_t siopoll; 411static int sioprobe __P((struct isa_device *dev)); 412static void siosettimeout __P((void)); 413static void comstart __P((struct tty *tp)); 414static timeout_t comwakeup; 415static void disc_optim __P((struct tty *tp, struct termios *t, 416 struct com_s *com)); 417 418#ifdef DSI_SOFT_MODEM 419static int LoadSoftModem __P((int unit,int base_io, u_long size, u_char *ptr)); 420#endif /* DSI_SOFT_MODEM */ 421 422static char driver_name[] = "sio"; 423 424/* table and macro for fast conversion from a unit number to its com struct */ 425static struct com_s *p_com_addr[NSIOTOT]; 426#define com_addr(unit) (p_com_addr[unit]) 427 428struct isa_driver siodriver = { 429 sioprobe, sioattach, driver_name 430}; 431 432static d_open_t sioopen; 433static d_close_t sioclose; 434static d_read_t sioread; 435static d_write_t siowrite; 436static d_ioctl_t sioioctl; 437static d_stop_t siostop; 438static d_devtotty_t siodevtotty; 439 440#define CDEV_MAJOR 28 441static struct cdevsw sio_cdevsw = { 442 sioopen, sioclose, sioread, siowrite, 443 sioioctl, siostop, noreset, siodevtotty, 444 ttpoll, nommap, NULL, driver_name, 445 NULL, -1, 446}; 447 448static int comconsole = -1; 449static volatile speed_t comdefaultrate = CONSPEED; 450static u_int com_events; /* input chars + weighted output completions */ 451static Port_t siocniobase; 452static bool_t sio_registered; 453static int sio_timeout; 454static int sio_timeouts_until_log; 455static struct callout_handle sio_timeout_handle 456 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 457#if 0 /* XXX */ 458static struct tty *sio_tty[NSIOTOT]; 459#else 460static struct tty sio_tty[NSIOTOT]; 461#endif 462static const int nsio_tty = NSIOTOT; 463 464#ifdef PC98 465struct siodev { 466 short if_type; 467 short irq; 468 Port_t cmd, sts, ctrl, mod; 469 }; 470static int sysclock; 471static short port_table[5][3] = { 472 {0x30, 0xb1, 0xb9}, 473 {0x32, 0xb3, 0xbb}, 474 {0x32, 0xb3, 0xbb}, 475 {0x33, 0xb0, 0xb2}, 476 {0x35, 0xb0, 0xb2} 477 }; 478#define PC98SIO_data_port(ch) port_table[0][ch] 479#define PC98SIO_cmd_port(ch) port_table[1][ch] 480#define PC98SIO_sts_port(ch) port_table[2][ch] 481#define PC98SIO_in_modem_port(ch) port_table[3][ch] 482#define PC98SIO_intr_ctrl_port(ch) port_table[4][ch] 483#ifdef COM_IF_PIO9032B 484#define IO_COM_PIO9032B_2 0x0b8 485#define IO_COM_PIO9032B_3 0x0ba 486#endif /* COM_IF_PIO9032B */ 487#ifdef COM_IF_B98_01 488#define IO_COM_B98_01_2 0x0d1 489#define IO_COM_B98_01_3 0x0d5 490#endif /* COM_IF_B98_01 */ 491#define COM_INT_DISABLE {int previpri; previpri=spltty(); 492#define COM_INT_ENABLE splx(previpri);} 493#define IEN_TxFLAG IEN_Tx 494 495#define COM_CARRIER_DETECT_EMULATE 0 496#define PC98_CHECK_MODEM_INTERVAL (hz/10) 497#define DCD_OFF_TOLERANCE 2 498#define DCD_ON_RECOGNITION 2 499#define IS_8251(type) (type != MC16550) 500#define IS_PC98IN(adr) (adr == 0x30) 501 502static void commint __P((dev_t dev)); 503static void com_tiocm_set __P((struct com_s *com, int msr)); 504static void com_tiocm_bis __P((struct com_s *com, int msr)); 505static void com_tiocm_bic __P((struct com_s *com, int msr)); 506static int com_tiocm_get __P((struct com_s *com)); 507static int com_tiocm_get_delta __P((struct com_s *com)); 508static void pc98_msrint_start __P((dev_t dev)); 509static void com_cflag_and_speed_set __P((struct com_s *com, int cflag, int speed)); 510static int pc98_ttspeedtab __P((struct com_s *com, int speed)); 511static int pc98_get_modem_status __P((struct com_s *com)); 512static timeout_t pc98_check_msr; 513static void pc98_set_baud_rate __P((struct com_s *com, int count)); 514static void pc98_i8251_reset __P((struct com_s *com, int mode, int command)); 515static void pc98_disable_i8251_interrupt __P((struct com_s *com, int mod)); 516static void pc98_enable_i8251_interrupt __P((struct com_s *com, int mod)); 517static int pc98_check_i8251_interrupt __P((struct com_s *com)); 518static int pc98_i8251_get_cmd __P((struct com_s *com)); 519static int pc98_i8251_get_mod __P((struct com_s *com)); 520static void pc98_i8251_set_cmd __P((struct com_s *com, int x)); 521static void pc98_i8251_or_cmd __P((struct com_s *com, int x)); 522static void pc98_i8251_clear_cmd __P((struct com_s *com, int x)); 523static void pc98_i8251_clear_or_cmd __P((struct com_s *com, int clr, int x)); 524static int pc98_check_if_type __P((int iobase, struct siodev *iod)); 525static void pc98_check_sysclock __P((void)); 526static int pc98_set_ioport __P((struct com_s *com, int io_base)); 527 528#define com_int_Tx_disable(com) \ 529 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP) 530#define com_int_Tx_enable(com) \ 531 pc98_enable_i8251_interrupt(com,IEN_TxFLAG) 532#define com_int_Rx_disable(com) \ 533 pc98_disable_i8251_interrupt(com,IEN_Rx) 534#define com_int_Rx_enable(com) \ 535 pc98_enable_i8251_interrupt(com,IEN_Rx) 536#define com_int_TxRx_disable(com) \ 537 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP|IEN_Rx) 538#define com_int_TxRx_enable(com) \ 539 pc98_enable_i8251_interrupt(com,IEN_TxFLAG|IEN_Rx) 540#define com_send_break_on(com) \ 541 pc98_i8251_or_cmd(com,CMD8251_SBRK) 542#define com_send_break_off(com) \ 543 pc98_i8251_clear_cmd(com,CMD8251_SBRK) 544 545struct speedtab pc98speedtab[] = { /* internal RS232C interface */ 546 0, 0, 547 50, 50, 548 75, 75, 549 150, 150, 550 200, 200, 551 300, 300, 552 600, 600, 553 1200, 1200, 554 2400, 2400, 555 4800, 4800, 556 9600, 9600, 557 19200, 19200, 558 38400, 38400, 559 76800, 76800, 560 20800, 20800, 561 41600, 41600, 562 15600, 15600, 563 31200, 31200, 564 62400, 62400, 565 -1, -1 566}; 567#ifdef COM_IF_PIO9032B 568struct speedtab comspeedtab_pio9032b[] = { 569 300, 6, 570 600, 5, 571 1200, 4, 572 2400, 3, 573 4800, 2, 574 9600, 1, 575 19200, 0, 576 38400, 7, 577 -1, -1 578}; 579#endif 580 581#ifdef COM_IF_B98_01 582struct speedtab comspeedtab_b98_01[] = { 583 0, 0, 584 75, 15, 585 150, 14, 586 300, 13, 587 600, 12, 588 1200, 11, 589 2400, 10, 590 4800, 9, 591 9600, 8, 592 19200, 7, 593 38400, 6, 594 76800, 5, 595 153600, 4, 596 -1, -1 597}; 598#endif 599#endif /* PC98 */ 600 601static struct speedtab comspeedtab[] = { 602 { 0, 0 }, 603 { 50, COMBRD(50) }, 604 { 75, COMBRD(75) }, 605 { 110, COMBRD(110) }, 606 { 134, COMBRD(134) }, 607 { 150, COMBRD(150) }, 608 { 200, COMBRD(200) }, 609 { 300, COMBRD(300) }, 610 { 600, COMBRD(600) }, 611 { 1200, COMBRD(1200) }, 612 { 1800, COMBRD(1800) }, 613 { 2400, COMBRD(2400) }, 614 { 4800, COMBRD(4800) }, 615 { 9600, COMBRD(9600) }, 616 { 19200, COMBRD(19200) }, 617 { 38400, COMBRD(38400) }, 618 { 57600, COMBRD(57600) }, 619 { 115200, COMBRD(115200) }, 620 { -1, -1 } 621}; 622 623#ifdef COM_ESP 624/* XXX configure this properly. */ 625static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, }; 626static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 }; 627#endif 628 629/* 630 * handle sysctl read/write requests for console speed 631 * 632 * In addition to setting comdefaultrate for I/O through /dev/console, 633 * also set the initial and lock values for the /dev/ttyXX device 634 * if there is one associated with the console. Finally, if the /dev/tty 635 * device has already been open, change the speed on the open running port 636 * itself. 637 */ 638 639static int 640sysctl_machdep_comdefaultrate SYSCTL_HANDLER_ARGS 641{ 642 int error, s; 643 speed_t newspeed; 644 struct com_s *com; 645 struct tty *tp; 646 647 newspeed = comdefaultrate; 648 649 error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req); 650 if (error || !req->newptr) 651 return (error); 652 653 comdefaultrate = newspeed; 654 655 if (comconsole < 0) /* serial console not selected? */ 656 return (0); 657 658 com = com_addr(comconsole); 659 if (!com) 660 return (ENXIO); 661 662 /* 663 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX 664 * (note, the lock rates really are boolean -- if non-zero, disallow 665 * speed changes) 666 */ 667 com->it_in.c_ispeed = com->it_in.c_ospeed = 668 com->lt_in.c_ispeed = com->lt_in.c_ospeed = 669 com->it_out.c_ispeed = com->it_out.c_ospeed = 670 com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate; 671 672 /* 673 * if we're open, change the running rate too 674 */ 675 tp = com->tp; 676 if (tp && (tp->t_state & TS_ISOPEN)) { 677 tp->t_termios.c_ispeed = 678 tp->t_termios.c_ospeed = comdefaultrate; 679 s = spltty(); 680 error = comparam(tp, &tp->t_termios); 681 splx(s); 682 } 683 return error; 684} 685 686SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW, 687 0, 0, sysctl_machdep_comdefaultrate, "I", ""); 688 689#if NCARD > 0 690/* 691 * PC-Card (PCMCIA) specific code. 692 */ 693static int sioinit __P((struct pccard_devinfo *)); 694static void siounload __P((struct pccard_devinfo *)); 695static int card_intr __P((struct pccard_devinfo *)); 696 697static struct pccard_device sio_info = { 698 driver_name, 699 sioinit, 700 siounload, 701 card_intr, 702 0, /* Attributes - presently unused */ 703 &tty_imask /* Interrupt mask for device */ 704 /* XXX - Should this also include net_imask? */ 705}; 706 707DATA_SET(pccarddrv_set, sio_info); 708 709/* 710 * Initialize the device - called from Slot manager. 711 */ 712int 713sioinit(struct pccard_devinfo *devi) 714{ 715 716 /* validate unit number. */ 717 if (devi->isahd.id_unit >= (NSIOTOT)) 718 return(ENODEV); 719 /* Make sure it isn't already probed. */ 720 if (com_addr(devi->isahd.id_unit)) 721 return(EBUSY); 722 723 /* It's already probed as serial by Upper */ 724 devi->isahd.id_flags |= COM_C_NOPROBE; 725 726 /* 727 * Probe the device. If a value is returned, the 728 * device was found at the location. 729 */ 730 if (sioprobe(&devi->isahd) == 0) 731 return(ENXIO); 732 if (sioattach(&devi->isahd) == 0) 733 return(ENXIO); 734 735 return(0); 736} 737 738/* 739 * siounload - unload the driver and clear the table. 740 * XXX TODO: 741 * This is usually called when the card is ejected, but 742 * can be caused by a modunload of a controller driver. 743 * The idea is to reset the driver's view of the device 744 * and ensure that any driver entry points such as 745 * read and write do not hang. 746 */ 747static void 748siounload(struct pccard_devinfo *devi) 749{ 750 struct com_s *com; 751 752 if (!devi) { 753 printf("NULL devi in siounload\n"); 754 return; 755 } 756 com = com_addr(devi->isahd.id_unit); 757 if (!com) { 758 printf("NULL com in siounload\n"); 759 return; 760 } 761 if (!com->iobase) { 762 printf("sio%d already unloaded!\n",devi->isahd.id_unit); 763 return; 764 } 765 if (com->tp && (com->tp->t_state & TS_ISOPEN)) { 766 com->gone = 1; 767 printf("sio%d: unload\n", devi->isahd.id_unit); 768 com->tp->t_gen++; 769 ttyclose(com->tp); 770 ttwakeup(com->tp); 771 ttwwakeup(com->tp); 772 } else { 773 com_addr(com->unit) = NULL; 774 bzero(com, sizeof *com); 775 free(com,M_TTYS); 776 printf("sio%d: unload,gone\n", devi->isahd.id_unit); 777 } 778} 779 780/* 781 * card_intr - Shared interrupt called from 782 * front end of PC-Card handler. 783 */ 784static int 785card_intr(struct pccard_devinfo *devi) 786{ 787 struct com_s *com; 788 789 COM_LOCK(); 790 com = com_addr(devi->isahd.id_unit); 791 if (com && !com->gone) 792 siointr1(com_addr(devi->isahd.id_unit)); 793 COM_UNLOCK(); 794 return(1); 795} 796#endif /* NCARD > 0 */ 797 798static int 799sioprobe(dev) 800 struct isa_device *dev; 801{ 802 static bool_t already_init; 803 bool_t failures[10]; 804 int fn; 805 struct isa_device *idev; 806 Port_t iobase; 807 intrmask_t irqmap[4]; 808 intrmask_t irqs; 809 u_char mcr_image; 810 int result; 811 struct isa_device *xdev; 812#ifdef PC98 813 int irqout=0; 814 int ret = 0; 815 int tmp; 816 struct siodev iod; 817#endif 818 819 if (!already_init) { 820 /* 821 * Turn off MCR_IENABLE for all likely serial ports. An unused 822 * port with its MCR_IENABLE gate open will inhibit interrupts 823 * from any used port that shares the interrupt vector. 824 * XXX the gate enable is elsewhere for some multiports. 825 */ 826 for (xdev = isa_devtab_tty; xdev->id_driver != NULL; xdev++) 827 if (xdev->id_driver == &siodriver && xdev->id_enabled) 828#ifdef PC98 829 if (IS_PC98IN(xdev->id_iobase)) 830 outb(xdev->id_iobase + 2, 0xf2); 831 else 832#endif 833 outb(xdev->id_iobase + com_mcr, 0); 834 already_init = TRUE; 835 } 836 837 if (COM_LLCONSOLE(dev)) { 838 printf("sio%d: reserved for low-level i/o\n", dev->id_unit); 839 return (0); 840 } 841 842#ifdef PC98 843 DELAY(10); 844 /* 845 * If the port is i8251 UART (internal, B98_01) 846 */ 847 if(pc98_check_if_type(dev->id_iobase, &iod) == -1) 848 return 0; 849 if(IS_8251(iod.if_type)){ 850 if ( iod.irq > 0 ) 851 dev->id_irq = (1 << iod.irq); 852 outb(iod.cmd, 0); 853 DELAY(10); 854 outb(iod.cmd, 0); 855 DELAY(10); 856 outb(iod.cmd, 0); 857 DELAY(10); 858 outb(iod.cmd, CMD8251_RESET); 859 DELAY(1000); /* for a while...*/ 860 outb(iod.cmd, 0xf2); /* MODE (dummy) */ 861 DELAY(10); 862 outb(iod.cmd, 0x01); /* CMD (dummy) */ 863 DELAY(1000); /* for a while...*/ 864 if (( inb(iod.sts) & STS8251_TxEMP ) == 0 ) { 865 ret = 0; 866 } 867 switch (iod.if_type) { 868 case COM_IF_INTERNAL: 869 COM_INT_DISABLE 870 tmp = ( inb( iod.ctrl ) & ~(IEN_Rx|IEN_TxEMP|IEN_Tx)); 871 outb( iod.ctrl, tmp|IEN_TxEMP ); 872 DELAY(10); 873 ret = isa_irq_pending() ? 4 : 0; 874 outb( iod.ctrl, tmp ); 875 COM_INT_ENABLE 876 break; 877#ifdef COM_IF_B98_01 878 case COM_IF_B98_01: 879 /* B98_01 doesn't activate TxEMP interrupt line 880 when being reset, so we can't check irq pending.*/ 881 ret = 4; 882 break; 883#endif 884 } 885 if (epson_machine_id==0x20) { /* XXX */ 886 ret = 4; 887 } 888 return ret; 889 } 890#endif /* PC98 */ 891 /* 892 * If the device is on a multiport card and has an AST/4 893 * compatible interrupt control register, initialize this 894 * register and prepare to leave MCR_IENABLE clear in the mcr. 895 * Otherwise, prepare to set MCR_IENABLE in the mcr. 896 * Point idev to the device struct giving the correct id_irq. 897 * This is the struct for the master device if there is one. 898 */ 899 idev = dev; 900 mcr_image = MCR_IENABLE; 901#ifdef COM_MULTIPORT 902 if (COM_ISMULTIPORT(dev)) { 903 idev = find_isadev(isa_devtab_tty, &siodriver, 904 COM_MPMASTER(dev)); 905 if (idev == NULL) { 906 printf("sio%d: master device %d not configured\n", 907 dev->id_unit, COM_MPMASTER(dev)); 908 dev->id_irq = 0; 909 idev = dev; 910 } 911#ifndef PC98 912 if (!COM_NOTAST4(dev)) { 913 outb(idev->id_iobase + com_scr, 914 idev->id_irq ? 0x80 : 0); 915 mcr_image = 0; 916 } 917#endif /* !PC98 */ 918 } 919#endif /* COM_MULTIPORT */ 920 if (idev->id_irq == 0) 921 mcr_image = 0; 922 923#ifdef PC98 924 switch(idev->id_irq){ 925 case IRQ3: irqout = 4; break; 926 case IRQ5: irqout = 5; break; 927 case IRQ6: irqout = 6; break; 928 case IRQ12: irqout = 7; break; 929 default: 930 printf("sio%d: irq configuration error\n",dev->id_unit); 931 return (0); 932 } 933 outb(dev->id_iobase+0x1000, irqout); 934#endif 935 bzero(failures, sizeof failures); 936 iobase = dev->id_iobase; 937 938 /* 939 * We don't want to get actual interrupts, just masked ones. 940 * Interrupts from this line should already be masked in the ICU, 941 * but mask them in the processor as well in case there are some 942 * (misconfigured) shared interrupts. 943 */ 944 disable_intr(); 945/* EXTRA DELAY? */ 946 947 /* 948 * Initialize the speed and the word size and wait long enough to 949 * drain the maximum of 16 bytes of junk in device output queues. 950 * The speed is undefined after a master reset and must be set 951 * before relying on anything related to output. There may be 952 * junk after a (very fast) soft reboot and (apparently) after 953 * master reset. 954 * XXX what about the UART bug avoided by waiting in comparam()? 955 * We don't want to to wait long enough to drain at 2 bps. 956 */ 957 if (iobase == siocniobase) 958 DELAY((16 + 1) * 1000000 / (comdefaultrate / 10)); 959 else { 960 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 961 outb(iobase + com_dlbl, COMBRD(SIO_TEST_SPEED) & 0xff); 962 outb(iobase + com_dlbh, (u_int) COMBRD(SIO_TEST_SPEED) >> 8); 963 outb(iobase + com_cfcr, CFCR_8BITS); 964 DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10)); 965 } 966 967 /* 968 * Enable the interrupt gate and disable device interupts. This 969 * should leave the device driving the interrupt line low and 970 * guarantee an edge trigger if an interrupt can be generated. 971 */ 972/* EXTRA DELAY? */ 973 outb(iobase + com_mcr, mcr_image); 974 outb(iobase + com_ier, 0); 975 DELAY(1000); /* XXX */ 976 irqmap[0] = isa_irq_pending(); 977 978 /* 979 * Attempt to set loopback mode so that we can send a null byte 980 * without annoying any external device. 981 */ 982/* EXTRA DELAY? */ 983 outb(iobase + com_mcr, mcr_image | MCR_LOOPBACK); 984 985 /* 986 * Attempt to generate an output interrupt. On 8250's, setting 987 * IER_ETXRDY generates an interrupt independent of the current 988 * setting and independent of whether the THR is empty. On 16450's, 989 * setting IER_ETXRDY generates an interrupt independent of the 990 * current setting. On 16550A's, setting IER_ETXRDY only 991 * generates an interrupt when IER_ETXRDY is not already set. 992 */ 993 outb(iobase + com_ier, IER_ETXRDY); 994 995 /* 996 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate 997 * an interrupt. They'd better generate one for actually doing 998 * output. Loopback may be broken on the same incompatibles but 999 * it's unlikely to do more than allow the null byte out. 1000 */ 1001 outb(iobase + com_data, 0); 1002 DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10)); 1003 1004 /* 1005 * Turn off loopback mode so that the interrupt gate works again 1006 * (MCR_IENABLE was hidden). This should leave the device driving 1007 * an interrupt line high. It doesn't matter if the interrupt 1008 * line oscillates while we are not looking at it, since interrupts 1009 * are disabled. 1010 */ 1011/* EXTRA DELAY? */ 1012 outb(iobase + com_mcr, mcr_image); 1013 1014 /* 1015 * It's a definitly Serial PCMCIA(16550A), but still be required 1016 * for IIR_TXRDY implementation ( Palido 321s, DC-1S... ) 1017 */ 1018 if ( COM_NOPROBE(dev) ) { 1019 /* Reading IIR register twice */ 1020 for ( fn = 0; fn < 2; fn ++ ) { 1021 DELAY(10000); 1022 failures[6] = inb(iobase + com_iir); 1023 } 1024 /* Check IIR_TXRDY clear ? */ 1025 result = IO_COMSIZE; 1026 if ( failures[6] & IIR_TXRDY ) { 1027 /* Nop, Double check with clearing IER */ 1028 outb(iobase + com_ier, 0); 1029 if ( inb(iobase + com_iir) & IIR_NOPEND ) { 1030 /* Ok. we're familia this gang */ 1031 dev->id_flags |= COM_C_IIR_TXRDYBUG; /* Set IIR_TXRDYBUG */ 1032 } else { 1033 /* Unknow, Just omit this chip.. XXX*/ 1034 result = 0; 1035 } 1036 } else { 1037 /* OK. this is well-known guys */ 1038 dev->id_flags &= ~COM_C_IIR_TXRDYBUG; /*Clear IIR_TXRDYBUG*/ 1039 } 1040 outb(iobase + com_cfcr, CFCR_8BITS); 1041 enable_intr(); 1042 return (iobase == siocniobase ? IO_COMSIZE : result); 1043 } 1044 1045 /* 1046 * Check that 1047 * o the CFCR, IER and MCR in UART hold the values written to them 1048 * (the values happen to be all distinct - this is good for 1049 * avoiding false positive tests from bus echoes). 1050 * o an output interrupt is generated and its vector is correct. 1051 * o the interrupt goes away when the IIR in the UART is read. 1052 */ 1053/* EXTRA DELAY? */ 1054 failures[0] = inb(iobase + com_cfcr) - CFCR_8BITS; 1055 failures[1] = inb(iobase + com_ier) - IER_ETXRDY; 1056 failures[2] = inb(iobase + com_mcr) - mcr_image; 1057 DELAY(10000); /* Some internal modems need this time */ 1058 irqmap[1] = isa_irq_pending(); 1059 failures[4] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_TXRDY; 1060 DELAY(1000); /* XXX */ 1061 irqmap[2] = isa_irq_pending(); 1062 failures[6] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; 1063 1064 /* 1065 * Turn off all device interrupts and check that they go off properly. 1066 * Leave MCR_IENABLE alone. For ports without a master port, it gates 1067 * the OUT2 output of the UART to 1068 * the ICU input. Closing the gate would give a floating ICU input 1069 * (unless there is another device driving at) and spurious interrupts. 1070 * (On the system that this was first tested on, the input floats high 1071 * and gives a (masked) interrupt as soon as the gate is closed.) 1072 */ 1073 outb(iobase + com_ier, 0); 1074 outb(iobase + com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */ 1075 failures[7] = inb(iobase + com_ier); 1076 DELAY(1000); /* XXX */ 1077 irqmap[3] = isa_irq_pending(); 1078 failures[9] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; 1079 1080 enable_intr(); 1081 1082 irqs = irqmap[1] & ~irqmap[0]; 1083 if (idev->id_irq != 0 && (idev->id_irq & irqs) == 0) 1084 printf( 1085 "sio%d: configured irq %d not in bitmap of probed irqs %#x\n", 1086 dev->id_unit, ffs(idev->id_irq) - 1, irqs); 1087 if (bootverbose) 1088 printf("sio%d: irq maps: %#x %#x %#x %#x\n", 1089 dev->id_unit, irqmap[0], irqmap[1], irqmap[2], irqmap[3]); 1090 1091 result = IO_COMSIZE; 1092 for (fn = 0; fn < sizeof failures; ++fn) 1093 if (failures[fn]) { 1094 outb(iobase + com_mcr, 0); 1095 result = 0; 1096 if (bootverbose) { 1097 printf("sio%d: probe failed test(s):", 1098 dev->id_unit); 1099 for (fn = 0; fn < sizeof failures; ++fn) 1100 if (failures[fn]) 1101 printf(" %d", fn); 1102 printf("\n"); 1103 } 1104 break; 1105 } 1106 return (iobase == siocniobase ? IO_COMSIZE : result); 1107} 1108 1109#ifdef COM_ESP 1110static int 1111espattach(isdp, com, esp_port) 1112 struct isa_device *isdp; 1113 struct com_s *com; 1114 Port_t esp_port; 1115{ 1116 u_char dips; 1117 u_char val; 1118 1119 /* 1120 * Check the ESP-specific I/O port to see if we're an ESP 1121 * card. If not, return failure immediately. 1122 */ 1123 if ((inb(esp_port) & 0xf3) == 0) { 1124 printf(" port 0x%x is not an ESP board?\n", esp_port); 1125 return (0); 1126 } 1127 1128 /* 1129 * We've got something that claims to be a Hayes ESP card. 1130 * Let's hope so. 1131 */ 1132 1133 /* Get the dip-switch configuration */ 1134 outb(esp_port + ESP_CMD1, ESP_GETDIPS); 1135 dips = inb(esp_port + ESP_STATUS1); 1136 1137 /* 1138 * Bits 0,1 of dips say which COM port we are. 1139 */ 1140 if (com->iobase == likely_com_ports[dips & 0x03]) 1141 printf(" : ESP"); 1142 else { 1143 printf(" esp_port has com %d\n", dips & 0x03); 1144 return (0); 1145 } 1146 1147 /* 1148 * Check for ESP version 2.0 or later: bits 4,5,6 = 010. 1149 */ 1150 outb(esp_port + ESP_CMD1, ESP_GETTEST); 1151 val = inb(esp_port + ESP_STATUS1); /* clear reg 1 */ 1152 val = inb(esp_port + ESP_STATUS2); 1153 if ((val & 0x70) < 0x20) { 1154 printf("-old (%o)", val & 0x70); 1155 return (0); 1156 } 1157 1158 /* 1159 * Check for ability to emulate 16550: bit 7 == 1 1160 */ 1161 if ((dips & 0x80) == 0) { 1162 printf(" slave"); 1163 return (0); 1164 } 1165 1166 /* 1167 * Okay, we seem to be a Hayes ESP card. Whee. 1168 */ 1169 com->esp = TRUE; 1170 com->esp_port = esp_port; 1171 return (1); 1172} 1173#endif /* COM_ESP */ 1174 1175static int 1176sioattach(isdp) 1177 struct isa_device *isdp; 1178{ 1179 struct com_s *com; 1180 dev_t dev; 1181#ifdef COM_ESP 1182 Port_t *espp; 1183#endif 1184 Port_t iobase; 1185 int s; 1186 int unit; 1187 1188 isdp->id_ri_flags |= RI_FAST; 1189 iobase = isdp->id_iobase; 1190 unit = isdp->id_unit; 1191 com = malloc(sizeof *com, M_TTYS, M_NOWAIT); 1192 if (com == NULL) 1193 return (0); 1194 1195 /* 1196 * sioprobe() has initialized the device registers as follows: 1197 * o cfcr = CFCR_8BITS. 1198 * It is most important that CFCR_DLAB is off, so that the 1199 * data port is not hidden when we enable interrupts. 1200 * o ier = 0. 1201 * Interrupts are only enabled when the line is open. 1202 * o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible 1203 * interrupt control register or the config specifies no irq. 1204 * Keeping MCR_DTR and MCR_RTS off might stop the external 1205 * device from sending before we are ready. 1206 */ 1207 bzero(com, sizeof *com); 1208 com->unit = unit; 1209 com->cfcr_image = CFCR_8BITS; 1210 com->dtr_wait = 3 * hz; 1211 com->loses_outints = COM_LOSESOUTINTS(isdp) != 0; 1212 com->no_irq = isdp->id_irq == 0; 1213 com->tx_fifo_size = 1; 1214 com->iptr = com->ibuf = com->ibuf1; 1215 com->ibufend = com->ibuf1 + RS_IBUFSIZE; 1216 com->ihighwater = com->ibuf1 + RS_IHIGHWATER; 1217 com->obufs[0].l_head = com->obuf1; 1218 com->obufs[1].l_head = com->obuf2; 1219 1220 com->iobase = iobase; 1221#ifdef PC98 1222 if(pc98_set_ioport(com, iobase) == -1) 1223 if((iobase & 0x0f0) == 0xd0) { 1224 com->pc98_if_type = MC16550; 1225 com->data_port = iobase + com_data; 1226 com->int_id_port = iobase + com_iir; 1227 com->modem_ctl_port = iobase + com_mcr; 1228 com->mcr_image = inb(com->modem_ctl_port); 1229 com->line_status_port = iobase + com_lsr; 1230 com->modem_status_port = iobase + com_msr; 1231 com->intr_ctl_port = iobase + com_ier; 1232 } 1233#else /* not PC98 */ 1234 com->data_port = iobase + com_data; 1235 com->int_id_port = iobase + com_iir; 1236 com->modem_ctl_port = iobase + com_mcr; 1237 com->mcr_image = inb(com->modem_ctl_port); 1238 com->line_status_port = iobase + com_lsr; 1239 com->modem_status_port = iobase + com_msr; 1240 com->intr_ctl_port = iobase + com_ier; 1241#endif 1242 1243 /* 1244 * We don't use all the flags from <sys/ttydefaults.h> since they 1245 * are only relevant for logins. It's important to have echo off 1246 * initially so that the line doesn't start blathering before the 1247 * echo flag can be turned off. 1248 */ 1249 com->it_in.c_iflag = 0; 1250 com->it_in.c_oflag = 0; 1251 com->it_in.c_cflag = TTYDEF_CFLAG; 1252 com->it_in.c_lflag = 0; 1253 if (unit == comconsole) { 1254#ifdef PC98 1255 if(IS_8251(com->pc98_if_type)) 1256 DELAY(100000); 1257#endif 1258 com->it_in.c_iflag = TTYDEF_IFLAG; 1259 com->it_in.c_oflag = TTYDEF_OFLAG; 1260 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 1261 com->it_in.c_lflag = TTYDEF_LFLAG; 1262 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 1263 com->lt_out.c_ispeed = com->lt_out.c_ospeed = 1264 com->lt_in.c_ispeed = com->lt_in.c_ospeed = 1265 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 1266 } else 1267 com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED; 1268 termioschars(&com->it_in); 1269 com->it_out = com->it_in; 1270 1271 /* attempt to determine UART type */ 1272 printf("sio%d: type", unit); 1273 1274#ifdef DSI_SOFT_MODEM 1275 if((inb(iobase+7) ^ inb(iobase+7)) & 0x80) { 1276 printf(" Digicom Systems, Inc. SoftModem"); 1277 goto determined_type; 1278 } 1279#endif /* DSI_SOFT_MODEM */ 1280 1281#ifndef PC98 1282#ifdef COM_MULTIPORT 1283 if (!COM_ISMULTIPORT(isdp) && !COM_IIR_TXRDYBUG(isdp)) 1284#else 1285 if (!COM_IIR_TXRDYBUG(isdp)) 1286#endif 1287 { 1288 u_char scr; 1289 u_char scr1; 1290 u_char scr2; 1291 1292 scr = inb(iobase + com_scr); 1293 outb(iobase + com_scr, 0xa5); 1294 scr1 = inb(iobase + com_scr); 1295 outb(iobase + com_scr, 0x5a); 1296 scr2 = inb(iobase + com_scr); 1297 outb(iobase + com_scr, scr); 1298 if (scr1 != 0xa5 || scr2 != 0x5a) { 1299 printf(" 8250"); 1300 goto determined_type; 1301 } 1302 } 1303#endif /* !PC98 */ 1304#ifdef PC98 1305 if(IS_8251(com->pc98_if_type)){ 1306 com_int_TxRx_disable( com ); 1307 com_cflag_and_speed_set( com, com->it_in.c_cflag, 1308 comdefaultrate ); 1309 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 1310 com_send_break_off( com ); 1311 switch(com->pc98_if_type){ 1312 case COM_IF_INTERNAL: 1313 printf(" 8251 (internal)"); 1314 break; 1315#ifdef COM_IF_PC9861K 1316 case COM_IF_PC9861K: 1317 printf(" 8251 (PC9861K)"); 1318 break; 1319#endif 1320#ifdef COM_IF_PIO9032B 1321 case COM_IF_PIO9032B: 1322 printf(" 8251 (PIO9032B)"); 1323 break; 1324#endif 1325#ifdef COM_IF_B98_01 1326 case COM_IF_B98_01: 1327 printf(" 8251 (B98_01)"); 1328 break; 1329#endif 1330 } 1331 } else { 1332#endif /* PC98 */ 1333 outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RX_HIGH); 1334 DELAY(100); 1335 com->st16650a = 0; 1336 switch (inb(com->int_id_port) & IIR_FIFO_MASK) { 1337 case FIFO_RX_LOW: 1338 printf(" 16450"); 1339 break; 1340 case FIFO_RX_MEDL: 1341 printf(" 16450?"); 1342 break; 1343 case FIFO_RX_MEDH: 1344 printf(" 16550?"); 1345 break; 1346 case FIFO_RX_HIGH: 1347 if (COM_NOFIFO(isdp)) { 1348 printf(" 16550A fifo disabled"); 1349 } else { 1350 com->hasfifo = TRUE; 1351 if (COM_ST16650A(isdp)) { 1352 com->st16650a = 1; 1353 com->tx_fifo_size = 32; 1354 printf(" ST16650A"); 1355 } else { 1356 com->tx_fifo_size = COM_FIFOSIZE(isdp); 1357 printf(" 16550A"); 1358 } 1359 } 1360#ifdef COM_ESP 1361 for (espp = likely_esp_ports; *espp != 0; espp++) 1362 if (espattach(isdp, com, *espp)) { 1363 com->tx_fifo_size = 1024; 1364 break; 1365 } 1366#endif 1367 if (!com->st16650a) { 1368 if (!com->tx_fifo_size) 1369 com->tx_fifo_size = 16; 1370 else 1371 printf(" lookalike with %d bytes FIFO", 1372 com->tx_fifo_size); 1373 } 1374 1375 break; 1376 } 1377 1378#ifdef COM_ESP 1379 if (com->esp) { 1380 /* 1381 * Set 16550 compatibility mode. 1382 * We don't use the ESP_MODE_SCALE bit to increase the 1383 * fifo trigger levels because we can't handle large 1384 * bursts of input. 1385 * XXX flow control should be set in comparam(), not here. 1386 */ 1387 outb(com->esp_port + ESP_CMD1, ESP_SETMODE); 1388 outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); 1389 1390 /* Set RTS/CTS flow control. */ 1391 outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE); 1392 outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS); 1393 outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS); 1394 1395 /* Set flow-control levels. */ 1396 outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW); 1397 outb(com->esp_port + ESP_CMD2, HIBYTE(768)); 1398 outb(com->esp_port + ESP_CMD2, LOBYTE(768)); 1399 outb(com->esp_port + ESP_CMD2, HIBYTE(512)); 1400 outb(com->esp_port + ESP_CMD2, LOBYTE(512)); 1401 } 1402#endif /* COM_ESP */ 1403 outb(iobase + com_fifo, 0); 1404determined_type: ; 1405 1406#ifdef COM_MULTIPORT 1407 if (COM_ISMULTIPORT(isdp)) { 1408 com->multiport = TRUE; 1409 printf(" (multiport"); 1410 if (unit == COM_MPMASTER(isdp)) 1411 printf(" master"); 1412 printf(")"); 1413 com->no_irq = find_isadev(isa_devtab_tty, &siodriver, 1414 COM_MPMASTER(isdp))->id_irq == 0; 1415 } 1416#endif /* COM_MULTIPORT */ 1417#ifdef PC98 1418 } 1419#endif 1420 if (unit == comconsole) 1421 printf(", console"); 1422 if ( COM_IIR_TXRDYBUG(isdp) ) 1423 printf(" with a bogus IIR_TXRDY register"); 1424 printf("\n"); 1425 1426 s = spltty(); 1427 com_addr(unit) = com; 1428 splx(s); 1429 1430#ifdef DEVFS 1431 com->devfs_token_ttyd = devfs_add_devswf(&sio_cdevsw, 1432 unit, DV_CHR, 1433 UID_ROOT, GID_WHEEL, 0600, "ttyd%r", unit); 1434 com->devfs_token_ttyi = devfs_add_devswf(&sio_cdevsw, 1435 unit | CONTROL_INIT_STATE, DV_CHR, 1436 UID_ROOT, GID_WHEEL, 0600, "ttyid%r", unit); 1437 com->devfs_token_ttyl = devfs_add_devswf(&sio_cdevsw, 1438 unit | CONTROL_LOCK_STATE, DV_CHR, 1439 UID_ROOT, GID_WHEEL, 0600, "ttyld%r", unit); 1440 com->devfs_token_cuaa = devfs_add_devswf(&sio_cdevsw, 1441 unit | CALLOUT_MASK, DV_CHR, 1442 UID_UUCP, GID_DIALER, 0660, "cuaa%r", unit); 1443 com->devfs_token_cuai = devfs_add_devswf(&sio_cdevsw, 1444 unit | CALLOUT_MASK | CONTROL_INIT_STATE, DV_CHR, 1445 UID_UUCP, GID_DIALER, 0660, "cuaia%r", unit); 1446 com->devfs_token_cual = devfs_add_devswf(&sio_cdevsw, 1447 unit | CALLOUT_MASK | CONTROL_LOCK_STATE, DV_CHR, 1448 UID_UUCP, GID_DIALER, 0660, "cuala%r", unit); 1449#endif 1450 if (!sio_registered) { 1451 dev = makedev(CDEV_MAJOR, 0); 1452 cdevsw_add(&dev, &sio_cdevsw, NULL); 1453 register_swi(SWI_TTY, siopoll); 1454 sio_registered = TRUE; 1455 } 1456 com->id_flags = isdp->id_flags; /* Heritate id_flags for later */ 1457 return (1); 1458} 1459 1460static int 1461sioopen(dev, flag, mode, p) 1462 dev_t dev; 1463 int flag; 1464 int mode; 1465 struct proc *p; 1466{ 1467 struct com_s *com; 1468 int error; 1469 Port_t iobase; 1470 int mynor; 1471 int s; 1472 struct tty *tp; 1473 int unit; 1474 1475 mynor = minor(dev); 1476 unit = MINOR_TO_UNIT(mynor); 1477 if ((u_int) unit >= NSIOTOT || (com = com_addr(unit)) == NULL) 1478 return (ENXIO); 1479 if (com->gone) 1480 return (ENXIO); 1481 if (mynor & CONTROL_MASK) 1482 return (0); 1483#if 0 /* XXX */ 1484 tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]); 1485#else 1486 tp = com->tp = &sio_tty[unit]; 1487#endif 1488 s = spltty(); 1489 /* 1490 * We jump to this label after all non-interrupted sleeps to pick 1491 * up any changes of the device state. 1492 */ 1493open_top: 1494 while (com->state & CS_DTR_OFF) { 1495 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0); 1496 if (com_addr(unit) == NULL) 1497 return (ENXIO); 1498 if (error != 0 || com->gone) 1499 goto out; 1500 } 1501 if (tp->t_state & TS_ISOPEN) { 1502 /* 1503 * The device is open, so everything has been initialized. 1504 * Handle conflicts. 1505 */ 1506 if (mynor & CALLOUT_MASK) { 1507 if (!com->active_out) { 1508 error = EBUSY; 1509 goto out; 1510 } 1511 } else { 1512 if (com->active_out) { 1513 if (flag & O_NONBLOCK) { 1514 error = EBUSY; 1515 goto out; 1516 } 1517 error = tsleep(&com->active_out, 1518 TTIPRI | PCATCH, "siobi", 0); 1519 if (com_addr(unit) == NULL) 1520 return (ENXIO); 1521 if (error != 0 || com->gone) 1522 goto out; 1523 goto open_top; 1524 } 1525 } 1526 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { 1527 error = EBUSY; 1528 goto out; 1529 } 1530 } else { 1531 /* 1532 * The device isn't open, so there are no conflicts. 1533 * Initialize it. Initialization is done twice in many 1534 * cases: to preempt sleeping callin opens if we are 1535 * callout, and to complete a callin open after DCD rises. 1536 */ 1537 tp->t_oproc = comstart; 1538 tp->t_param = comparam; 1539 tp->t_dev = dev; 1540 tp->t_termios = mynor & CALLOUT_MASK 1541 ? com->it_out : com->it_in; 1542 tp->t_ififosize = 2 * RS_IBUFSIZE; 1543 tp->t_ispeedwat = (speed_t)-1; 1544 tp->t_ospeedwat = (speed_t)-1; 1545#ifdef PC98 1546 if(!IS_8251(com->pc98_if_type)) 1547#endif 1548 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 1549 com->poll = com->no_irq; 1550 com->poll_output = com->loses_outints; 1551 ++com->wopeners; 1552 error = comparam(tp, &tp->t_termios); 1553 --com->wopeners; 1554 if (error != 0) 1555 goto out; 1556#ifdef PC98 1557 if(IS_8251(com->pc98_if_type)){ 1558 com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS); 1559 pc98_msrint_start(dev); 1560 } 1561#endif 1562 /* 1563 * XXX we should goto open_top if comparam() slept. 1564 */ 1565 iobase = com->iobase; 1566 if (com->hasfifo) { 1567 /* 1568 * (Re)enable and drain fifos. 1569 * 1570 * Certain SMC chips cause problems if the fifos 1571 * are enabled while input is ready. Turn off the 1572 * fifo if necessary to clear the input. We test 1573 * the input ready bit after enabling the fifos 1574 * since we've already enabled them in comparam() 1575 * and to handle races between enabling and fresh 1576 * input. 1577 */ 1578 while (TRUE) { 1579 outb(iobase + com_fifo, 1580 FIFO_RCV_RST | FIFO_XMT_RST 1581 | com->fifo_image); 1582 /* 1583 * XXX the delays are for superstitious 1584 * historical reasons. It must be less than 1585 * the character time at the maximum 1586 * supported speed (87 usec at 115200 bps 1587 * 8N1). Otherwise we might loop endlessly 1588 * if data is streaming in. We used to use 1589 * delays of 100. That usually worked 1590 * because DELAY(100) used to usually delay 1591 * for about 85 usec instead of 100. 1592 */ 1593 DELAY(50); 1594 if (!(inb(com->line_status_port) & LSR_RXRDY)) 1595 break; 1596 outb(iobase + com_fifo, 0); 1597 DELAY(50); 1598 (void) inb(com->data_port); 1599 } 1600 } 1601 1602 disable_intr(); 1603#ifdef PC98 1604 if(IS_8251(com->pc98_if_type)){ 1605 com_tiocm_bis(com, TIOCM_LE); 1606 com->pc98_prev_modem_status = 1607 pc98_get_modem_status(com); 1608 com_int_Rx_enable(com); 1609 } else { 1610#endif 1611 (void) inb(com->line_status_port); 1612 (void) inb(com->data_port); 1613 com->prev_modem_status = com->last_modem_status 1614 = inb(com->modem_status_port); 1615 if (COM_IIR_TXRDYBUG(com)) { 1616 outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS 1617 | IER_EMSC); 1618 } else { 1619 outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY 1620 | IER_ERLS | IER_EMSC); 1621 } 1622#ifdef PC98 1623 } 1624#endif 1625 enable_intr(); 1626 /* 1627 * Handle initial DCD. Callout devices get a fake initial 1628 * DCD (trapdoor DCD). If we are callout, then any sleeping 1629 * callin opens get woken up and resume sleeping on "siobi" 1630 * instead of "siodcd". 1631 */ 1632 /* 1633 * XXX `mynor & CALLOUT_MASK' should be 1634 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 1635 * TRAPDOOR_CARRIER is the default initial state for callout 1636 * devices and SOFT_CARRIER is like CLOCAL except it hides 1637 * the true carrier. 1638 */ 1639#ifdef PC98 1640 if ((IS_8251(com->pc98_if_type) && 1641 (pc98_get_modem_status(com) & TIOCM_CAR)) || 1642 (!IS_8251(com->pc98_if_type) && 1643 (com->prev_modem_status & MSR_DCD)) || 1644 mynor & CALLOUT_MASK) 1645#else 1646 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 1647#endif 1648 (*linesw[tp->t_line].l_modem)(tp, 1); 1649 } 1650 /* 1651 * Wait for DCD if necessary. 1652 */ 1653 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 1654 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 1655 ++com->wopeners; 1656 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0); 1657 if (com_addr(unit) == NULL) 1658 return (ENXIO); 1659 --com->wopeners; 1660 if (error != 0 || com->gone) 1661 goto out; 1662 goto open_top; 1663 } 1664 error = (*linesw[tp->t_line].l_open)(dev, tp); 1665 disc_optim(tp, &tp->t_termios, com); 1666 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 1667 com->active_out = TRUE; 1668 siosettimeout(); 1669out: 1670 splx(s); 1671 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 1672 comhardclose(com); 1673 return (error); 1674} 1675 1676static int 1677sioclose(dev, flag, mode, p) 1678 dev_t dev; 1679 int flag; 1680 int mode; 1681 struct proc *p; 1682{ 1683 struct com_s *com; 1684 int mynor; 1685 int s; 1686 struct tty *tp; 1687 1688 mynor = minor(dev); 1689 if (mynor & CONTROL_MASK) 1690 return (0); 1691 com = com_addr(MINOR_TO_UNIT(mynor)); 1692 tp = com->tp; 1693 s = spltty(); 1694 (*linesw[tp->t_line].l_close)(tp, flag); 1695#ifdef PC98 1696 com->modem_checking = 0; 1697#endif 1698 disc_optim(tp, &tp->t_termios, com); 1699 siostop(tp, FREAD | FWRITE); 1700 comhardclose(com); 1701 ttyclose(tp); 1702 siosettimeout(); 1703 splx(s); 1704 if (com->gone) { 1705 printf("sio%d: gone\n", com->unit); 1706 s = spltty(); 1707 com_addr(com->unit) = 0; 1708 bzero(tp,sizeof *tp); 1709 bzero(com,sizeof *com); 1710 free(com,M_TTYS); 1711 splx(s); 1712 } 1713 return (0); 1714} 1715 1716static void 1717comhardclose(com) 1718 struct com_s *com; 1719{ 1720 Port_t iobase; 1721 int s; 1722 struct tty *tp; 1723 int unit; 1724 1725 unit = com->unit; 1726 iobase = com->iobase; 1727 s = spltty(); 1728 com->poll = FALSE; 1729 com->poll_output = FALSE; 1730 com->do_timestamp = FALSE; 1731 com->do_dcd_timestamp = FALSE; 1732#ifdef PC98 1733 if(IS_8251(com->pc98_if_type)) 1734 com_send_break_off(com); 1735 else 1736#endif 1737 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1738 { 1739#ifdef PC98 1740 int tmp; 1741 if(IS_8251(com->pc98_if_type)) 1742 com_int_TxRx_disable(com); 1743 else 1744#endif 1745 outb(iobase + com_ier, 0); 1746 tp = com->tp; 1747#ifdef PC98 1748 if(IS_8251(com->pc98_if_type)) 1749 tmp = pc98_get_modem_status(com) & TIOCM_CAR; 1750 else 1751 tmp = com->prev_modem_status & MSR_DCD; 1752#endif 1753 if (tp->t_cflag & HUPCL 1754 /* 1755 * XXX we will miss any carrier drop between here and the 1756 * next open. Perhaps we should watch DCD even when the 1757 * port is closed; it is not sufficient to check it at 1758 * the next open because it might go up and down while 1759 * we're not watching. 1760 */ 1761 || !com->active_out 1762#ifdef PC98 1763 && !(tmp) 1764#else 1765 && !(com->prev_modem_status & MSR_DCD) 1766#endif 1767 && !(com->it_in.c_cflag & CLOCAL) 1768 || !(tp->t_state & TS_ISOPEN)) { 1769#ifdef PC98 1770 if(IS_8251(com->pc98_if_type)) 1771 com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE); 1772 else 1773#endif 1774 (void)commctl(com, TIOCM_DTR, DMBIC); 1775 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 1776 timeout(siodtrwakeup, com, com->dtr_wait); 1777 com->state |= CS_DTR_OFF; 1778 } 1779 } 1780#ifdef PC98 1781 else { 1782 if(IS_8251(com->pc98_if_type)) 1783 com_tiocm_bic(com, TIOCM_LE ); 1784 } 1785#endif 1786 } 1787 if (com->hasfifo) { 1788 /* 1789 * Disable fifos so that they are off after controlled 1790 * reboots. Some BIOSes fail to detect 16550s when the 1791 * fifos are enabled. 1792 */ 1793 outb(iobase + com_fifo, 0); 1794 } 1795 com->active_out = FALSE; 1796 wakeup(&com->active_out); 1797 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 1798 splx(s); 1799} 1800 1801static int 1802sioread(dev, uio, flag) 1803 dev_t dev; 1804 struct uio *uio; 1805 int flag; 1806{ 1807 int mynor; 1808 int unit; 1809 struct tty *tp; 1810 1811 mynor = minor(dev); 1812 if (mynor & CONTROL_MASK) 1813 return (ENODEV); 1814 unit = MINOR_TO_UNIT(mynor); 1815 if (com_addr(unit)->gone) 1816 return (ENODEV); 1817 tp = com_addr(unit)->tp; 1818 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 1819} 1820 1821static int 1822siowrite(dev, uio, flag) 1823 dev_t dev; 1824 struct uio *uio; 1825 int flag; 1826{ 1827 int mynor; 1828 struct tty *tp; 1829 int unit; 1830 1831 mynor = minor(dev); 1832 if (mynor & CONTROL_MASK) 1833 return (ENODEV); 1834 1835 unit = MINOR_TO_UNIT(mynor); 1836 if (com_addr(unit)->gone) 1837 return (ENODEV); 1838 tp = com_addr(unit)->tp; 1839 /* 1840 * (XXX) We disallow virtual consoles if the physical console is 1841 * a serial port. This is in case there is a display attached that 1842 * is not the console. In that situation we don't need/want the X 1843 * server taking over the console. 1844 */ 1845 if (constty != NULL && unit == comconsole) 1846 constty = NULL; 1847 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1848} 1849 1850static void 1851siobusycheck(chan) 1852 void *chan; 1853{ 1854 struct com_s *com; 1855 int s; 1856 1857 com = (struct com_s *)chan; 1858 1859 /* 1860 * Clear TS_BUSY if low-level output is complete. 1861 * spl locking is sufficient because siointr1() does not set CS_BUSY. 1862 * If siointr1() clears CS_BUSY after we look at it, then we'll get 1863 * called again. Reading the line status port outside of siointr1() 1864 * is safe because CS_BUSY is clear so there are no output interrupts 1865 * to lose. 1866 */ 1867 s = spltty(); 1868 if (com->state & CS_BUSY) 1869 com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */ 1870#ifdef PC98 1871 else if (IS_8251(com->pc98_if_type) && 1872 (inb(com->sts_port) & (STS8251_TxRDY | STS8251_TxEMP)) 1873 == (STS8251_TxRDY | STS8251_TxEMP) || 1874 (inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 1875 == (LSR_TSRE | LSR_TXRDY)) { 1876#else 1877 else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 1878 == (LSR_TSRE | LSR_TXRDY)) { 1879#endif 1880 com->tp->t_state &= ~TS_BUSY; 1881 ttwwakeup(com->tp); 1882 com->extra_state &= ~CSE_BUSYCHECK; 1883 } else 1884 timeout(siobusycheck, com, hz / 100); 1885 splx(s); 1886} 1887 1888static void 1889siodtrwakeup(chan) 1890 void *chan; 1891{ 1892 struct com_s *com; 1893 1894 com = (struct com_s *)chan; 1895 com->state &= ~CS_DTR_OFF; 1896 wakeup(&com->dtr_wait); 1897} 1898 1899void 1900siointr(unit) 1901 int unit; 1902{ 1903#ifndef COM_MULTIPORT 1904 COM_LOCK(); 1905 siointr1(com_addr(unit)); 1906 COM_UNLOCK(); 1907#else /* COM_MULTIPORT */ 1908 struct com_s *com; 1909 bool_t possibly_more_intrs; 1910 1911 /* 1912 * Loop until there is no activity on any port. This is necessary 1913 * to get an interrupt edge more than to avoid another interrupt. 1914 * If the IRQ signal is just an OR of the IRQ signals from several 1915 * devices, then the edge from one may be lost because another is 1916 * on. 1917 */ 1918 COM_LOCK(); 1919 do { 1920 possibly_more_intrs = FALSE; 1921 for (unit = 0; unit < NSIOTOT; ++unit) { 1922 com = com_addr(unit); 1923 /* 1924 * XXX COM_LOCK(); 1925 * would it work here, or be counter-productive? 1926 */ 1927#ifdef PC98 1928 if (com != NULL 1929 && !com->gone 1930 && IS_8251(com->pc98_if_type)){ 1931 siointr1(com); 1932 } else 1933#endif /* PC98 */ 1934 if (com != NULL 1935 && !com->gone 1936 && (inb(com->int_id_port) & IIR_IMASK) 1937 != IIR_NOPEND) { 1938 siointr1(com); 1939 possibly_more_intrs = TRUE; 1940 } 1941 /* XXX COM_UNLOCK(); */ 1942 } 1943 } while (possibly_more_intrs); 1944 COM_UNLOCK(); 1945#endif /* COM_MULTIPORT */ 1946} 1947 1948static void 1949siointr1(com) 1950 struct com_s *com; 1951{ 1952 u_char line_status; 1953 u_char modem_status; 1954 u_char *ioptr; 1955 u_char recv_data; 1956 u_char int_ident; 1957 u_char int_ctl; 1958 u_char int_ctl_new; 1959 1960#ifdef PC98 1961 u_char tmp=0; 1962recv_data=0; 1963#endif /* PC98 */ 1964 1965 int_ctl = inb(com->intr_ctl_port); 1966 int_ctl_new = int_ctl; 1967 1968 while (!com->gone) { 1969#ifdef PC98 1970status_read:; 1971 if (IS_8251(com->pc98_if_type)) { 1972 tmp = inb(com->sts_port); 1973more_intr: 1974 line_status = 0; 1975 if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY; 1976 if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY; 1977 if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE; 1978 if (tmp & STS8251_PE) line_status |= LSR_PE; 1979 if (tmp & STS8251_OE) line_status |= LSR_OE; 1980 if (tmp & STS8251_FE) line_status |= LSR_FE; 1981 if (tmp & STS8251_BD_SD) line_status |= LSR_BI; 1982 } else 1983#endif /* PC98 */ 1984 line_status = inb(com->line_status_port); 1985 1986 /* input event? (check first to help avoid overruns) */ 1987 while (line_status & LSR_RCV_MASK) { 1988 /* break/unnattached error bits or real input? */ 1989#ifdef PC98 1990 if(IS_8251(com->pc98_if_type)){ 1991 recv_data = inb(com->data_port); 1992 if(tmp & 0x78){ 1993 pc98_i8251_or_cmd(com,CMD8251_ER); 1994 recv_data = 0; 1995 } 1996 } else { 1997#endif /* PC98 */ 1998 if (!(line_status & LSR_RXRDY)) 1999 recv_data = 0; 2000 else 2001 recv_data = inb(com->data_port); 2002#ifdef PC98 2003 } 2004#endif 2005 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) { 2006 /* 2007 * Don't store BI if IGNBRK or FE/PE if IGNPAR. 2008 * Otherwise, push the work to a higher level 2009 * (to handle PARMRK) if we're bypassing. 2010 * Otherwise, convert BI/FE and PE+INPCK to 0. 2011 * 2012 * This makes bypassing work right in the 2013 * usual "raw" case (IGNBRK set, and IGNPAR 2014 * and INPCK clear). 2015 * 2016 * Note: BI together with FE/PE means just BI. 2017 */ 2018 if (line_status & LSR_BI) { 2019#if defined(DDB) && defined(BREAK_TO_DEBUGGER) 2020 if (com->unit == comconsole) { 2021 breakpoint(); 2022 goto cont; 2023 } 2024#endif 2025 if (com->tp == NULL 2026 || com->tp->t_iflag & IGNBRK) 2027 goto cont; 2028 } else { 2029 if (com->tp == NULL 2030 || com->tp->t_iflag & IGNPAR) 2031 goto cont; 2032 } 2033 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT 2034 && (line_status & (LSR_BI | LSR_FE) 2035 || com->tp->t_iflag & INPCK)) 2036 recv_data = 0; 2037 } 2038 ++com->bytes_in; 2039 if (com->hotchar != 0 && recv_data == com->hotchar) 2040 setsofttty(); 2041 ioptr = com->iptr; 2042 if (ioptr >= com->ibufend) 2043 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 2044 else { 2045 if (com->do_timestamp) 2046 microtime(&com->timestamp); 2047 ++com_events; 2048 schedsofttty(); 2049#if 0 /* for testing input latency vs efficiency */ 2050if (com->iptr - com->ibuf == 8) 2051 setsofttty(); 2052#endif 2053 ioptr[0] = recv_data; 2054 ioptr[CE_INPUT_OFFSET] = line_status; 2055 com->iptr = ++ioptr; 2056 if (ioptr == com->ihighwater 2057 && com->state & CS_RTS_IFLOW) 2058#ifdef PC98 2059 if(IS_8251(com->pc98_if_type)) 2060 com_tiocm_bic(com, TIOCM_RTS); 2061 else 2062#endif 2063 outb(com->modem_ctl_port, 2064 com->mcr_image &= ~MCR_RTS); 2065 if (line_status & LSR_OE) 2066 CE_RECORD(com, CE_OVERRUN); 2067 } 2068cont: 2069 /* 2070 * "& 0x7F" is to avoid the gcc-1.40 generating a slow 2071 * jump from the top of the loop to here 2072 */ 2073#ifdef PC98 2074 if(IS_8251(com->pc98_if_type)) 2075 goto status_read; 2076 else 2077#endif 2078 line_status = inb(com->line_status_port) & 0x7F; 2079 } 2080 2081 /* modem status change? (always check before doing output) */ 2082#ifdef PC98 2083 if(!IS_8251(com->pc98_if_type)){ 2084#endif 2085 modem_status = inb(com->modem_status_port); 2086 if (modem_status != com->last_modem_status) { 2087 if (com->do_dcd_timestamp 2088 && !(com->last_modem_status & MSR_DCD) 2089 && modem_status & MSR_DCD) 2090 microtime(&com->dcd_timestamp); 2091 2092 /* 2093 * Schedule high level to handle DCD changes. Note 2094 * that we don't use the delta bits anywhere. Some 2095 * UARTs mess them up, and it's easy to remember the 2096 * previous bits and calculate the delta. 2097 */ 2098 com->last_modem_status = modem_status; 2099 if (!(com->state & CS_CHECKMSR)) { 2100 com_events += LOTS_OF_EVENTS; 2101 com->state |= CS_CHECKMSR; 2102 setsofttty(); 2103 } 2104 2105 /* handle CTS change immediately for crisp flow ctl */ 2106 if (com->state & CS_CTS_OFLOW) { 2107 if (modem_status & MSR_CTS) 2108 com->state |= CS_ODEVREADY; 2109 else 2110 com->state &= ~CS_ODEVREADY; 2111 } 2112 } 2113#ifdef PC98 2114 } 2115#endif 2116 2117 /* output queued and everything ready? */ 2118 if (line_status & LSR_TXRDY 2119 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2120 ioptr = com->obufq.l_head; 2121 if (com->tx_fifo_size > 1) { 2122 u_int ocount; 2123 2124 ocount = com->obufq.l_tail - ioptr; 2125 if (ocount > com->tx_fifo_size) 2126 ocount = com->tx_fifo_size; 2127 com->bytes_out += ocount; 2128 do 2129 outb(com->data_port, *ioptr++); 2130 while (--ocount != 0); 2131 } else { 2132 outb(com->data_port, *ioptr++); 2133 ++com->bytes_out; 2134 } 2135#ifdef PC98 2136 if(IS_8251(com->pc98_if_type)) 2137 if ( !(pc98_check_i8251_interrupt(com) & IEN_TxFLAG) ) 2138 com_int_Tx_enable(com); 2139#endif 2140 com->obufq.l_head = ioptr; 2141 if (COM_IIR_TXRDYBUG(com)) { 2142 int_ctl_new = int_ctl | IER_ETXRDY; 2143 } 2144 if (ioptr >= com->obufq.l_tail) { 2145 struct lbq *qp; 2146 2147 qp = com->obufq.l_next; 2148 qp->l_queued = FALSE; 2149 qp = qp->l_next; 2150 if (qp != NULL) { 2151 com->obufq.l_head = qp->l_head; 2152 com->obufq.l_tail = qp->l_tail; 2153 com->obufq.l_next = qp; 2154 } else { 2155 /* output just completed */ 2156 if ( COM_IIR_TXRDYBUG(com) ) { 2157 int_ctl_new = int_ctl & ~IER_ETXRDY; 2158 } 2159 com->state &= ~CS_BUSY; 2160#if defined(PC98) 2161 if(IS_8251(com->pc98_if_type)) 2162 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2163 com_int_Tx_disable(com); 2164#endif 2165 } 2166 if (!(com->state & CS_ODONE)) { 2167 com_events += LOTS_OF_EVENTS; 2168 com->state |= CS_ODONE; 2169 setsofttty(); /* handle at high level ASAP */ 2170 } 2171 } 2172 if ( COM_IIR_TXRDYBUG(com) && (int_ctl != int_ctl_new)) { 2173 outb(com->intr_ctl_port, int_ctl_new); 2174 } 2175 } 2176#ifdef PC98 2177 else if (line_status & LSR_TXRDY) { 2178 if(IS_8251(com->pc98_if_type)) 2179 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2180 com_int_Tx_disable(com); 2181 } 2182 if(IS_8251(com->pc98_if_type)) 2183 if ((tmp = inb(com->sts_port)) & STS8251_RxRDY) 2184 goto more_intr; 2185#endif 2186 2187 /* finished? */ 2188#ifndef COM_MULTIPORT 2189#ifdef PC98 2190 if(IS_8251(com->pc98_if_type)) 2191 return; 2192#endif 2193 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) 2194#endif /* COM_MULTIPORT */ 2195 return; 2196 } 2197} 2198 2199static int 2200sioioctl(dev, cmd, data, flag, p) 2201 dev_t dev; 2202 u_long cmd; 2203 caddr_t data; 2204 int flag; 2205 struct proc *p; 2206{ 2207 struct com_s *com; 2208 int error; 2209 Port_t iobase; 2210 int mynor; 2211 int s; 2212 struct tty *tp; 2213#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2214 int oldcmd; 2215 struct termios term; 2216#endif 2217 2218 mynor = minor(dev); 2219 com = com_addr(MINOR_TO_UNIT(mynor)); 2220 if (com->gone) 2221 return (ENODEV); 2222 iobase = com->iobase; 2223 if (mynor & CONTROL_MASK) { 2224 struct termios *ct; 2225 2226 switch (mynor & CONTROL_MASK) { 2227 case CONTROL_INIT_STATE: 2228 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 2229 break; 2230 case CONTROL_LOCK_STATE: 2231 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 2232 break; 2233 default: 2234 return (ENODEV); /* /dev/nodev */ 2235 } 2236 switch (cmd) { 2237 case TIOCSETA: 2238 error = suser(p->p_ucred, &p->p_acflag); 2239 if (error != 0) 2240 return (error); 2241 *ct = *(struct termios *)data; 2242 return (0); 2243 case TIOCGETA: 2244 *(struct termios *)data = *ct; 2245 return (0); 2246 case TIOCGETD: 2247 *(int *)data = TTYDISC; 2248 return (0); 2249 case TIOCGWINSZ: 2250 bzero(data, sizeof(struct winsize)); 2251 return (0); 2252#ifdef DSI_SOFT_MODEM 2253 /* 2254 * Download micro-code to Digicom modem. 2255 */ 2256 case TIOCDSIMICROCODE: 2257 { 2258 u_long l; 2259 u_char *p,*pi; 2260 2261 pi = (u_char*)(*(caddr_t*)data); 2262 error = copyin(pi,&l,sizeof l); 2263 if(error) 2264 {return error;}; 2265 pi += sizeof l; 2266 2267 p = malloc(l,M_TEMP,M_NOWAIT); 2268 if(!p) 2269 {return ENOBUFS;} 2270 error = copyin(pi,p,l); 2271 if(error) 2272 {free(p,M_TEMP); return error;}; 2273 if(error = LoadSoftModem( 2274 MINOR_TO_UNIT(mynor),iobase,l,p)) 2275 {free(p,M_TEMP); return error;} 2276 free(p,M_TEMP); 2277 return(0); 2278 } 2279#endif /* DSI_SOFT_MODEM */ 2280 default: 2281 return (ENOTTY); 2282 } 2283 } 2284 tp = com->tp; 2285#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2286 term = tp->t_termios; 2287 oldcmd = cmd; 2288 error = ttsetcompat(tp, &cmd, data, &term); 2289 if (error != 0) 2290 return (error); 2291 if (cmd != oldcmd) 2292 data = (caddr_t)&term; 2293#endif 2294 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 2295 int cc; 2296 struct termios *dt = (struct termios *)data; 2297 struct termios *lt = mynor & CALLOUT_MASK 2298 ? &com->lt_out : &com->lt_in; 2299 2300 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 2301 | (dt->c_iflag & ~lt->c_iflag); 2302 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 2303 | (dt->c_oflag & ~lt->c_oflag); 2304 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 2305 | (dt->c_cflag & ~lt->c_cflag); 2306 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 2307 | (dt->c_lflag & ~lt->c_lflag); 2308 for (cc = 0; cc < NCCS; ++cc) 2309 if (lt->c_cc[cc] != 0) 2310 dt->c_cc[cc] = tp->t_cc[cc]; 2311 if (lt->c_ispeed != 0) 2312 dt->c_ispeed = tp->t_ispeed; 2313 if (lt->c_ospeed != 0) 2314 dt->c_ospeed = tp->t_ospeed; 2315 } 2316 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 2317 if (error != ENOIOCTL) 2318 return (error); 2319 s = spltty(); 2320 error = ttioctl(tp, cmd, data, flag); 2321 disc_optim(tp, &tp->t_termios, com); 2322 if (error != ENOIOCTL) { 2323 splx(s); 2324 return (error); 2325 } 2326#ifdef PC98 2327 if(IS_8251(com->pc98_if_type)){ 2328 switch (cmd) { 2329 case TIOCSBRK: 2330 com_send_break_on( com ); 2331 break; 2332 case TIOCCBRK: 2333 com_send_break_off( com ); 2334 break; 2335 case TIOCSDTR: 2336 com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS ); 2337 break; 2338 case TIOCCDTR: 2339 com_tiocm_bic(com, TIOCM_DTR); 2340 break; 2341 /* 2342 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2343 * changes get undone on the next call to comparam(). 2344 */ 2345 case TIOCMSET: 2346 com_tiocm_set( com, *(int *)data ); 2347 break; 2348 case TIOCMBIS: 2349 com_tiocm_bis( com, *(int *)data ); 2350 break; 2351 case TIOCMBIC: 2352 com_tiocm_bic( com, *(int *)data ); 2353 break; 2354 case TIOCMGET: 2355 *(int *)data = com_tiocm_get(com); 2356 break; 2357 case TIOCMSDTRWAIT: 2358 /* must be root since the wait applies to following logins */ 2359 error = suser(p->p_ucred, &p->p_acflag); 2360 if (error != 0) { 2361 splx(s); 2362 return (error); 2363 } 2364 com->dtr_wait = *(int *)data * hz / 100; 2365 break; 2366 case TIOCMGDTRWAIT: 2367 *(int *)data = com->dtr_wait * 100 / hz; 2368 break; 2369 case TIOCTIMESTAMP: 2370 com->do_timestamp = TRUE; 2371 *(struct timeval *)data = com->timestamp; 2372 break; 2373 case TIOCDCDTIMESTAMP: 2374 com->do_dcd_timestamp = TRUE; 2375 *(struct timeval *)data = com->dcd_timestamp; 2376 break; 2377 default: 2378 splx(s); 2379 return (ENOTTY); 2380 } 2381 } else { 2382#endif 2383 switch (cmd) { 2384 case TIOCSBRK: 2385 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 2386 break; 2387 case TIOCCBRK: 2388 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 2389 break; 2390 case TIOCSDTR: 2391 (void)commctl(com, TIOCM_DTR, DMBIS); 2392 break; 2393 case TIOCCDTR: 2394 (void)commctl(com, TIOCM_DTR, DMBIC); 2395 break; 2396 /* 2397 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2398 * changes get undone on the next call to comparam(). 2399 */ 2400 case TIOCMSET: 2401 (void)commctl(com, *(int *)data, DMSET); 2402 break; 2403 case TIOCMBIS: 2404 (void)commctl(com, *(int *)data, DMBIS); 2405 break; 2406 case TIOCMBIC: 2407 (void)commctl(com, *(int *)data, DMBIC); 2408 break; 2409 case TIOCMGET: 2410 *(int *)data = commctl(com, 0, DMGET); 2411 break; 2412 case TIOCMSDTRWAIT: 2413 /* must be root since the wait applies to following logins */ 2414 error = suser(p->p_ucred, &p->p_acflag); 2415 if (error != 0) { 2416 splx(s); 2417 return (error); 2418 } 2419 com->dtr_wait = *(int *)data * hz / 100; 2420 break; 2421 case TIOCMGDTRWAIT: 2422 *(int *)data = com->dtr_wait * 100 / hz; 2423 break; 2424 case TIOCTIMESTAMP: 2425 com->do_timestamp = TRUE; 2426 *(struct timeval *)data = com->timestamp; 2427 break; 2428 case TIOCDCDTIMESTAMP: 2429 com->do_dcd_timestamp = TRUE; 2430 *(struct timeval *)data = com->dcd_timestamp; 2431 break; 2432 default: 2433 splx(s); 2434 return (ENOTTY); 2435 } 2436#ifdef PC98 2437 } 2438#endif 2439 splx(s); 2440 return (0); 2441} 2442 2443static void 2444siopoll() 2445{ 2446 int unit; 2447 2448 if (com_events == 0) 2449 return; 2450repeat: 2451 for (unit = 0; unit < NSIOTOT; ++unit) { 2452 u_char *buf; 2453 struct com_s *com; 2454 u_char *ibuf; 2455 int incc; 2456 struct tty *tp; 2457#ifdef PC98 2458 int tmp; 2459#endif 2460 2461 com = com_addr(unit); 2462 if (com == NULL) 2463 continue; 2464 tp = com->tp; 2465 if (tp == NULL || com->gone) { 2466 /* 2467 * Discard any events related to never-opened or 2468 * going-away devices. 2469 */ 2470 disable_intr(); 2471 incc = com->iptr - com->ibuf; 2472 com->iptr = com->ibuf; 2473 if (com->state & CS_CHECKMSR) { 2474 incc += LOTS_OF_EVENTS; 2475 com->state &= ~CS_CHECKMSR; 2476 } 2477 com_events -= incc; 2478 enable_intr(); 2479 continue; 2480 } 2481 2482 /* switch the role of the low-level input buffers */ 2483 if (com->iptr == (ibuf = com->ibuf)) { 2484 buf = NULL; /* not used, but compiler can't tell */ 2485 incc = 0; 2486 } else { 2487 buf = ibuf; 2488 disable_intr(); 2489 incc = com->iptr - buf; 2490 com_events -= incc; 2491 if (ibuf == com->ibuf1) 2492 ibuf = com->ibuf2; 2493 else 2494 ibuf = com->ibuf1; 2495 com->ibufend = ibuf + RS_IBUFSIZE; 2496 com->ihighwater = ibuf + RS_IHIGHWATER; 2497 com->iptr = ibuf; 2498 2499 /* 2500 * There is now room for another low-level buffer full 2501 * of input, so enable RTS if it is now disabled and 2502 * there is room in the high-level buffer. 2503 */ 2504#ifdef PC98 2505 if(IS_8251(com->pc98_if_type)) 2506 tmp = com_tiocm_get(com) & TIOCM_RTS; 2507 else 2508 tmp = com->mcr_image & MCR_RTS; 2509#endif 2510 if ((com->state & CS_RTS_IFLOW) 2511#ifdef PC98 2512 && !(tmp) 2513#else 2514 && !(com->mcr_image & MCR_RTS) 2515#endif 2516 && !(tp->t_state & TS_TBLOCK)) 2517#ifdef PC98 2518 if(IS_8251(com->pc98_if_type)) 2519 com_tiocm_bis(com, TIOCM_RTS); 2520 else 2521#endif 2522 outb(com->modem_ctl_port, 2523 com->mcr_image |= MCR_RTS); 2524 enable_intr(); 2525 com->ibuf = ibuf; 2526 } 2527 2528 if (com->state & CS_CHECKMSR) { 2529 u_char delta_modem_status; 2530 2531#ifdef PC98 2532 if(!IS_8251(com->pc98_if_type)){ 2533#endif 2534 disable_intr(); 2535 delta_modem_status = com->last_modem_status 2536 ^ com->prev_modem_status; 2537 com->prev_modem_status = com->last_modem_status; 2538 com_events -= LOTS_OF_EVENTS; 2539 com->state &= ~CS_CHECKMSR; 2540 enable_intr(); 2541 if (delta_modem_status & MSR_DCD) 2542 (*linesw[tp->t_line].l_modem) 2543 (tp, com->prev_modem_status & MSR_DCD); 2544#ifdef PC98 2545 } 2546#endif 2547 } 2548 if (com->state & CS_ODONE) { 2549 disable_intr(); 2550 com_events -= LOTS_OF_EVENTS; 2551 com->state &= ~CS_ODONE; 2552 enable_intr(); 2553 if (!(com->state & CS_BUSY) 2554 && !(com->extra_state & CSE_BUSYCHECK)) { 2555 timeout(siobusycheck, com, hz / 100); 2556 com->extra_state |= CSE_BUSYCHECK; 2557 } 2558 (*linesw[tp->t_line].l_start)(tp); 2559 } 2560 if (incc <= 0 || !(tp->t_state & TS_ISOPEN) || 2561 !(tp->t_cflag & CREAD)) 2562 continue; 2563 /* 2564 * Avoid the grotesquely inefficient lineswitch routine 2565 * (ttyinput) in "raw" mode. It usually takes about 450 2566 * instructions (that's without canonical processing or echo!). 2567 * slinput is reasonably fast (usually 40 instructions plus 2568 * call overhead). 2569 */ 2570 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 2571 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 2572 && (com->state & CS_RTS_IFLOW 2573 || tp->t_iflag & IXOFF) 2574 && !(tp->t_state & TS_TBLOCK)) 2575 ttyblock(tp); 2576 tk_nin += incc; 2577 tk_rawcc += incc; 2578 tp->t_rawcc += incc; 2579 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 2580 += b_to_q((char *)buf, incc, &tp->t_rawq); 2581 ttwakeup(tp); 2582 if (tp->t_state & TS_TTSTOP 2583 && (tp->t_iflag & IXANY 2584 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 2585 tp->t_state &= ~TS_TTSTOP; 2586 tp->t_lflag &= ~FLUSHO; 2587 comstart(tp); 2588 } 2589 } else { 2590 do { 2591 u_char line_status; 2592 int recv_data; 2593 2594 line_status = (u_char) buf[CE_INPUT_OFFSET]; 2595 recv_data = (u_char) *buf++; 2596 if (line_status 2597 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 2598 if (line_status & LSR_BI) 2599 recv_data |= TTY_BI; 2600 if (line_status & LSR_FE) 2601 recv_data |= TTY_FE; 2602 if (line_status & LSR_OE) 2603 recv_data |= TTY_OE; 2604 if (line_status & LSR_PE) 2605 recv_data |= TTY_PE; 2606 } 2607 (*linesw[tp->t_line].l_rint)(recv_data, tp); 2608 } while (--incc > 0); 2609 } 2610 if (com_events == 0) 2611 break; 2612 } 2613 if (com_events >= LOTS_OF_EVENTS) 2614 goto repeat; 2615} 2616 2617static int 2618comparam(tp, t) 2619 struct tty *tp; 2620 struct termios *t; 2621{ 2622 u_int cfcr; 2623 int cflag; 2624 struct com_s *com; 2625 int divisor; 2626 u_char dlbh; 2627 u_char dlbl; 2628 int error; 2629 Port_t iobase; 2630 int s; 2631 int unit; 2632 int txtimeout; 2633#ifdef PC98 2634 Port_t tmp_port; 2635 int tmp_flg; 2636#endif 2637 2638#ifdef PC98 2639 cfcr = 0; 2640 unit = DEV_TO_UNIT(tp->t_dev); 2641 com = com_addr(unit); 2642 iobase = com->iobase; 2643 if(IS_8251(com->pc98_if_type)) { 2644 divisor = pc98_ttspeedtab(com, t->c_ospeed); 2645 } else 2646#endif 2647 /* do historical conversions */ 2648 if (t->c_ispeed == 0) 2649 t->c_ispeed = t->c_ospeed; 2650 2651 /* check requested parameters */ 2652 divisor = ttspeedtab(t->c_ospeed, comspeedtab); 2653 if (divisor < 0 || divisor > 0 && t->c_ispeed != t->c_ospeed) 2654 return (EINVAL); 2655 2656 /* parameters are OK, convert them to the com struct and the device */ 2657#ifndef PC98 2658 unit = DEV_TO_UNIT(tp->t_dev); 2659 com = com_addr(unit); 2660 iobase = com->iobase; 2661#endif 2662 s = spltty(); 2663#ifdef PC98 2664 if(IS_8251(com->pc98_if_type)){ 2665 if(divisor == 0) 2666 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 2667 else 2668 com_tiocm_bis( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 2669 } else { 2670#endif 2671 if (divisor == 0) 2672 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 2673 else 2674 (void)commctl(com, TIOCM_DTR, DMBIS); 2675#ifdef PC98 2676 } 2677#endif 2678 cflag = t->c_cflag; 2679#ifdef PC98 2680 if(!IS_8251(com->pc98_if_type)){ 2681#endif 2682 switch (cflag & CSIZE) { 2683 case CS5: 2684 cfcr = CFCR_5BITS; 2685 break; 2686 case CS6: 2687 cfcr = CFCR_6BITS; 2688 break; 2689 case CS7: 2690 cfcr = CFCR_7BITS; 2691 break; 2692 default: 2693 cfcr = CFCR_8BITS; 2694 break; 2695 } 2696 if (cflag & PARENB) { 2697 cfcr |= CFCR_PENAB; 2698 if (!(cflag & PARODD)) 2699 cfcr |= CFCR_PEVEN; 2700 } 2701 if (cflag & CSTOPB) 2702 cfcr |= CFCR_STOPB; 2703 2704 if (com->hasfifo && divisor != 0) { 2705 /* 2706 * Use a fifo trigger level low enough so that the input 2707 * latency from the fifo is less than about 16 msec and 2708 * the total latency is less than about 30 msec. These 2709 * latencies are reasonable for humans. Serial comms 2710 * protocols shouldn't expect anything better since modem 2711 * latencies are larger. 2712 */ 2713 com->fifo_image = t->c_ospeed <= 4800 2714 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; 2715#ifdef COM_ESP 2716 /* 2717 * The Hayes ESP card needs the fifo DMA mode bit set 2718 * in compatibility mode. If not, it will interrupt 2719 * for each character received. 2720 */ 2721 if (com->esp) 2722 com->fifo_image |= FIFO_DMA_MODE; 2723#endif 2724 outb(iobase + com_fifo, com->fifo_image); 2725 } 2726 2727 /* 2728 * Some UARTs lock up if the divisor latch registers are selected 2729 * while the UART is doing output (they refuse to transmit anything 2730 * more until given a hard reset). Fix this by stopping filling 2731 * the device buffers and waiting for them to drain. Reading the 2732 * line status port outside of siointr1() might lose some receiver 2733 * error bits, but that is acceptable here. 2734 */ 2735#ifdef PC98 2736 } 2737#endif 2738 disable_intr(); 2739retry: 2740 com->state &= ~CS_TTGO; 2741 txtimeout = tp->t_timeout; 2742 enable_intr(); 2743#ifdef PC98 2744 if(IS_8251(com->pc98_if_type)){ 2745 tmp_port = com->sts_port; 2746 tmp_flg = (STS8251_TxRDY|STS8251_TxEMP); 2747 } else { 2748 tmp_port = com->line_status_port; 2749 tmp_flg = (LSR_TSRE|LSR_TXRDY); 2750 } 2751 while ((inb(tmp_port) & tmp_flg) != tmp_flg) { 2752#else 2753 while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2754 != (LSR_TSRE | LSR_TXRDY)) { 2755#endif 2756 tp->t_state |= TS_SO_OCOMPLETE; 2757 error = ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI | PCATCH, 2758 "siotx", hz / 100); 2759 if ( txtimeout != 0 2760 && (!error || error == EAGAIN) 2761 && (txtimeout -= hz / 100) <= 0 2762 ) 2763 error = EIO; 2764 if (com->gone) 2765 error = ENODEV; 2766 if (error != 0 && error != EAGAIN) { 2767 if (!(tp->t_state & TS_TTSTOP)) { 2768 disable_intr(); 2769 com->state |= CS_TTGO; 2770 enable_intr(); 2771 } 2772 splx(s); 2773 return (error); 2774 } 2775 } 2776 2777 disable_intr(); /* very important while com_data is hidden */ 2778 2779 /* 2780 * XXX - clearing CS_TTGO is not sufficient to stop further output, 2781 * because siopoll() calls comstart() which usually sets it again 2782 * because TS_TTSTOP is clear. Setting TS_TTSTOP would not be 2783 * sufficient, for similar reasons. 2784 */ 2785#ifdef PC98 2786 if ((inb(tmp_port) & tmp_flg) != tmp_flg) 2787#else 2788 if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2789 != (LSR_TSRE | LSR_TXRDY)) 2790#endif 2791 goto retry; 2792 2793#ifdef PC98 2794 if(!IS_8251(com->pc98_if_type)){ 2795#endif 2796 if (divisor != 0) { 2797 outb(iobase + com_cfcr, cfcr | CFCR_DLAB); 2798 /* 2799 * Only set the divisor registers if they would change, 2800 * since on some 16550 incompatibles (UMC8669F), setting 2801 * them while input is arriving them loses sync until 2802 * data stops arriving. 2803 */ 2804 dlbl = divisor & 0xFF; 2805 if (inb(iobase + com_dlbl) != dlbl) 2806 outb(iobase + com_dlbl, dlbl); 2807 dlbh = (u_int) divisor >> 8; 2808 if (inb(iobase + com_dlbh) != dlbh) 2809 outb(iobase + com_dlbh, dlbh); 2810 } 2811 2812 2813 outb(iobase + com_cfcr, com->cfcr_image = cfcr); 2814 2815#ifdef PC98 2816 } else 2817 com_cflag_and_speed_set(com, cflag, t->c_ospeed); 2818#endif 2819 if (!(tp->t_state & TS_TTSTOP)) 2820 com->state |= CS_TTGO; 2821 2822 if (cflag & CRTS_IFLOW) { 2823 if (com->st16650a) { 2824 outb(iobase + com_cfcr, 0xbf); 2825 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40); 2826 } 2827 com->state |= CS_RTS_IFLOW; 2828 /* 2829 * If CS_RTS_IFLOW just changed from off to on, the change 2830 * needs to be propagated to MCR_RTS. This isn't urgent, 2831 * so do it later by calling comstart() instead of repeating 2832 * a lot of code from comstart() here. 2833 */ 2834 } else if (com->state & CS_RTS_IFLOW) { 2835 com->state &= ~CS_RTS_IFLOW; 2836 /* 2837 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2838 * on here, since comstart() won't do it later. 2839 */ 2840#ifdef PC98 2841 if(IS_8251(com->pc98_if_type)) 2842 com_tiocm_bis(com, TIOCM_RTS); 2843 else 2844#endif 2845 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2846 if (com->st16650a) { 2847 outb(iobase + com_cfcr, 0xbf); 2848 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40); 2849 } 2850 } 2851 2852 2853 /* 2854 * Set up state to handle output flow control. 2855 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2856 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2857 */ 2858 com->state |= CS_ODEVREADY; 2859 com->state &= ~CS_CTS_OFLOW; 2860 if (cflag & CCTS_OFLOW) { 2861 com->state |= CS_CTS_OFLOW; 2862#ifdef PC98 2863 if(IS_8251(com->pc98_if_type)){ 2864 if (!(pc98_get_modem_status(com) & TIOCM_CTS)) 2865 com->state &= ~CS_ODEVREADY; 2866 } else { 2867#endif 2868 if (!(com->last_modem_status & MSR_CTS)) 2869 com->state &= ~CS_ODEVREADY; 2870 if (com->st16650a) { 2871 outb(iobase + com_cfcr, 0xbf); 2872 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80); 2873 } 2874#ifdef PC98 2875 } 2876#endif 2877 } else { 2878 if (com->st16650a) { 2879 outb(iobase + com_cfcr, 0xbf); 2880 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80); 2881 } 2882 } 2883 2884 2885 outb(iobase + com_cfcr, com->cfcr_image); 2886 2887 2888 /* XXX shouldn't call functions while intrs are disabled. */ 2889 disc_optim(tp, t, com); 2890 /* 2891 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2892 * unconditionally, but that defeated the careful discarding of 2893 * stale input in sioopen(). 2894 */ 2895 if (com->state >= (CS_BUSY | CS_TTGO)) 2896 siointr1(com); 2897 2898 enable_intr(); 2899 splx(s); 2900 comstart(tp); 2901 return (0); 2902} 2903 2904static void 2905comstart(tp) 2906 struct tty *tp; 2907{ 2908 struct com_s *com; 2909 int s; 2910 int unit; 2911#ifdef PC98 2912 int tmp; 2913#endif 2914 2915 unit = DEV_TO_UNIT(tp->t_dev); 2916 com = com_addr(unit); 2917 s = spltty(); 2918 disable_intr(); 2919 if (tp->t_state & TS_TTSTOP) 2920 com->state &= ~CS_TTGO; 2921 else 2922 com->state |= CS_TTGO; 2923 if (tp->t_state & TS_TBLOCK) { 2924#ifdef PC98 2925 if(IS_8251(com->pc98_if_type)) 2926 tmp = com_tiocm_get(com) & TIOCM_RTS; 2927 else 2928 tmp = com->mcr_image & MCR_RTS; 2929 if (tmp && (com->state & CS_RTS_IFLOW)) 2930#else 2931 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 2932#endif 2933#ifdef PC98 2934 if(IS_8251(com->pc98_if_type)) 2935 com_tiocm_bic(com, TIOCM_RTS); 2936 else 2937#endif 2938 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2939 } else { 2940#ifdef PC98 2941 if(IS_8251(com->pc98_if_type)) 2942 tmp = com_tiocm_get(com) & TIOCM_RTS; 2943 else 2944 tmp = com->mcr_image & MCR_RTS; 2945 if (!(tmp) && com->iptr < com->ihighwater 2946 && com->state & CS_RTS_IFLOW) 2947#else 2948 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater 2949 && com->state & CS_RTS_IFLOW) 2950#endif 2951#ifdef PC98 2952 if(IS_8251(com->pc98_if_type)) 2953 com_tiocm_bis(com, TIOCM_RTS); 2954 else 2955#endif 2956 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2957 } 2958 enable_intr(); 2959 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2960 ttwwakeup(tp); 2961#ifdef PC98 2962/* if(IS_8251(com->pc98_if_type)) 2963 com_int_Tx_enable(com); */ 2964#endif 2965 splx(s); 2966 return; 2967 } 2968 if (tp->t_outq.c_cc != 0) { 2969 struct lbq *qp; 2970 struct lbq *next; 2971 2972 if (!com->obufs[0].l_queued) { 2973 com->obufs[0].l_tail 2974 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2975 sizeof com->obuf1); 2976 com->obufs[0].l_next = NULL; 2977 com->obufs[0].l_queued = TRUE; 2978 disable_intr(); 2979 if (com->state & CS_BUSY) { 2980 qp = com->obufq.l_next; 2981 while ((next = qp->l_next) != NULL) 2982 qp = next; 2983 qp->l_next = &com->obufs[0]; 2984 } else { 2985 com->obufq.l_head = com->obufs[0].l_head; 2986 com->obufq.l_tail = com->obufs[0].l_tail; 2987 com->obufq.l_next = &com->obufs[0]; 2988 com->state |= CS_BUSY; 2989 } 2990 enable_intr(); 2991 } 2992 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2993 com->obufs[1].l_tail 2994 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2995 sizeof com->obuf2); 2996 com->obufs[1].l_next = NULL; 2997 com->obufs[1].l_queued = TRUE; 2998 disable_intr(); 2999 if (com->state & CS_BUSY) { 3000 qp = com->obufq.l_next; 3001 while ((next = qp->l_next) != NULL) 3002 qp = next; 3003 qp->l_next = &com->obufs[1]; 3004 } else { 3005 com->obufq.l_head = com->obufs[1].l_head; 3006 com->obufq.l_tail = com->obufs[1].l_tail; 3007 com->obufq.l_next = &com->obufs[1]; 3008 com->state |= CS_BUSY; 3009 } 3010 enable_intr(); 3011 } 3012 tp->t_state |= TS_BUSY; 3013 } 3014 disable_intr(); 3015 if (com->state >= (CS_BUSY | CS_TTGO)) 3016 siointr1(com); /* fake interrupt to start output */ 3017 enable_intr(); 3018#ifdef PC98 3019/* if(IS_8251(com->pc98_if_type)) 3020 com_int_Tx_enable(com); */ 3021#endif 3022 ttwwakeup(tp); 3023 splx(s); 3024} 3025 3026static void 3027siostop(tp, rw) 3028 struct tty *tp; 3029 int rw; 3030{ 3031 struct com_s *com; 3032 3033 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 3034 if (com->gone) 3035 return; 3036 disable_intr(); 3037 if (rw & FWRITE) { 3038 if (com->hasfifo) 3039#ifdef COM_ESP 3040 /* XXX avoid h/w bug. */ 3041 if (!com->esp) 3042#endif 3043 /* XXX does this flush everything? */ 3044 outb(com->iobase + com_fifo, 3045 FIFO_XMT_RST | com->fifo_image); 3046 com->obufs[0].l_queued = FALSE; 3047 com->obufs[1].l_queued = FALSE; 3048 if (com->state & CS_ODONE) 3049 com_events -= LOTS_OF_EVENTS; 3050 com->state &= ~(CS_ODONE | CS_BUSY); 3051 com->tp->t_state &= ~TS_BUSY; 3052 } 3053 if (rw & FREAD) { 3054 if (com->hasfifo) 3055#ifdef COM_ESP 3056 /* XXX avoid h/w bug. */ 3057 if (!com->esp) 3058#endif 3059 /* XXX does this flush everything? */ 3060 outb(com->iobase + com_fifo, 3061 FIFO_RCV_RST | com->fifo_image); 3062 com_events -= (com->iptr - com->ibuf); 3063 com->iptr = com->ibuf; 3064 } 3065 enable_intr(); 3066 comstart(tp); 3067} 3068 3069static struct tty * 3070siodevtotty(dev) 3071 dev_t dev; 3072{ 3073 int mynor; 3074 int unit; 3075 3076 mynor = minor(dev); 3077 if (mynor & CONTROL_MASK) 3078 return (NULL); 3079 unit = MINOR_TO_UNIT(mynor); 3080 if ((u_int) unit >= NSIOTOT) 3081 return (NULL); 3082 return (&sio_tty[unit]); 3083} 3084 3085static int 3086commctl(com, bits, how) 3087 struct com_s *com; 3088 int bits; 3089 int how; 3090{ 3091 int mcr; 3092 int msr; 3093 3094 if (how == DMGET) { 3095 bits = TIOCM_LE; /* XXX - always enabled while open */ 3096 mcr = com->mcr_image; 3097 if (mcr & MCR_DTR) 3098 bits |= TIOCM_DTR; 3099 if (mcr & MCR_RTS) 3100 bits |= TIOCM_RTS; 3101 msr = com->prev_modem_status; 3102 if (msr & MSR_CTS) 3103 bits |= TIOCM_CTS; 3104 if (msr & MSR_DCD) 3105 bits |= TIOCM_CD; 3106 if (msr & MSR_DSR) 3107 bits |= TIOCM_DSR; 3108 /* 3109 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI 3110 * more volatile by reading the modem status a lot. Perhaps 3111 * we should latch both bits until the status is read here. 3112 */ 3113 if (msr & (MSR_RI | MSR_TERI)) 3114 bits |= TIOCM_RI; 3115 return (bits); 3116 } 3117 mcr = 0; 3118 if (bits & TIOCM_DTR) 3119 mcr |= MCR_DTR; 3120 if (bits & TIOCM_RTS) 3121 mcr |= MCR_RTS; 3122 if (com->gone) 3123 return(0); 3124 disable_intr(); 3125 switch (how) { 3126 case DMSET: 3127 outb(com->modem_ctl_port, 3128 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); 3129 break; 3130 case DMBIS: 3131 outb(com->modem_ctl_port, com->mcr_image |= mcr); 3132 break; 3133 case DMBIC: 3134 outb(com->modem_ctl_port, com->mcr_image &= ~mcr); 3135 break; 3136 } 3137 enable_intr(); 3138 return (0); 3139} 3140 3141static void 3142siosettimeout() 3143{ 3144 struct com_s *com; 3145 bool_t someopen; 3146 int unit; 3147 3148 /* 3149 * Set our timeout period to 1 second if no polled devices are open. 3150 * Otherwise set it to max(1/200, 1/hz). 3151 * Enable timeouts iff some device is open. 3152 */ 3153 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3154 sio_timeout = hz; 3155 someopen = FALSE; 3156 for (unit = 0; unit < NSIOTOT; ++unit) { 3157 com = com_addr(unit); 3158 if (com != NULL && com->tp != NULL 3159 && com->tp->t_state & TS_ISOPEN && !com->gone) { 3160 someopen = TRUE; 3161 if (com->poll || com->poll_output) { 3162 sio_timeout = hz > 200 ? hz / 200 : 1; 3163 break; 3164 } 3165 } 3166 } 3167 if (someopen) { 3168 sio_timeouts_until_log = hz / sio_timeout; 3169 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 3170 sio_timeout); 3171 } else { 3172 /* Flush error messages, if any. */ 3173 sio_timeouts_until_log = 1; 3174 comwakeup((void *)NULL); 3175 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3176 } 3177} 3178 3179static void 3180comwakeup(chan) 3181 void *chan; 3182{ 3183 struct com_s *com; 3184 int unit; 3185 3186 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 3187 3188 /* 3189 * Recover from lost output interrupts. 3190 * Poll any lines that don't use interrupts. 3191 */ 3192 for (unit = 0; unit < NSIOTOT; ++unit) { 3193 com = com_addr(unit); 3194 if (com != NULL && !com->gone 3195 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 3196 disable_intr(); 3197 siointr1(com); 3198 enable_intr(); 3199 } 3200 } 3201 3202 /* 3203 * Check for and log errors, but not too often. 3204 */ 3205 if (--sio_timeouts_until_log > 0) 3206 return; 3207 sio_timeouts_until_log = hz / sio_timeout; 3208 for (unit = 0; unit < NSIOTOT; ++unit) { 3209 int errnum; 3210 3211 com = com_addr(unit); 3212 if (com == NULL) 3213 continue; 3214 if (com->gone) 3215 continue; 3216 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 3217 u_int delta; 3218 u_long total; 3219 3220 disable_intr(); 3221 delta = com->delta_error_counts[errnum]; 3222 com->delta_error_counts[errnum] = 0; 3223 enable_intr(); 3224 if (delta == 0) 3225 continue; 3226 total = com->error_counts[errnum] += delta; 3227 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", 3228 unit, delta, error_desc[errnum], 3229 delta == 1 ? "" : "s", total); 3230 } 3231 } 3232} 3233 3234#ifdef PC98 3235/* commint is called when modem control line changes */ 3236static void 3237commint(dev_t dev) 3238{ 3239 register struct tty *tp; 3240 int stat,delta; 3241 struct com_s *com; 3242 int mynor,unit; 3243 3244 mynor = minor(dev); 3245 unit = MINOR_TO_UNIT(mynor); 3246 com = com_addr(unit); 3247 tp = com->tp; 3248 3249 stat = com_tiocm_get(com); 3250 delta = com_tiocm_get_delta(com); 3251 3252 if (com->state & CS_CTS_OFLOW) { 3253 if (stat & TIOCM_CTS) 3254 com->state |= CS_ODEVREADY; 3255 else 3256 com->state &= ~CS_ODEVREADY; 3257 } 3258 if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) { 3259 if (stat & TIOCM_CAR ) 3260 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 3261 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 3262 /* negate DTR, RTS */ 3263 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ? 3264 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE ); 3265 /* disable IENABLE */ 3266 com_int_TxRx_disable( com ); 3267 } 3268 } 3269} 3270#endif 3271 3272static void 3273disc_optim(tp, t, com) 3274 struct tty *tp; 3275 struct termios *t; 3276 struct com_s *com; 3277{ 3278 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 3279 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 3280 && (!(t->c_iflag & PARMRK) 3281 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 3282 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 3283 && linesw[tp->t_line].l_rint == ttyinput) 3284 tp->t_state |= TS_CAN_BYPASS_L_RINT; 3285 else 3286 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 3287 com->hotchar = linesw[tp->t_line].l_hotchar; 3288} 3289 3290/* 3291 * Following are all routines needed for SIO to act as console 3292 */ 3293#include <machine/cons.h> 3294 3295struct siocnstate { 3296 u_char dlbl; 3297 u_char dlbh; 3298 u_char ier; 3299 u_char cfcr; 3300 u_char mcr; 3301}; 3302 3303static speed_t siocngetspeed __P((Port_t, struct speedtab *)); 3304static void siocnclose __P((struct siocnstate *sp)); 3305static void siocnopen __P((struct siocnstate *sp)); 3306static void siocntxwait __P((void)); 3307 3308static void 3309siocntxwait() 3310{ 3311 int timo; 3312 3313 /* 3314 * Wait for any pending transmission to finish. Required to avoid 3315 * the UART lockup bug when the speed is changed, and for normal 3316 * transmits. 3317 */ 3318 timo = 100000; 3319 while ((inb(siocniobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) 3320 != (LSR_TSRE | LSR_TXRDY) && --timo != 0) 3321 ; 3322} 3323 3324/* 3325 * Read the serial port specified and try to figure out what speed 3326 * it's currently running at. We're assuming the serial port has 3327 * been initialized and is basicly idle. This routine is only intended 3328 * to be run at system startup. 3329 * 3330 * If the value read from the serial port doesn't make sense, return 0. 3331 */ 3332 3333static speed_t 3334siocngetspeed(iobase, table) 3335 Port_t iobase; 3336 struct speedtab *table; 3337{ 3338 int code; 3339 u_char dlbh; 3340 u_char dlbl; 3341 u_char cfcr; 3342 3343 cfcr = inb(iobase + com_cfcr); 3344 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 3345 3346 dlbl = inb(iobase + com_dlbl); 3347 dlbh = inb(iobase + com_dlbh); 3348 3349 outb(iobase + com_cfcr, cfcr); 3350 3351 code = dlbh << 8 | dlbl; 3352 3353 for ( ; table->sp_speed != -1; table++) 3354 if (table->sp_code == code) 3355 return (table->sp_speed); 3356 3357 return 0; /* didn't match anything sane */ 3358} 3359 3360static void 3361siocnopen(sp) 3362 struct siocnstate *sp; 3363{ 3364 int divisor; 3365 u_char dlbh; 3366 u_char dlbl; 3367 Port_t iobase; 3368 3369 /* 3370 * Save all the device control registers except the fifo register 3371 * and set our default ones (cs8 -parenb speed=comdefaultrate). 3372 * We can't save the fifo register since it is read-only. 3373 */ 3374 iobase = siocniobase; 3375 sp->ier = inb(iobase + com_ier); 3376 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ 3377 siocntxwait(); 3378 sp->cfcr = inb(iobase + com_cfcr); 3379 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3380 sp->dlbl = inb(iobase + com_dlbl); 3381 sp->dlbh = inb(iobase + com_dlbh); 3382 /* 3383 * Only set the divisor registers if they would change, since on 3384 * some 16550 incompatibles (Startech), setting them clears the 3385 * data input register. This also reduces the effects of the 3386 * UMC8669F bug. 3387 */ 3388 divisor = ttspeedtab(comdefaultrate, comspeedtab); 3389 dlbl = divisor & 0xFF; 3390 if (sp->dlbl != dlbl) 3391 outb(iobase + com_dlbl, dlbl); 3392 dlbh = (u_int) divisor >> 8; 3393 if (sp->dlbh != dlbh) 3394 outb(iobase + com_dlbh, dlbh); 3395 outb(iobase + com_cfcr, CFCR_8BITS); 3396 sp->mcr = inb(iobase + com_mcr); 3397 /* 3398 * We don't want interrupts, but must be careful not to "disable" 3399 * them by clearing the MCR_IENABLE bit, since that might cause 3400 * an interrupt by floating the IRQ line. 3401 */ 3402 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); 3403} 3404 3405static void 3406siocnclose(sp) 3407 struct siocnstate *sp; 3408{ 3409 Port_t iobase; 3410 3411 /* 3412 * Restore the device control registers. 3413 */ 3414 siocntxwait(); 3415 iobase = siocniobase; 3416 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3417 if (sp->dlbl != inb(iobase + com_dlbl)) 3418 outb(iobase + com_dlbl, sp->dlbl); 3419 if (sp->dlbh != inb(iobase + com_dlbh)) 3420 outb(iobase + com_dlbh, sp->dlbh); 3421 outb(iobase + com_cfcr, sp->cfcr); 3422 /* 3423 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. 3424 */ 3425 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); 3426 outb(iobase + com_ier, sp->ier); 3427} 3428 3429void 3430siocnprobe(cp) 3431 struct consdev *cp; 3432{ 3433 speed_t boot_speed; 3434 u_char cfcr; 3435 struct isa_device *dvp; 3436 int s; 3437 struct siocnstate sp; 3438 3439 /* 3440 * Find our first enabled console, if any. If it is a high-level 3441 * console device, then initialize it and return successfully. 3442 * If it is a low-level console device, then initialize it and 3443 * return unsuccessfully. It must be initialized in both cases 3444 * for early use by console drivers and debuggers. Initializing 3445 * the hardware is not necessary in all cases, since the i/o 3446 * routines initialize it on the fly, but it is necessary if 3447 * input might arrive while the hardware is switched back to an 3448 * uninitialized state. We can't handle multiple console devices 3449 * yet because our low-level routines don't take a device arg. 3450 * We trust the user to set the console flags properly so that we 3451 * don't need to probe. 3452 */ 3453 cp->cn_pri = CN_DEAD; 3454 for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) 3455 if (dvp->id_driver == &siodriver && dvp->id_enabled 3456 && COM_CONSOLE(dvp)) { 3457 siocniobase = dvp->id_iobase; 3458 s = spltty(); 3459 if (boothowto & RB_SERIAL) { 3460 boot_speed = siocngetspeed(siocniobase, 3461 comspeedtab); 3462 if (boot_speed) 3463 comdefaultrate = boot_speed; 3464 } 3465 3466 /* 3467 * Initialize the divisor latch. We can't rely on 3468 * siocnopen() to do this the first time, since it 3469 * avoids writing to the latch if the latch appears 3470 * to have the correct value. Also, if we didn't 3471 * just read the speed from the hardware, then we 3472 * need to set the speed in hardware so that 3473 * switching it later is null. 3474 */ 3475 cfcr = inb(siocniobase + com_cfcr); 3476 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr); 3477 outb(siocniobase + com_dlbl, 3478 COMBRD(comdefaultrate) & 0xff); 3479 outb(siocniobase + com_dlbh, 3480 (u_int) COMBRD(comdefaultrate) >> 8); 3481 outb(siocniobase + com_cfcr, cfcr); 3482 3483 siocnopen(&sp); 3484 splx(s); 3485 if (!COM_LLCONSOLE(dvp)) { 3486 cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit); 3487 cp->cn_pri = COM_FORCECONSOLE(dvp) 3488 || boothowto & RB_SERIAL 3489 ? CN_REMOTE : CN_NORMAL; 3490 } 3491 break; 3492 } 3493} 3494 3495void 3496siocninit(cp) 3497 struct consdev *cp; 3498{ 3499 comconsole = DEV_TO_UNIT(cp->cn_dev); 3500} 3501 3502int 3503siocncheckc(dev) 3504 dev_t dev; 3505{ 3506 int c; 3507 Port_t iobase; 3508 int s; 3509 struct siocnstate sp; 3510 3511 iobase = siocniobase; 3512 s = spltty(); 3513 siocnopen(&sp); 3514 if (inb(iobase + com_lsr) & LSR_RXRDY) 3515 c = inb(iobase + com_data); 3516 else 3517 c = -1; 3518 siocnclose(&sp); 3519 splx(s); 3520 return (c); 3521} 3522 3523 3524int 3525siocngetc(dev) 3526 dev_t dev; 3527{ 3528 int c; 3529 Port_t iobase; 3530 int s; 3531 struct siocnstate sp; 3532 3533 iobase = siocniobase; 3534 s = spltty(); 3535 siocnopen(&sp); 3536 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 3537 ; 3538 c = inb(iobase + com_data); 3539 siocnclose(&sp); 3540 splx(s); 3541 return (c); 3542} 3543 3544void 3545siocnputc(dev, c) 3546 dev_t dev; 3547 int c; 3548{ 3549 int s; 3550 struct siocnstate sp; 3551 3552 s = spltty(); 3553 siocnopen(&sp); 3554 siocntxwait(); 3555 outb(siocniobase + com_data, c); 3556 siocnclose(&sp); 3557 splx(s); 3558} 3559 3560#ifdef DSI_SOFT_MODEM 3561/* 3562 * The magic code to download microcode to a "Connection 14.4+Fax" 3563 * modem from Digicom Systems Inc. Very magic. 3564 */ 3565 3566#define DSI_ERROR(str) { ptr = str; goto error; } 3567static int 3568LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr) 3569{ 3570 int int_c,int_k; 3571 int data_0188, data_0187; 3572 3573 /* 3574 * First see if it is a DSI SoftModem 3575 */ 3576 if(!((inb(base_io+7) ^ inb(base_io+7)) & 0x80)) 3577 return ENODEV; 3578 3579 data_0188 = inb(base_io+4); 3580 data_0187 = inb(base_io+3); 3581 outb(base_io+3,0x80); 3582 outb(base_io+4,0x0C); 3583 outb(base_io+0,0x31); 3584 outb(base_io+1,0x8C); 3585 outb(base_io+7,0x10); 3586 outb(base_io+7,0x19); 3587 3588 if(0x18 != (inb(base_io+7) & 0x1A)) 3589 DSI_ERROR("dsp bus not granted"); 3590 3591 if(0x01 != (inb(base_io+7) & 0x01)) { 3592 outb(base_io+7,0x18); 3593 outb(base_io+7,0x19); 3594 if(0x01 != (inb(base_io+7) & 0x01)) 3595 DSI_ERROR("program mem not granted"); 3596 } 3597 3598 int_c = 0; 3599 3600 while(1) { 3601 if(int_c >= 7 || size <= 0x1800) 3602 break; 3603 3604 for(int_k = 0 ; int_k < 0x800; int_k++) { 3605 outb(base_io+0,*ptr++); 3606 outb(base_io+1,*ptr++); 3607 outb(base_io+2,*ptr++); 3608 } 3609 3610 size -= 0x1800; 3611 int_c++; 3612 } 3613 3614 if(size > 0x1800) { 3615 outb(base_io+7,0x18); 3616 outb(base_io+7,0x19); 3617 if(0x00 != (inb(base_io+7) & 0x01)) 3618 DSI_ERROR("program data not granted"); 3619 3620 for(int_k = 0 ; int_k < 0x800; int_k++) { 3621 outb(base_io+1,*ptr++); 3622 outb(base_io+2,0); 3623 outb(base_io+1,*ptr++); 3624 outb(base_io+2,*ptr++); 3625 } 3626 3627 size -= 0x1800; 3628 3629 while(size > 0x1800) { 3630 for(int_k = 0 ; int_k < 0xC00; int_k++) { 3631 outb(base_io+1,*ptr++); 3632 outb(base_io+2,*ptr++); 3633 } 3634 size -= 0x1800; 3635 } 3636 3637 if(size < 0x1800) { 3638 for(int_k=0;int_k<size/2;int_k++) { 3639 outb(base_io+1,*ptr++); 3640 outb(base_io+2,*ptr++); 3641 } 3642 } 3643 3644 } else if (size > 0) { 3645 if(int_c == 7) { 3646 outb(base_io+7,0x18); 3647 outb(base_io+7,0x19); 3648 if(0x00 != (inb(base_io+7) & 0x01)) 3649 DSI_ERROR("program data not granted"); 3650 for(int_k = 0 ; int_k < size/3; int_k++) { 3651 outb(base_io+1,*ptr++); 3652 outb(base_io+2,0); 3653 outb(base_io+1,*ptr++); 3654 outb(base_io+2,*ptr++); 3655 } 3656 } else { 3657 for(int_k = 0 ; int_k < size/3; int_k++) { 3658 outb(base_io+0,*ptr++); 3659 outb(base_io+1,*ptr++); 3660 outb(base_io+2,*ptr++); 3661 } 3662 } 3663 } 3664 outb(base_io+7,0x11); 3665 outb(base_io+7,3); 3666 3667 outb(base_io+4,data_0188 & 0xfb); 3668 3669 outb(base_io+3,data_0187); 3670 3671 return 0; 3672error: 3673 printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",unit,ptr); 3674 outb(base_io+7,0x00); \ 3675 outb(base_io+3,data_0187); \ 3676 outb(base_io+4,data_0188); \ 3677 return EIO; 3678} 3679#endif /* DSI_SOFT_MODEM */ 3680 3681/* 3682 * support PnP cards if we are using 'em 3683 */ 3684 3685#if NPNP > 0 3686 3687static struct siopnp_ids { 3688 u_long vend_id; 3689 char *id_str; 3690} siopnp_ids[] = { 3691 { 0x5015f435, "MOT1550"}, 3692 { 0x8113b04e, "Supra1381"}, 3693 { 0x9012b04e, "Supra1290"}, 3694 { 0x11007256, "USR0011"}, 3695 { 0x30207256, "USR2030"}, 3696 { 0 } 3697}; 3698 3699static char *siopnp_probe(u_long csn, u_long vend_id); 3700static void siopnp_attach(u_long csn, u_long vend_id, char *name, 3701 struct isa_device *dev); 3702static u_long nsiopnp = NSIO; 3703 3704static struct pnp_device siopnp = { 3705 "siopnp", 3706 siopnp_probe, 3707 siopnp_attach, 3708 &nsiopnp, 3709 &tty_imask 3710}; 3711DATA_SET (pnpdevice_set, siopnp); 3712 3713static char * 3714siopnp_probe(u_long csn, u_long vend_id) 3715{ 3716 struct siopnp_ids *ids; 3717 char *s = NULL; 3718 3719 for(ids = siopnp_ids; ids->vend_id != 0; ids++) { 3720 if (vend_id == ids->vend_id) { 3721 s = ids->id_str; 3722 break; 3723 } 3724 } 3725 3726 if (s) { 3727 struct pnp_cinfo d; 3728 read_pnp_parms(&d, 0); 3729 if (d.enable == 0 || d.flags & 1) { 3730 printf("CSN %d is disabled.\n", csn); 3731 return (NULL); 3732 } 3733 3734 } 3735 3736 return (s); 3737} 3738 3739static void 3740siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) 3741{ 3742 struct pnp_cinfo d; 3743 struct isa_device *dvp; 3744 3745 if (dev->id_unit >= NSIOTOT) 3746 return; 3747 3748 if (read_pnp_parms(&d, 0) == 0) { 3749 printf("failed to read pnp parms\n"); 3750 return; 3751 } 3752 3753 write_pnp_parms(&d, 0); 3754 3755 enable_pnp_card(); 3756 3757 dev->id_iobase = d.port[0]; 3758 dev->id_irq = (1 << d.irq[0]); 3759 dev->id_intr = siointr; 3760 dev->id_ri_flags = RI_FAST; 3761 dev->id_drq = -1; 3762 3763 if (dev->id_driver == NULL) { 3764 dev->id_driver = &siodriver; 3765 dvp = find_isadev(isa_devtab_tty, &siodriver, 0); 3766 if (dvp != NULL) 3767 dev->id_id = dvp->id_id; 3768 } 3769 3770 if ((dev->id_alive = sioprobe(dev)) != 0) 3771 sioattach(dev); 3772 else 3773 printf("sio%d: probe failed\n", dev->id_unit); 3774} 3775#endif 3776#ifdef PC98 3777/* 3778 * pc98 local function 3779 */ 3780 3781static void 3782com_tiocm_set(struct com_s *com, int msr) 3783{ 3784 int s; 3785 int tmp = 0; 3786 int mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS; 3787 3788 s=spltty(); 3789 com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ) 3790 | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3791 tmp |= (CMD8251_TxEN|CMD8251_RxEN); 3792 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3793 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3794 pc98_i8251_clear_or_cmd( com, mask, tmp ); 3795 splx(s); 3796} 3797 3798static void 3799com_tiocm_bis(struct com_s *com, int msr) 3800{ 3801 int s; 3802 int tmp = 0; 3803 3804 s=spltty(); 3805 com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3806 tmp |= CMD8251_TxEN|CMD8251_RxEN; 3807 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3808 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3809 3810 pc98_i8251_or_cmd( com, tmp ); 3811 splx(s); 3812} 3813 3814static void 3815com_tiocm_bic(struct com_s *com, int msr) 3816{ 3817 int s; 3818 int tmp = msr; 3819 3820 s=spltty(); 3821 com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3822 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3823 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3824 3825 pc98_i8251_clear_cmd( com, tmp ); 3826 splx(s); 3827} 3828 3829static int 3830com_tiocm_get(struct com_s *com) 3831{ 3832 return( com->pc98_prev_modem_status ); 3833} 3834 3835static int 3836com_tiocm_get_delta(struct com_s *com) 3837{ 3838 int tmp; 3839 3840 tmp = com->pc98_modem_delta; 3841 com->pc98_modem_delta = 0; 3842 return( tmp ); 3843} 3844 3845/* convert to TIOCM_?? ( ioctl.h ) */ 3846static int 3847pc98_get_modem_status(struct com_s *com) 3848{ 3849 int stat, stat2; 3850 register int msr; 3851 3852 stat = inb(com->sts_port); 3853 stat2 = inb(com->in_modem_port); 3854 msr = com->pc98_prev_modem_status 3855 & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3856 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR; 3857 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI; 3858 if ( stat & STS8251_DSR ) msr |= TIOCM_DSR; 3859 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS; 3860#if COM_CARRIER_DETECT_EMULATE 3861 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { 3862 msr |= TIOCM_CAR; 3863 } 3864#endif 3865 return(msr); 3866} 3867 3868static void 3869pc98_check_msr(void* chan) 3870{ 3871 int msr, delta; 3872 int s; 3873 register struct tty *tp; 3874 struct com_s *com; 3875 int mynor; 3876 int unit; 3877 dev_t dev; 3878 3879 dev=(dev_t)chan; 3880 mynor = minor(dev); 3881 unit = MINOR_TO_UNIT(mynor); 3882 com = com_addr(unit); 3883 tp = com->tp; 3884 3885 s = spltty(); 3886 msr = pc98_get_modem_status(com); 3887 /* make change flag */ 3888 delta = msr ^ com->pc98_prev_modem_status; 3889 if ( delta & TIOCM_CAR ) { 3890 if ( com->modem_car_chg_timer ) { 3891 if ( -- com->modem_car_chg_timer ) 3892 msr ^= TIOCM_CAR; 3893 } else { 3894 if ( com->modem_car_chg_timer = ( msr & TIOCM_CAR ) ? 3895 DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE ) 3896 msr ^= TIOCM_CAR; 3897 } 3898 } else 3899 com->modem_car_chg_timer = 0; 3900 delta = ( msr ^ com->pc98_prev_modem_status ) & 3901 (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3902 com->pc98_prev_modem_status = msr; 3903 delta = ( com->pc98_modem_delta |= delta ); 3904 splx(s); 3905 if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) { 3906 if ( delta ) { 3907 commint(dev); 3908 } 3909 timeout(pc98_check_msr, (caddr_t)dev, 3910 PC98_CHECK_MODEM_INTERVAL); 3911 } else { 3912 com->modem_checking = 0; 3913 } 3914} 3915 3916static void 3917pc98_msrint_start(dev_t dev) 3918{ 3919 struct com_s *com; 3920 int mynor; 3921 int unit; 3922 int s = spltty(); 3923 3924 mynor = minor(dev); 3925 unit = MINOR_TO_UNIT(mynor); 3926 com = com_addr(unit); 3927 /* modem control line check routine envoke interval is 1/10 sec */ 3928 if ( com->modem_checking == 0 ) { 3929 com->pc98_prev_modem_status = pc98_get_modem_status(com); 3930 com->pc98_modem_delta = 0; 3931 timeout(pc98_check_msr, (caddr_t)dev, 3932 PC98_CHECK_MODEM_INTERVAL); 3933 com->modem_checking = 1; 3934 } 3935 splx(s); 3936} 3937 3938static void 3939pc98_disable_i8251_interrupt(struct com_s *com, int mod) 3940{ 3941 /* disable interrupt */ 3942 register int tmp; 3943 3944 mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3945 COM_INT_DISABLE 3946 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3947 outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp ); 3948 COM_INT_ENABLE 3949} 3950 3951static void 3952pc98_enable_i8251_interrupt(struct com_s *com, int mod) 3953{ 3954 register int tmp; 3955 3956 COM_INT_DISABLE 3957 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3958 outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp ); 3959 COM_INT_ENABLE 3960} 3961 3962static int 3963pc98_check_i8251_interrupt(struct com_s *com) 3964{ 3965 return ( com->intr_enable & 0x07 ); 3966} 3967 3968static void 3969pc98_i8251_clear_cmd(struct com_s *com, int x) 3970{ 3971 int tmp; 3972 3973 COM_INT_DISABLE 3974 tmp = com->pc98_prev_siocmd & ~(x); 3975 outb(com->cmd_port, tmp); 3976 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3977 COM_INT_ENABLE 3978} 3979 3980static void 3981pc98_i8251_or_cmd(struct com_s *com, int x) 3982{ 3983 int tmp; 3984 3985 COM_INT_DISABLE 3986 tmp = com->pc98_prev_siocmd | (x); 3987 outb(com->cmd_port, tmp); 3988 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3989 COM_INT_ENABLE 3990} 3991 3992static void 3993pc98_i8251_set_cmd(struct com_s *com, int x) 3994{ 3995 int tmp; 3996 3997 COM_INT_DISABLE 3998 tmp = (x); 3999 outb(com->cmd_port, tmp); 4000 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4001 COM_INT_ENABLE 4002} 4003 4004static void 4005pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x) 4006{ 4007 int tmp; 4008 COM_INT_DISABLE 4009 tmp = com->pc98_prev_siocmd & ~(clr); 4010 tmp |= (x); 4011 outb(com->cmd_port, tmp); 4012 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4013 COM_INT_ENABLE 4014} 4015 4016static int 4017pc98_i8251_get_cmd(struct com_s *com) 4018{ 4019 return com->pc98_prev_siocmd; 4020} 4021 4022static int 4023pc98_i8251_get_mod(struct com_s *com) 4024{ 4025 return com->pc98_prev_siomod; 4026} 4027 4028static void 4029pc98_i8251_reset(struct com_s *com, int mode, int command) 4030{ 4031 outb(com->cmd_port, 0); /* dummy */ 4032 DELAY(2); 4033 outb(com->cmd_port, 0); /* dummy */ 4034 DELAY(2); 4035 outb(com->cmd_port, 0); /* dummy */ 4036 DELAY(2); 4037 outb(com->cmd_port, CMD8251_RESET); /* internal reset */ 4038 DELAY(2); 4039 outb(com->cmd_port, mode ); /* mode register */ 4040 com->pc98_prev_siomod = mode; 4041 DELAY(2); 4042 pc98_i8251_set_cmd( com, (command|CMD8251_ER) ); 4043} 4044 4045static void 4046pc98_check_sysclock(void) 4047{ 4048 /* get system clock from port */ 4049 if ( pc98_machine_type & M_8M ) { 4050 /* 8 MHz system & H98 */ 4051 sysclock = 8; 4052 } else { 4053 /* 5 MHz system */ 4054 sysclock = 5; 4055 } 4056} 4057 4058static void 4059com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) 4060{ 4061 int cfcr=0, count; 4062 int previnterrupt; 4063 4064 count = pc98_ttspeedtab( com, speed ); 4065 if ( count < 0 ) return; 4066 4067 previnterrupt = pc98_check_i8251_interrupt(com); 4068 pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx ); 4069 4070 switch ( cflag&CSIZE ) { 4071 case CS5: 4072 cfcr = MOD8251_5BITS; break; 4073 case CS6: 4074 cfcr = MOD8251_6BITS; break; 4075 case CS7: 4076 cfcr = MOD8251_7BITS; break; 4077 case CS8: 4078 cfcr = MOD8251_8BITS; break; 4079 } 4080 if ( cflag&PARENB ) { 4081 if ( cflag&PARODD ) 4082 cfcr |= MOD8251_PODD; 4083 else 4084 cfcr |= MOD8251_PEVEN; 4085 } else 4086 cfcr |= MOD8251_PDISAB; 4087 4088 if ( cflag&CSTOPB ) 4089 cfcr |= MOD8251_STOP2; 4090 else 4091 cfcr |= MOD8251_STOP1; 4092 4093 if ( count & 0x10000 ) 4094 cfcr |= MOD8251_CLKX1; 4095 else 4096 cfcr |= MOD8251_CLKX16; 4097 4098 if (epson_machine_id != 0x20) { /* XXX */ 4099 { 4100 int tmp; 4101 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP)) 4102 ; 4103 } 4104 } 4105 /* set baud rate from ospeed */ 4106 pc98_set_baud_rate( com, count ); 4107 4108 if ( cfcr != pc98_i8251_get_mod(com) ) 4109 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) ); 4110 4111 pc98_enable_i8251_interrupt( com, previnterrupt ); 4112} 4113 4114static int 4115pc98_ttspeedtab(struct com_s *com, int speed) 4116{ 4117 int effect_sp, count=-1, mod; 4118 4119 switch ( com->pc98_if_type ) { 4120 case COM_IF_INTERNAL: 4121 /* for *1CLK asynchronous! mode , TEFUTEFU */ 4122 effect_sp = ttspeedtab( speed, pc98speedtab ); 4123 if ( effect_sp < 0 ) 4124 effect_sp = ttspeedtab( (speed-1), pc98speedtab ); 4125 if ( effect_sp <= 0 ) 4126 return effect_sp; 4127 mod = (sysclock == 5 ? 2457600 : 1996800); 4128 if ( effect_sp == speed ) 4129 mod /= 16; 4130 count = mod / effect_sp; 4131 if ( count > 65535 ) 4132 return(-1); 4133 if ( effect_sp >= 2400 ) 4134 if ( !(sysclock != 5 && 4135 (effect_sp == 19200 || effect_sp == 38400)) ) 4136 if ( ( mod % effect_sp ) != 0 ) 4137 return(-1); 4138 if ( effect_sp != speed ) 4139 count |= 0x10000; 4140 break; 4141#ifdef COM_IF_PC9861K 4142 case COM_IF_PC9861K: 4143 effect_sp = speed; 4144 count = 1; 4145 break; 4146#endif 4147#ifdef COM_IF_PIO9032B 4148 case COM_IF_PIO9032B: 4149 if ( speed == 0 ) return 0; 4150 count = ttspeedtab( speed, comspeedtab_pio9032b ); 4151 if ( count < 0 ) return count; 4152 effect_sp = speed; 4153 break; 4154#endif 4155#ifdef COM_IF_B98_01 4156 case COM_IF_B98_01: 4157 effect_sp=speed; 4158 count = ttspeedtab( speed, comspeedtab_b98_01 ); 4159 if ( count <= 3 ) 4160 return -1; /* invalid speed/count */ 4161 if ( count <= 5 ) 4162 count |= 0x10000; /* x1 mode for 76800 and 153600 */ 4163 else 4164 count -= 4; /* x16 mode for slower */ 4165 break; 4166#endif 4167 } 4168 return count; 4169} 4170 4171static void 4172pc98_set_baud_rate( struct com_s *com, int count) 4173{ 4174 int s; 4175 4176 switch ( com->pc98_if_type ) { 4177 case COM_IF_INTERNAL: 4178 if ( count < 0 ) { 4179 printf( "[ Illegal count : %d ]", count ); 4180 return; 4181 } else if ( count == 0) 4182 return; 4183 /* set i8253 */ 4184 s = splclock(); 4185 outb( 0x77, 0xb6 ); 4186 outb( 0x5f, 0); 4187 outb( 0x75, count & 0xff ); 4188 outb( 0x5f, 0); 4189 outb( 0x75, (count >> 8) & 0xff ); 4190 splx(s); 4191 break; 4192#if 0 4193#ifdef COM_IF_PC9861K 4194 case COM_IF_PC9861K: 4195 break; 4196 /* ext. RS232C board: speed is determined by DIP switch */ 4197#endif 4198#endif /* 0 */ 4199#ifdef COM_IF_PIO9032B 4200 case COM_IF_PIO9032B: 4201 outb( com_addr[unit], count & 0x07 ); 4202 break; 4203#endif 4204#ifdef COM_IF_B98_01 4205 case COM_IF_B98_01: 4206 outb( com->iobase, count & 0x0f ); 4207#ifdef B98_01_OLD 4208 /* some old board should be controlled in different way, 4209 but this hasn't been tested yet.*/ 4210 outb( com->iobase+2, ( count & 0x10000 ) ? 0xf0 : 0xf2 ); 4211#endif 4212 break; 4213#endif 4214 } 4215} 4216static int 4217pc98_check_if_type( int iobase, struct siodev *iod) 4218{ 4219 int irr = 0, tmp = 0; 4220 int ret = 0; 4221 static short irq_tab[2][8] = { 4222 { 3, 5, 6, 9, 10, 12, 13, -1}, 4223 { 3, 10, 12, 13, 5, 6, 9, -1} 4224 }; 4225 iod->irq = 0; 4226 switch ( iobase & 0xff ) { 4227 case IO_COM1: 4228 iod->if_type = COM_IF_INTERNAL; 4229 ret = 0; iod->irq = 4; break; 4230#ifdef COM_IF_PC9861K 4231 case IO_COM2: 4232 iod->if_type = COM_IF_PC9861K; 4233 ret = 1; irr = 0; tmp = 3; break; 4234 case IO_COM3: 4235 iod->if_type = COM_IF_PC9861K; 4236 ret = 2; irr = 1; tmp = 3; break; 4237#endif 4238#ifdef COM_IF_PIO9032B 4239 case IO_COM_PIO9032B_2: 4240 iod->if_type = COM_IF_PIO9032B; 4241 ret = 1; irr = 0; tmp = 7; break; 4242 case IO_COM_PIO9032B_3: 4243 iod->if_type = COM_IF_PIO9032B; 4244 ret = 2; irr = 1; tmp = 7; break; 4245#endif 4246#ifdef COM_IF_B98_01 4247 case IO_COM_B98_01_2: 4248 iod->if_type = COM_IF_B98_01; 4249 ret = 1; irr = 0; tmp = 7; 4250 outb(iobase + 2, 0xf2); 4251 outb(iobase, 4); 4252 break; 4253 case IO_COM_B98_01_3: 4254 iod->if_type = COM_IF_B98_01; 4255 ret = 2; irr = 1; tmp = 7; 4256 outb(iobase + 2, 0xf2); 4257 outb(iobase , 4); 4258 break; 4259#endif 4260 default: 4261 if((iobase & 0x0f0) == 0xd0){ 4262 iod->if_type = MC16550; 4263 return 0; 4264 } 4265 return -1; 4266 } 4267 4268 iod->cmd = ( iobase & 0xff00 )|PC98SIO_cmd_port(ret); 4269 iod->sts = ( iobase & 0xff00 )|PC98SIO_sts_port(ret); 4270 iod->mod = ( iobase & 0xff00 )|PC98SIO_in_modem_port(ret); 4271 iod->ctrl = ( iobase & 0xff00 )|PC98SIO_intr_ctrl_port(ret); 4272 4273 if ( iod->irq == 0 ) { 4274 tmp &= inb( iod->mod ); 4275 iod->irq = irq_tab[irr][tmp]; 4276 if ( iod->irq == -1 ) return -1; 4277 } 4278 return 0; 4279} 4280static int 4281pc98_set_ioport( struct com_s *com, int io_base ) 4282{ 4283 int a, io, type; 4284 4285 switch ( io_base & 0xff ) { 4286 case IO_COM1: a = 0; io = 0; type = COM_IF_INTERNAL; 4287 pc98_check_sysclock(); break; 4288#ifdef COM_IF_PC9861K 4289 case IO_COM2: a = 1; io = 0; type = COM_IF_PC9861K; break; 4290 case IO_COM3: a = 2; io = 0; type = COM_IF_PC9861K; break; 4291#endif /* COM_IF_PC9861K */ 4292#ifdef COM_IF_PIO9032B 4293 /* PIO9032B : I/O address is changeable */ 4294 case IO_COM_PIO9032B_2: 4295 a = 1; io = io_base & 0xff00; 4296 type = COM_IF_PIO9032B; break; 4297 case IO_COM_PIO9032B_3: 4298 a = 2; io = io_base & 0xff00; 4299 type = COM_IF_PIO9032B; break; 4300#endif /* COM_IF_PIO9032B */ 4301#ifdef COM_IF_B98_01 4302 case IO_COM_B98_01_2: 4303 a = 1; io = 0; type = COM_IF_B98_01; break; 4304 case IO_COM_B98_01_3: 4305 a = 2; io = 0; type = COM_IF_B98_01; break; 4306#endif /* COM_IF_B98_01*/ 4307 default: /* i/o address not match */ 4308 return -1; 4309 } 4310 4311 com->pc98_if_type = type; 4312 com->data_port = io | PC98SIO_data_port(a); 4313 com->cmd_port = io | PC98SIO_cmd_port(a); 4314 com->sts_port = io | PC98SIO_sts_port(a); 4315 com->in_modem_port = io | PC98SIO_in_modem_port(a); 4316 com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(a); 4317 return 0; 4318} 4319#endif /* PC98 defined */ 4320