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