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