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