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