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