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