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