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