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