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