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