sio.c revision 31778
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.44 1997/12/06 13:24:54 bde 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_int_TxRx_disable( com ); 2590 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 2591 } 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#ifdef PC98 2884/* if(IS_8251(com->pc98_if_type)) 2885 com_int_Tx_enable(com); */ 2886#endif 2887 splx(s); 2888 return; 2889 } 2890 if (tp->t_outq.c_cc != 0) { 2891 struct lbq *qp; 2892 struct lbq *next; 2893 2894 if (!com->obufs[0].l_queued) { 2895 com->obufs[0].l_tail 2896 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2897 sizeof com->obuf1); 2898 com->obufs[0].l_next = NULL; 2899 com->obufs[0].l_queued = TRUE; 2900 disable_intr(); 2901 if (com->state & CS_BUSY) { 2902 qp = com->obufq.l_next; 2903 while ((next = qp->l_next) != NULL) 2904 qp = next; 2905 qp->l_next = &com->obufs[0]; 2906 } else { 2907 com->obufq.l_head = com->obufs[0].l_head; 2908 com->obufq.l_tail = com->obufs[0].l_tail; 2909 com->obufq.l_next = &com->obufs[0]; 2910 com->state |= CS_BUSY; 2911 } 2912 enable_intr(); 2913 } 2914 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2915 com->obufs[1].l_tail 2916 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2917 sizeof com->obuf2); 2918 com->obufs[1].l_next = NULL; 2919 com->obufs[1].l_queued = TRUE; 2920 disable_intr(); 2921 if (com->state & CS_BUSY) { 2922 qp = com->obufq.l_next; 2923 while ((next = qp->l_next) != NULL) 2924 qp = next; 2925 qp->l_next = &com->obufs[1]; 2926 } else { 2927 com->obufq.l_head = com->obufs[1].l_head; 2928 com->obufq.l_tail = com->obufs[1].l_tail; 2929 com->obufq.l_next = &com->obufs[1]; 2930 com->state |= CS_BUSY; 2931 } 2932 enable_intr(); 2933 } 2934 tp->t_state |= TS_BUSY; 2935 } 2936 disable_intr(); 2937 if (com->state >= (CS_BUSY | CS_TTGO)) 2938 siointr1(com); /* fake interrupt to start output */ 2939 enable_intr(); 2940#ifdef PC98 2941/* if(IS_8251(com->pc98_if_type)) 2942 com_int_Tx_enable(com); */ 2943#endif 2944 ttwwakeup(tp); 2945 splx(s); 2946} 2947 2948static void 2949siostop(tp, rw) 2950 struct tty *tp; 2951 int rw; 2952{ 2953 struct com_s *com; 2954 2955 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2956 if (com->gone) 2957 return; 2958 disable_intr(); 2959 if (rw & FWRITE) { 2960 if (com->hasfifo) 2961#ifdef COM_ESP 2962 /* XXX avoid h/w bug. */ 2963 if (!com->esp) 2964#endif 2965 /* XXX does this flush everything? */ 2966 outb(com->iobase + com_fifo, 2967 FIFO_XMT_RST | com->fifo_image); 2968 com->obufs[0].l_queued = FALSE; 2969 com->obufs[1].l_queued = FALSE; 2970 if (com->state & CS_ODONE) 2971 com_events -= LOTS_OF_EVENTS; 2972 com->state &= ~(CS_ODONE | CS_BUSY); 2973 com->tp->t_state &= ~TS_BUSY; 2974 } 2975 if (rw & FREAD) { 2976 if (com->hasfifo) 2977#ifdef COM_ESP 2978 /* XXX avoid h/w bug. */ 2979 if (!com->esp) 2980#endif 2981 /* XXX does this flush everything? */ 2982 outb(com->iobase + com_fifo, 2983 FIFO_RCV_RST | com->fifo_image); 2984 com_events -= (com->iptr - com->ibuf); 2985 com->iptr = com->ibuf; 2986 } 2987 enable_intr(); 2988 comstart(tp); 2989} 2990 2991static struct tty * 2992siodevtotty(dev) 2993 dev_t dev; 2994{ 2995 int mynor; 2996 int unit; 2997 2998 mynor = minor(dev); 2999 if (mynor & CONTROL_MASK) 3000 return (NULL); 3001 unit = MINOR_TO_UNIT(mynor); 3002 if ((u_int) unit >= NSIOTOT) 3003 return (NULL); 3004 return (&sio_tty[unit]); 3005} 3006 3007static int 3008commctl(com, bits, how) 3009 struct com_s *com; 3010 int bits; 3011 int how; 3012{ 3013 int mcr; 3014 int msr; 3015 3016 if (how == DMGET) { 3017 bits = TIOCM_LE; /* XXX - always enabled while open */ 3018 mcr = com->mcr_image; 3019 if (mcr & MCR_DTR) 3020 bits |= TIOCM_DTR; 3021 if (mcr & MCR_RTS) 3022 bits |= TIOCM_RTS; 3023 msr = com->prev_modem_status; 3024 if (msr & MSR_CTS) 3025 bits |= TIOCM_CTS; 3026 if (msr & MSR_DCD) 3027 bits |= TIOCM_CD; 3028 if (msr & MSR_DSR) 3029 bits |= TIOCM_DSR; 3030 /* 3031 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI 3032 * more volatile by reading the modem status a lot. Perhaps 3033 * we should latch both bits until the status is read here. 3034 */ 3035 if (msr & (MSR_RI | MSR_TERI)) 3036 bits |= TIOCM_RI; 3037 return (bits); 3038 } 3039 mcr = 0; 3040 if (bits & TIOCM_DTR) 3041 mcr |= MCR_DTR; 3042 if (bits & TIOCM_RTS) 3043 mcr |= MCR_RTS; 3044 if (com->gone) 3045 return(0); 3046 disable_intr(); 3047 switch (how) { 3048 case DMSET: 3049 outb(com->modem_ctl_port, 3050 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); 3051 break; 3052 case DMBIS: 3053 outb(com->modem_ctl_port, com->mcr_image |= mcr); 3054 break; 3055 case DMBIC: 3056 outb(com->modem_ctl_port, com->mcr_image &= ~mcr); 3057 break; 3058 } 3059 enable_intr(); 3060 return (0); 3061} 3062 3063static void 3064siosettimeout() 3065{ 3066 struct com_s *com; 3067 bool_t someopen; 3068 int unit; 3069 3070 /* 3071 * Set our timeout period to 1 second if no polled devices are open. 3072 * Otherwise set it to max(1/200, 1/hz). 3073 * Enable timeouts iff some device is open. 3074 */ 3075 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3076 sio_timeout = hz; 3077 someopen = FALSE; 3078 for (unit = 0; unit < NSIOTOT; ++unit) { 3079 com = com_addr(unit); 3080 if (com != NULL && com->tp != NULL 3081 && com->tp->t_state & TS_ISOPEN && !com->gone) { 3082 someopen = TRUE; 3083 if (com->poll || com->poll_output) { 3084 sio_timeout = hz > 200 ? hz / 200 : 1; 3085 break; 3086 } 3087 } 3088 } 3089 if (someopen) { 3090 sio_timeouts_until_log = hz / sio_timeout; 3091 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 3092 sio_timeout); 3093 } else { 3094 /* Flush error messages, if any. */ 3095 sio_timeouts_until_log = 1; 3096 comwakeup((void *)NULL); 3097 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3098 } 3099} 3100 3101static void 3102comwakeup(chan) 3103 void *chan; 3104{ 3105 struct com_s *com; 3106 int unit; 3107 3108 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 3109 3110 /* 3111 * Recover from lost output interrupts. 3112 * Poll any lines that don't use interrupts. 3113 */ 3114 for (unit = 0; unit < NSIOTOT; ++unit) { 3115 com = com_addr(unit); 3116 if (com != NULL && !com->gone 3117 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 3118 disable_intr(); 3119 siointr1(com); 3120 enable_intr(); 3121 } 3122 } 3123 3124 /* 3125 * Check for and log errors, but not too often. 3126 */ 3127 if (--sio_timeouts_until_log > 0) 3128 return; 3129 sio_timeouts_until_log = hz / sio_timeout; 3130 for (unit = 0; unit < NSIOTOT; ++unit) { 3131 int errnum; 3132 3133 com = com_addr(unit); 3134 if (com == NULL) 3135 continue; 3136 if (com->gone) 3137 continue; 3138 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 3139 u_int delta; 3140 u_long total; 3141 3142 disable_intr(); 3143 delta = com->delta_error_counts[errnum]; 3144 com->delta_error_counts[errnum] = 0; 3145 enable_intr(); 3146 if (delta == 0) 3147 continue; 3148 total = com->error_counts[errnum] += delta; 3149 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", 3150 unit, delta, error_desc[errnum], 3151 delta == 1 ? "" : "s", total); 3152 } 3153 } 3154} 3155 3156#ifdef PC98 3157/* commint is called when modem control line changes */ 3158static void 3159commint(dev_t dev) 3160{ 3161 register struct tty *tp; 3162 int stat,delta; 3163 struct com_s *com; 3164 int mynor,unit; 3165 3166 mynor = minor(dev); 3167 unit = MINOR_TO_UNIT(mynor); 3168 com = com_addr(unit); 3169 tp = com->tp; 3170 3171 stat = com_tiocm_get(com); 3172 delta = com_tiocm_get_delta(com); 3173 3174 if (com->state & CS_CTS_OFLOW) { 3175 if (stat & TIOCM_CTS) 3176 com->state |= CS_ODEVREADY; 3177 else 3178 com->state &= ~CS_ODEVREADY; 3179 } 3180 if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) { 3181 if (stat & TIOCM_CAR ) 3182 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 3183 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 3184 /* negate DTR, RTS */ 3185 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ? 3186 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE ); 3187 /* disable IENABLE */ 3188 com_int_TxRx_disable( com ); 3189 } 3190 } 3191} 3192#endif 3193 3194static void 3195disc_optim(tp, t, com) 3196 struct tty *tp; 3197 struct termios *t; 3198 struct com_s *com; 3199{ 3200 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 3201 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 3202 && (!(t->c_iflag & PARMRK) 3203 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 3204 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 3205 && linesw[tp->t_line].l_rint == ttyinput) 3206 tp->t_state |= TS_CAN_BYPASS_L_RINT; 3207 else 3208 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 3209 /* 3210 * Prepare to reduce input latency for packet 3211 * discplines with a end of packet character. 3212 */ 3213 if (tp->t_line == SLIPDISC) 3214 com->hotchar = 0xc0; 3215 else if (tp->t_line == PPPDISC) 3216 com->hotchar = 0x7e; 3217 else 3218 com->hotchar = 0; 3219} 3220 3221/* 3222 * Following are all routines needed for SIO to act as console 3223 */ 3224#include <machine/cons.h> 3225 3226struct siocnstate { 3227 u_char dlbl; 3228 u_char dlbh; 3229 u_char ier; 3230 u_char cfcr; 3231 u_char mcr; 3232}; 3233 3234static speed_t siocngetspeed __P((Port_t, struct speedtab *)); 3235static void siocnclose __P((struct siocnstate *sp)); 3236static void siocnopen __P((struct siocnstate *sp)); 3237static void siocntxwait __P((void)); 3238 3239static void 3240siocntxwait() 3241{ 3242 int timo; 3243 3244 /* 3245 * Wait for any pending transmission to finish. Required to avoid 3246 * the UART lockup bug when the speed is changed, and for normal 3247 * transmits. 3248 */ 3249 timo = 100000; 3250 while ((inb(siocniobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) 3251 != (LSR_TSRE | LSR_TXRDY) && --timo != 0) 3252 ; 3253} 3254 3255/* 3256 * Read the serial port specified and try to figure out what speed 3257 * it's currently running at. We're assuming the serial port has 3258 * been initialized and is basicly idle. This routine is only intended 3259 * to be run at system startup. 3260 * 3261 * If the value read from the serial port doesn't make sense, return 0. 3262 */ 3263 3264static speed_t 3265siocngetspeed(iobase, table) 3266 Port_t iobase; 3267 struct speedtab *table; 3268{ 3269 int code; 3270 u_char dlbh; 3271 u_char dlbl; 3272 u_char cfcr; 3273 3274 cfcr = inb(iobase + com_cfcr); 3275 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 3276 3277 dlbl = inb(iobase + com_dlbl); 3278 dlbh = inb(iobase + com_dlbh); 3279 3280 outb(iobase + com_cfcr, cfcr); 3281 3282 code = dlbh << 8 | dlbl; 3283 3284 for ( ; table->sp_speed != -1; table++) 3285 if (table->sp_code == code) 3286 return (table->sp_speed); 3287 3288 return 0; /* didn't match anything sane */ 3289} 3290 3291static void 3292siocnopen(sp) 3293 struct siocnstate *sp; 3294{ 3295 int divisor; 3296 u_char dlbh; 3297 u_char dlbl; 3298 Port_t iobase; 3299 3300 /* 3301 * Save all the device control registers except the fifo register 3302 * and set our default ones (cs8 -parenb speed=comdefaultrate). 3303 * We can't save the fifo register since it is read-only. 3304 */ 3305 iobase = siocniobase; 3306 sp->ier = inb(iobase + com_ier); 3307 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ 3308 siocntxwait(); 3309 sp->cfcr = inb(iobase + com_cfcr); 3310 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3311 sp->dlbl = inb(iobase + com_dlbl); 3312 sp->dlbh = inb(iobase + com_dlbh); 3313 /* 3314 * Only set the divisor registers if they would change, since on 3315 * some 16550 incompatibles (Startech), setting them clears the 3316 * data input register. This also reduces the effects of the 3317 * UMC8669F bug. 3318 */ 3319 divisor = ttspeedtab(comdefaultrate, comspeedtab); 3320 dlbl = divisor & 0xFF; 3321 if (sp->dlbl != dlbl) 3322 outb(iobase + com_dlbl, dlbl); 3323 dlbh = (u_int) divisor >> 8; 3324 if (sp->dlbh != dlbh) 3325 outb(iobase + com_dlbh, dlbh); 3326 outb(iobase + com_cfcr, CFCR_8BITS); 3327 sp->mcr = inb(iobase + com_mcr); 3328 /* 3329 * We don't want interrupts, but must be careful not to "disable" 3330 * them by clearing the MCR_IENABLE bit, since that might cause 3331 * an interrupt by floating the IRQ line. 3332 */ 3333 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); 3334} 3335 3336static void 3337siocnclose(sp) 3338 struct siocnstate *sp; 3339{ 3340 Port_t iobase; 3341 3342 /* 3343 * Restore the device control registers. 3344 */ 3345 siocntxwait(); 3346 iobase = siocniobase; 3347 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3348 if (sp->dlbl != inb(iobase + com_dlbl)) 3349 outb(iobase + com_dlbl, sp->dlbl); 3350 if (sp->dlbh != inb(iobase + com_dlbh)) 3351 outb(iobase + com_dlbh, sp->dlbh); 3352 outb(iobase + com_cfcr, sp->cfcr); 3353 /* 3354 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. 3355 */ 3356 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); 3357 outb(iobase + com_ier, sp->ier); 3358} 3359 3360void 3361siocnprobe(cp) 3362 struct consdev *cp; 3363{ 3364 struct isa_device *dvp; 3365 int s; 3366 struct siocnstate sp; 3367 speed_t boot_speed; 3368 3369 /* 3370 * Find our first enabled console, if any. If it is a high-level 3371 * console device, then initialize it and return successfully. 3372 * If it is a low-level console device, then initialize it and 3373 * return unsuccessfully. It must be initialized in both cases 3374 * for early use by console drivers and debuggers. Initializing 3375 * the hardware is not necessary in all cases, since the i/o 3376 * routines initialize it on the fly, but it is necessary if 3377 * input might arrive while the hardware is switched back to an 3378 * uninitialized state. We can't handle multiple console devices 3379 * yet because our low-level routines don't take a device arg. 3380 * We trust the user to set the console flags properly so that we 3381 * don't need to probe. 3382 */ 3383 cp->cn_pri = CN_DEAD; 3384 for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) 3385 if (dvp->id_driver == &siodriver && dvp->id_enabled 3386 && COM_CONSOLE(dvp)) { 3387 siocniobase = dvp->id_iobase; 3388 s = spltty(); 3389 if (boothowto & RB_SERIAL) { 3390 boot_speed = siocngetspeed(siocniobase, 3391 comspeedtab); 3392 if (boot_speed) 3393 comdefaultrate = boot_speed; 3394 } 3395 siocnopen(&sp); 3396 splx(s); 3397 if (!COM_LLCONSOLE(dvp)) { 3398 cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit); 3399 cp->cn_pri = COM_FORCECONSOLE(dvp) 3400 || boothowto & RB_SERIAL 3401 ? CN_REMOTE : CN_NORMAL; 3402 } 3403 break; 3404 } 3405} 3406 3407void 3408siocninit(cp) 3409 struct consdev *cp; 3410{ 3411 comconsole = DEV_TO_UNIT(cp->cn_dev); 3412} 3413 3414int 3415siocncheckc(dev) 3416 dev_t dev; 3417{ 3418 int c; 3419 Port_t iobase; 3420 int s; 3421 struct siocnstate sp; 3422 3423 iobase = siocniobase; 3424 s = spltty(); 3425 siocnopen(&sp); 3426 if (inb(iobase + com_lsr) & LSR_RXRDY) 3427 c = inb(iobase + com_data); 3428 else 3429 c = -1; 3430 siocnclose(&sp); 3431 splx(s); 3432 return (c); 3433} 3434 3435 3436int 3437siocngetc(dev) 3438 dev_t dev; 3439{ 3440 int c; 3441 Port_t iobase; 3442 int s; 3443 struct siocnstate sp; 3444 3445 iobase = siocniobase; 3446 s = spltty(); 3447 siocnopen(&sp); 3448 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 3449 ; 3450 c = inb(iobase + com_data); 3451 siocnclose(&sp); 3452 splx(s); 3453 return (c); 3454} 3455 3456void 3457siocnputc(dev, c) 3458 dev_t dev; 3459 int c; 3460{ 3461 int s; 3462 struct siocnstate sp; 3463 3464 s = spltty(); 3465 siocnopen(&sp); 3466 siocntxwait(); 3467 outb(siocniobase + com_data, c); 3468 siocnclose(&sp); 3469 splx(s); 3470} 3471 3472#ifdef DSI_SOFT_MODEM 3473/* 3474 * The magic code to download microcode to a "Connection 14.4+Fax" 3475 * modem from Digicom Systems Inc. Very magic. 3476 */ 3477 3478#define DSI_ERROR(str) { ptr = str; goto error; } 3479static int 3480LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr) 3481{ 3482 int int_c,int_k; 3483 int data_0188, data_0187; 3484 3485 /* 3486 * First see if it is a DSI SoftModem 3487 */ 3488 if(!((inb(base_io+7) ^ inb(base_io+7) & 0x80))) 3489 return ENODEV; 3490 3491 data_0188 = inb(base_io+4); 3492 data_0187 = inb(base_io+3); 3493 outb(base_io+3,0x80); 3494 outb(base_io+4,0x0C); 3495 outb(base_io+0,0x31); 3496 outb(base_io+1,0x8C); 3497 outb(base_io+7,0x10); 3498 outb(base_io+7,0x19); 3499 3500 if(0x18 != (inb(base_io+7) & 0x1A)) 3501 DSI_ERROR("dsp bus not granted"); 3502 3503 if(0x01 != (inb(base_io+7) & 0x01)) { 3504 outb(base_io+7,0x18); 3505 outb(base_io+7,0x19); 3506 if(0x01 != (inb(base_io+7) & 0x01)) 3507 DSI_ERROR("program mem not granted"); 3508 } 3509 3510 int_c = 0; 3511 3512 while(1) { 3513 if(int_c >= 7 || size <= 0x1800) 3514 break; 3515 3516 for(int_k = 0 ; int_k < 0x800; int_k++) { 3517 outb(base_io+0,*ptr++); 3518 outb(base_io+1,*ptr++); 3519 outb(base_io+2,*ptr++); 3520 } 3521 3522 size -= 0x1800; 3523 int_c++; 3524 } 3525 3526 if(size > 0x1800) { 3527 outb(base_io+7,0x18); 3528 outb(base_io+7,0x19); 3529 if(0x00 != (inb(base_io+7) & 0x01)) 3530 DSI_ERROR("program data not granted"); 3531 3532 for(int_k = 0 ; int_k < 0x800; int_k++) { 3533 outb(base_io+1,*ptr++); 3534 outb(base_io+2,0); 3535 outb(base_io+1,*ptr++); 3536 outb(base_io+2,*ptr++); 3537 } 3538 3539 size -= 0x1800; 3540 3541 while(size > 0x1800) { 3542 for(int_k = 0 ; int_k < 0xC00; int_k++) { 3543 outb(base_io+1,*ptr++); 3544 outb(base_io+2,*ptr++); 3545 } 3546 size -= 0x1800; 3547 } 3548 3549 if(size < 0x1800) { 3550 for(int_k=0;int_k<size/2;int_k++) { 3551 outb(base_io+1,*ptr++); 3552 outb(base_io+2,*ptr++); 3553 } 3554 } 3555 3556 } else if (size > 0) { 3557 if(int_c == 7) { 3558 outb(base_io+7,0x18); 3559 outb(base_io+7,0x19); 3560 if(0x00 != (inb(base_io+7) & 0x01)) 3561 DSI_ERROR("program data not granted"); 3562 for(int_k = 0 ; int_k < size/3; int_k++) { 3563 outb(base_io+1,*ptr++); 3564 outb(base_io+2,0); 3565 outb(base_io+1,*ptr++); 3566 outb(base_io+2,*ptr++); 3567 } 3568 } else { 3569 for(int_k = 0 ; int_k < size/3; int_k++) { 3570 outb(base_io+0,*ptr++); 3571 outb(base_io+1,*ptr++); 3572 outb(base_io+2,*ptr++); 3573 } 3574 } 3575 } 3576 outb(base_io+7,0x11); 3577 outb(base_io+7,3); 3578 3579 outb(base_io+4,data_0188 & 0xfb); 3580 3581 outb(base_io+3,data_0187); 3582 3583 return 0; 3584error: 3585 printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",unit,ptr); 3586 outb(base_io+7,0x00); \ 3587 outb(base_io+3,data_0187); \ 3588 outb(base_io+4,data_0188); \ 3589 return EIO; 3590} 3591#endif /* DSI_SOFT_MODEM */ 3592 3593/* 3594 * support PnP cards if we are using 'em 3595 */ 3596 3597#if NPNP > 0 3598 3599static struct siopnp_ids { 3600 u_long vend_id; 3601 char *id_str; 3602} siopnp_ids[] = { 3603 { 0x8113b04e, "Supra1381"}, 3604 { 0x9012b04e, "Supra1290"}, 3605 { 0x11007256, "USR0011"}, 3606 { 0 } 3607}; 3608 3609static char *siopnp_probe(u_long csn, u_long vend_id); 3610static void siopnp_attach(u_long csn, u_long vend_id, char *name, 3611 struct isa_device *dev); 3612static u_long nsiopnp = NSIO; 3613 3614static struct pnp_device siopnp = { 3615 "siopnp", 3616 siopnp_probe, 3617 siopnp_attach, 3618 &nsiopnp, 3619 &tty_imask 3620}; 3621DATA_SET (pnpdevice_set, siopnp); 3622 3623static char * 3624siopnp_probe(u_long csn, u_long vend_id) 3625{ 3626 struct siopnp_ids *ids; 3627 char *s = NULL; 3628 3629 for(ids = siopnp_ids; ids->vend_id != 0; ids++) { 3630 if (vend_id == ids->vend_id) { 3631 s = ids->id_str; 3632 break; 3633 } 3634 } 3635 3636 if (s) { 3637 struct pnp_cinfo d; 3638 read_pnp_parms(&d, 0); 3639 if (d.enable == 0 || d.flags & 1) { 3640 printf("CSN %d is disabled.\n", csn); 3641 return (NULL); 3642 } 3643 3644 } 3645 3646 return (s); 3647} 3648 3649static void 3650siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) 3651{ 3652 struct pnp_cinfo d; 3653 struct isa_device *dvp; 3654 3655 if (dev->id_unit >= NSIOTOT) 3656 return; 3657 3658 if (read_pnp_parms(&d, 0) == 0) { 3659 printf("failed to read pnp parms\n"); 3660 return; 3661 } 3662 3663 write_pnp_parms(&d, 0); 3664 3665 enable_pnp_card(); 3666 3667 dev->id_iobase = d.port[0]; 3668 dev->id_irq = (1 << d.irq[0]); 3669 dev->id_intr = siointr; 3670 dev->id_ri_flags = RI_FAST; 3671 dev->id_drq = -1; 3672 3673 if (dev->id_driver == NULL) { 3674 dev->id_driver = &siodriver; 3675 dvp = find_isadev(isa_devtab_tty, &siodriver, 0); 3676 if (dvp != NULL) 3677 dev->id_id = dvp->id_id; 3678 } 3679 3680 if ((dev->id_alive = sioprobe(dev)) != 0) 3681 sioattach(dev); 3682 else 3683 printf("sio%d: probe failed\n", dev->id_unit); 3684} 3685#endif 3686#ifdef PC98 3687/* 3688 * pc98 local function 3689 */ 3690 3691static void 3692com_tiocm_set(struct com_s *com, int msr) 3693{ 3694 int s; 3695 int tmp = 0; 3696 int mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS; 3697 3698 s=spltty(); 3699 com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ) 3700 | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3701 tmp |= (CMD8251_TxEN|CMD8251_RxEN); 3702 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3703 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3704 pc98_i8251_clear_or_cmd( com, mask, tmp ); 3705 splx(s); 3706} 3707 3708static void 3709com_tiocm_bis(struct com_s *com, int msr) 3710{ 3711 int s; 3712 int tmp = 0; 3713 3714 s=spltty(); 3715 com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3716 tmp |= CMD8251_TxEN|CMD8251_RxEN; 3717 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3718 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3719 3720 pc98_i8251_or_cmd( com, tmp ); 3721 splx(s); 3722} 3723 3724static void 3725com_tiocm_bic(struct com_s *com, int msr) 3726{ 3727 int s; 3728 int tmp = msr; 3729 3730 s=spltty(); 3731 com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3732 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3733 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3734 3735 pc98_i8251_clear_cmd( com, tmp ); 3736 splx(s); 3737} 3738 3739static int 3740com_tiocm_get(struct com_s *com) 3741{ 3742 return( com->pc98_prev_modem_status ); 3743} 3744 3745static int 3746com_tiocm_get_delta(struct com_s *com) 3747{ 3748 int tmp; 3749 3750 tmp = com->pc98_modem_delta; 3751 com->pc98_modem_delta = 0; 3752 return( tmp ); 3753} 3754 3755/* convert to TIOCM_?? ( ioctl.h ) */ 3756static int 3757pc98_get_modem_status(struct com_s *com) 3758{ 3759 int stat, stat2; 3760 register int msr; 3761 3762 stat = inb(com->sts_port); 3763 stat2 = inb(com->in_modem_port); 3764 msr = com->pc98_prev_modem_status 3765 & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3766 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR; 3767 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI; 3768 if ( stat & STS8251_DSR ) msr |= TIOCM_DSR; 3769 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS; 3770#if COM_CARRIER_DETECT_EMULATE 3771 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { 3772 msr |= TIOCM_CAR; 3773 } 3774#endif 3775 return(msr); 3776} 3777 3778static void 3779pc98_check_msr(void* chan) 3780{ 3781 int msr, delta; 3782 int s; 3783 register struct tty *tp; 3784 struct com_s *com; 3785 int mynor; 3786 int unit; 3787 dev_t dev; 3788 3789 dev=(dev_t)chan; 3790 mynor = minor(dev); 3791 unit = MINOR_TO_UNIT(mynor); 3792 com = com_addr(unit); 3793 tp = com->tp; 3794 3795 s = spltty(); 3796 msr = pc98_get_modem_status(com); 3797 /* make change flag */ 3798 delta = msr ^ com->pc98_prev_modem_status; 3799 if ( delta & TIOCM_CAR ) { 3800 if ( com->modem_car_chg_timer ) { 3801 if ( -- com->modem_car_chg_timer ) 3802 msr ^= TIOCM_CAR; 3803 } else { 3804 if ( com->modem_car_chg_timer = ( msr & TIOCM_CAR ) ? 3805 DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE ) 3806 msr ^= TIOCM_CAR; 3807 } 3808 } else 3809 com->modem_car_chg_timer = 0; 3810 delta = ( msr ^ com->pc98_prev_modem_status ) & 3811 (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3812 com->pc98_prev_modem_status = msr; 3813 delta = ( com->pc98_modem_delta |= delta ); 3814 splx(s); 3815 if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) { 3816 if ( delta ) { 3817 commint(dev); 3818 } 3819 timeout(pc98_check_msr, (caddr_t)dev, 3820 PC98_CHECK_MODEM_INTERVAL); 3821 } else { 3822 com->modem_checking = 0; 3823 } 3824} 3825 3826static void 3827pc98_msrint_start(dev_t dev) 3828{ 3829 struct com_s *com; 3830 int mynor; 3831 int unit; 3832 int s = spltty(); 3833 3834 mynor = minor(dev); 3835 unit = MINOR_TO_UNIT(mynor); 3836 com = com_addr(unit); 3837 /* modem control line check routine envoke interval is 1/10 sec */ 3838 if ( com->modem_checking == 0 ) { 3839 com->pc98_prev_modem_status = pc98_get_modem_status(com); 3840 com->pc98_modem_delta = 0; 3841 timeout(pc98_check_msr, (caddr_t)dev, 3842 PC98_CHECK_MODEM_INTERVAL); 3843 com->modem_checking = 1; 3844 } 3845 splx(s); 3846} 3847 3848static void 3849pc98_disable_i8251_interrupt(struct com_s *com, int mod) 3850{ 3851 /* disable interrupt */ 3852 register int tmp; 3853 3854 mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3855 COM_INT_DISABLE 3856 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3857 outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp ); 3858 COM_INT_ENABLE 3859} 3860 3861static void 3862pc98_enable_i8251_interrupt(struct com_s *com, int mod) 3863{ 3864 register int tmp; 3865 3866 COM_INT_DISABLE 3867 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3868 outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp ); 3869 COM_INT_ENABLE 3870} 3871 3872static int 3873pc98_check_i8251_interrupt(struct com_s *com) 3874{ 3875 return ( com->intr_enable & 0x07 ); 3876} 3877 3878static void 3879pc98_i8251_clear_cmd(struct com_s *com, int x) 3880{ 3881 int tmp; 3882 3883 COM_INT_DISABLE 3884 tmp = com->pc98_prev_siocmd & ~(x); 3885 outb(com->cmd_port, tmp); 3886 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3887 COM_INT_ENABLE 3888} 3889 3890static void 3891pc98_i8251_or_cmd(struct com_s *com, int x) 3892{ 3893 int tmp; 3894 3895 COM_INT_DISABLE 3896 tmp = com->pc98_prev_siocmd | (x); 3897 outb(com->cmd_port, tmp); 3898 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3899 COM_INT_ENABLE 3900} 3901 3902static void 3903pc98_i8251_set_cmd(struct com_s *com, int x) 3904{ 3905 int tmp; 3906 3907 COM_INT_DISABLE 3908 tmp = (x); 3909 outb(com->cmd_port, tmp); 3910 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3911 COM_INT_ENABLE 3912} 3913 3914static void 3915pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x) 3916{ 3917 int tmp; 3918 COM_INT_DISABLE 3919 tmp = com->pc98_prev_siocmd & ~(clr); 3920 tmp |= (x); 3921 outb(com->cmd_port, tmp); 3922 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3923 COM_INT_ENABLE 3924} 3925 3926static int 3927pc98_i8251_get_cmd(struct com_s *com) 3928{ 3929 return com->pc98_prev_siocmd; 3930} 3931 3932static int 3933pc98_i8251_get_mod(struct com_s *com) 3934{ 3935 return com->pc98_prev_siomod; 3936} 3937 3938static void 3939pc98_i8251_reset(struct com_s *com, int mode, int command) 3940{ 3941 outb(com->cmd_port, 0); /* dummy */ 3942 DELAY(2); 3943 outb(com->cmd_port, 0); /* dummy */ 3944 DELAY(2); 3945 outb(com->cmd_port, 0); /* dummy */ 3946 DELAY(2); 3947 outb(com->cmd_port, CMD8251_RESET); /* internal reset */ 3948 DELAY(2); 3949 outb(com->cmd_port, mode ); /* mode register */ 3950 com->pc98_prev_siomod = mode; 3951 DELAY(2); 3952 pc98_i8251_set_cmd( com, (command|CMD8251_ER) ); 3953} 3954 3955static void 3956pc98_check_sysclock(void) 3957{ 3958 /* get system clock from port */ 3959 if ( pc98_machine_type & M_8M ) { 3960 /* 8 MHz system & H98 */ 3961 sysclock = 8; 3962 } else { 3963 /* 5 MHz system */ 3964 sysclock = 5; 3965 } 3966} 3967 3968static void 3969com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) 3970{ 3971 int cfcr=0, count; 3972 int previnterrupt; 3973 3974 count = pc98_ttspeedtab( com, speed ); 3975 if ( count < 0 ) return; 3976 3977 previnterrupt = pc98_check_i8251_interrupt(com); 3978 pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx ); 3979 3980 switch ( cflag&CSIZE ) { 3981 case CS5: 3982 cfcr = MOD8251_5BITS; break; 3983 case CS6: 3984 cfcr = MOD8251_6BITS; break; 3985 case CS7: 3986 cfcr = MOD8251_7BITS; break; 3987 case CS8: 3988 cfcr = MOD8251_8BITS; break; 3989 } 3990 if ( cflag&PARENB ) { 3991 if ( cflag&PARODD ) 3992 cfcr |= MOD8251_PODD; 3993 else 3994 cfcr |= MOD8251_PEVEN; 3995 } else 3996 cfcr |= MOD8251_PDISAB; 3997 3998 if ( cflag&CSTOPB ) 3999 cfcr |= MOD8251_STOP2; 4000 else 4001 cfcr |= MOD8251_STOP1; 4002 4003 if ( count & 0x10000 ) 4004 cfcr |= MOD8251_CLKX1; 4005 else 4006 cfcr |= MOD8251_CLKX16; 4007 4008 if (epson_machine_id != 0x20) { /* XXX */ 4009 { 4010 int tmp; 4011 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP)) 4012 ; 4013 } 4014 } 4015 /* set baud rate from ospeed */ 4016 pc98_set_baud_rate( com, count ); 4017 4018 if ( cfcr != pc98_i8251_get_mod(com) ) 4019 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) ); 4020 4021 pc98_enable_i8251_interrupt( com, previnterrupt ); 4022} 4023 4024static int 4025pc98_ttspeedtab(struct com_s *com, int speed) 4026{ 4027 int effect_sp, count=-1, mod; 4028 4029 switch ( com->pc98_if_type ) { 4030 case COM_IF_INTERNAL: 4031 /* for *1CLK asynchronous! mode , TEFUTEFU */ 4032 effect_sp = ttspeedtab( speed, pc98speedtab ); 4033 if ( effect_sp < 0 ) 4034 effect_sp = ttspeedtab( (speed-1), pc98speedtab ); 4035 if ( effect_sp <= 0 ) 4036 return effect_sp; 4037 mod = (sysclock == 5 ? 2457600 : 1996800); 4038 if ( effect_sp == speed ) 4039 mod /= 16; 4040 count = mod / effect_sp; 4041 if ( count > 65535 ) 4042 return(-1); 4043 if ( effect_sp >= 2400 ) 4044 if ( !(sysclock != 5 && 4045 (effect_sp == 19200 || effect_sp == 38400)) ) 4046 if ( ( mod % effect_sp ) != 0 ) 4047 return(-1); 4048 if ( effect_sp != speed ) 4049 count |= 0x10000; 4050 break; 4051#ifdef COM_IF_PC9861K 4052 case COM_IF_PC9861K: 4053 effect_sp = speed; 4054 count = 1; 4055 break; 4056#endif 4057#ifdef COM_IF_PIO9032B 4058 case COM_IF_PIO9032B: 4059 if ( speed == 0 ) return 0; 4060 count = ttspeedtab( speed, comspeedtab_pio9032b ); 4061 if ( count < 0 ) return count; 4062 effect_sp = speed; 4063 break; 4064#endif 4065#ifdef COM_IF_B98_01 4066 case COM_IF_B98_01: 4067 effect_sp=speed; 4068 count = ttspeedtab( speed, comspeedtab_b98_01 ); 4069 if ( count <= 3 ) 4070 return -1; /* invalid speed/count */ 4071 if ( count <= 5 ) 4072 count |= 0x10000; /* x1 mode for 76800 and 153600 */ 4073 else 4074 count -= 4; /* x16 mode for slower */ 4075 break; 4076#endif 4077 } 4078 return count; 4079} 4080 4081static void 4082pc98_set_baud_rate( struct com_s *com, int count) 4083{ 4084 int s; 4085 4086 switch ( com->pc98_if_type ) { 4087 case COM_IF_INTERNAL: 4088 if ( count < 0 ) { 4089 printf( "[ Illegal count : %d ]", count ); 4090 return; 4091 } else if ( count == 0) 4092 return; 4093 /* set i8253 */ 4094 s = splclock(); 4095 outb( 0x77, 0xb6 ); 4096 outb( 0x5f, 0); 4097 outb( 0x75, count & 0xff ); 4098 outb( 0x5f, 0); 4099 outb( 0x75, (count >> 8) & 0xff ); 4100 splx(s); 4101 break; 4102#if 0 4103#ifdef COM_IF_PC9861K 4104 case COM_IF_PC9861K: 4105 break; 4106 /* ext. RS232C board: speed is determined by DIP switch */ 4107#endif 4108#endif /* 0 */ 4109#ifdef COM_IF_PIO9032B 4110 case COM_IF_PIO9032B: 4111 outb( com_addr[unit], count & 0x07 ); 4112 break; 4113#endif 4114#ifdef COM_IF_B98_01 4115 case COM_IF_B98_01: 4116 outb( com->iobase, count & 0x0f ); 4117#ifdef B98_01_OLD 4118 /* some old board should be controlled in different way, 4119 but this hasn't been tested yet.*/ 4120 outb( com->iobase+2, ( count & 0x10000 ) ? 0xf0 : 0xf2 ); 4121#endif 4122 break; 4123#endif 4124 } 4125} 4126static int 4127pc98_check_if_type( int iobase, struct siodev *iod) 4128{ 4129 int irr = 0, tmp = 0; 4130 int ret = 0; 4131 static short irq_tab[2][8] = { 4132 { 3, 5, 6, 9, 10, 12, 13, -1}, 4133 { 3, 10, 12, 13, 5, 6, 9, -1} 4134 }; 4135 iod->irq = 0; 4136 switch ( iobase & 0xff ) { 4137 case IO_COM1: 4138 iod->if_type = COM_IF_INTERNAL; 4139 ret = 0; iod->irq = 4; break; 4140#ifdef COM_IF_PC9861K 4141 case IO_COM2: 4142 iod->if_type = COM_IF_PC9861K; 4143 ret = 1; irr = 0; tmp = 3; break; 4144 case IO_COM3: 4145 iod->if_type = COM_IF_PC9861K; 4146 ret = 2; irr = 1; tmp = 3; break; 4147#endif 4148#ifdef COM_IF_PIO9032B 4149 case IO_COM_PIO9032B_2: 4150 iod->if_type = COM_IF_PIO9032B; 4151 ret = 1; irr = 0; tmp = 7; break; 4152 case IO_COM_PIO9032B_3: 4153 iod->if_type = COM_IF_PIO9032B; 4154 ret = 2; irr = 1; tmp = 7; break; 4155#endif 4156#ifdef COM_IF_B98_01 4157 case IO_COM_B98_01_2: 4158 iod->if_type = COM_IF_B98_01; 4159 ret = 1; irr = 0; tmp = 7; 4160 outb(iobase + 2, 0xf2); 4161 outb(iobase, 4); 4162 break; 4163 case IO_COM_B98_01_3: 4164 iod->if_type = COM_IF_B98_01; 4165 ret = 2; irr = 1; tmp = 7; 4166 outb(iobase + 2, 0xf2); 4167 outb(iobase , 4); 4168 break; 4169#endif 4170 default: 4171 if((iobase & 0x0f0) == 0xd0){ 4172 iod->if_type = MC16550; 4173 return 0; 4174 } 4175 return -1; 4176 } 4177 4178 iod->cmd = ( iobase & 0xff00 )|PC98SIO_cmd_port(ret); 4179 iod->sts = ( iobase & 0xff00 )|PC98SIO_sts_port(ret); 4180 iod->mod = ( iobase & 0xff00 )|PC98SIO_in_modem_port(ret); 4181 iod->ctrl = ( iobase & 0xff00 )|PC98SIO_intr_ctrl_port(ret); 4182 4183 if ( iod->irq == 0 ) { 4184 tmp &= inb( iod->mod ); 4185 iod->irq = irq_tab[irr][tmp]; 4186 if ( iod->irq == -1 ) return -1; 4187 } 4188 return 0; 4189} 4190static int 4191pc98_set_ioport( struct com_s *com, int io_base ) 4192{ 4193 int a, io, type; 4194 4195 switch ( io_base & 0xff ) { 4196 case IO_COM1: a = 0; io = 0; type = COM_IF_INTERNAL; 4197 pc98_check_sysclock(); break; 4198#ifdef COM_IF_PC9861K 4199 case IO_COM2: a = 1; io = 0; type = COM_IF_PC9861K; break; 4200 case IO_COM3: a = 2; io = 0; type = COM_IF_PC9861K; break; 4201#endif /* COM_IF_PC9861K */ 4202#ifdef COM_IF_PIO9032B 4203 /* PIO9032B : I/O address is changeable */ 4204 case IO_COM_PIO9032B_2: 4205 a = 1; io = io_base & 0xff00; 4206 type = COM_IF_PIO9032B; break; 4207 case IO_COM_PIO9032B_3: 4208 a = 2; io = io_base & 0xff00; 4209 type = COM_IF_PIO9032B; break; 4210#endif /* COM_IF_PIO9032B */ 4211#ifdef COM_IF_B98_01 4212 case IO_COM_B98_01_2: 4213 a = 1; io = 0; type = COM_IF_B98_01; break; 4214 case IO_COM_B98_01_3: 4215 a = 2; io = 0; type = COM_IF_B98_01; break; 4216#endif /* COM_IF_B98_01*/ 4217 default: /* i/o address not match */ 4218 return -1; 4219 } 4220 4221 com->pc98_if_type = type; 4222 com->data_port = io | PC98SIO_data_port(a); 4223 com->cmd_port = io | PC98SIO_cmd_port(a); 4224 com->sts_port = io | PC98SIO_sts_port(a); 4225 com->in_modem_port = io | PC98SIO_in_modem_port(a); 4226 com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(a); 4227 return 0; 4228} 4229#endif /* PC98 defined */ 4230