sio.c revision 53373
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 53373 1999-11-18 12:22:09Z 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 isa_set_irq(dev, iod.irq); 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#endif 1148 mcr_image = 0; 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#ifdef PC98 2401 u_char tmp; 2402#endif 2403 2404 buf = com->ibuf; 2405 tp = com->tp; 2406 if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) { 2407 com_events -= (com->iptr - com->ibuf); 2408 com->iptr = com->ibuf; 2409 return; 2410 } 2411 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 2412 /* 2413 * Avoid the grotesquely inefficient lineswitch routine 2414 * (ttyinput) in "raw" mode. It usually takes about 450 2415 * instructions (that's without canonical processing or echo!). 2416 * slinput is reasonably fast (usually 40 instructions plus 2417 * call overhead). 2418 */ 2419 do { 2420 enable_intr(); 2421 incc = com->iptr - buf; 2422 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 2423 && (com->state & CS_RTS_IFLOW 2424 || tp->t_iflag & IXOFF) 2425 && !(tp->t_state & TS_TBLOCK)) 2426 ttyblock(tp); 2427 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 2428 += b_to_q((char *)buf, incc, &tp->t_rawq); 2429 buf += incc; 2430 tk_nin += incc; 2431 tk_rawcc += incc; 2432 tp->t_rawcc += incc; 2433 ttwakeup(tp); 2434 if (tp->t_state & TS_TTSTOP 2435 && (tp->t_iflag & IXANY 2436 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 2437 tp->t_state &= ~TS_TTSTOP; 2438 tp->t_lflag &= ~FLUSHO; 2439 comstart(tp); 2440 } 2441 disable_intr(); 2442 } while (buf < com->iptr); 2443 } else { 2444 do { 2445 enable_intr(); 2446 line_status = buf[com->ierroff]; 2447 recv_data = *buf++; 2448 if (line_status 2449 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 2450 if (line_status & LSR_BI) 2451 recv_data |= TTY_BI; 2452 if (line_status & LSR_FE) 2453 recv_data |= TTY_FE; 2454 if (line_status & LSR_OE) 2455 recv_data |= TTY_OE; 2456 if (line_status & LSR_PE) 2457 recv_data |= TTY_PE; 2458 } 2459 (*linesw[tp->t_line].l_rint)(recv_data, tp); 2460 disable_intr(); 2461 } while (buf < com->iptr); 2462 } 2463 com_events -= (com->iptr - com->ibuf); 2464 com->iptr = com->ibuf; 2465 2466 /* 2467 * There is now room for another low-level buffer full of input, 2468 * so enable RTS if it is now disabled and there is room in the 2469 * high-level buffer. 2470 */ 2471#ifdef PC98 2472 if (IS_8251(com->pc98_if_type)) 2473 tmp = com_tiocm_get(com) & TIOCM_RTS; 2474 else 2475 tmp = com->mcr_image & MCR_RTS; 2476 if ((com->state & CS_RTS_IFLOW) && !(tmp) && 2477 !(tp->t_state & TS_TBLOCK)) 2478 if (IS_8251(com->pc98_if_type)) 2479 com_tiocm_bis(com, TIOCM_RTS); 2480 else 2481 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2482#else 2483 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) && 2484 !(tp->t_state & TS_TBLOCK)) 2485 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2486#endif 2487} 2488 2489void 2490siointr(arg) 2491 void *arg; 2492{ 2493#ifndef COM_MULTIPORT 2494 COM_LOCK(); 2495 siointr1((struct com_s *) arg); 2496 COM_UNLOCK(); 2497#else /* COM_MULTIPORT */ 2498 bool_t possibly_more_intrs; 2499 int unit; 2500 struct com_s *com; 2501#ifdef PC98 2502 u_char rsa_buf_status; 2503#endif 2504 2505 /* 2506 * Loop until there is no activity on any port. This is necessary 2507 * to get an interrupt edge more than to avoid another interrupt. 2508 * If the IRQ signal is just an OR of the IRQ signals from several 2509 * devices, then the edge from one may be lost because another is 2510 * on. 2511 */ 2512 COM_LOCK(); 2513 do { 2514 possibly_more_intrs = FALSE; 2515 for (unit = 0; unit < sio_numunits; ++unit) { 2516 com = com_addr(unit); 2517 /* 2518 * XXX COM_LOCK(); 2519 * would it work here, or be counter-productive? 2520 */ 2521#ifdef PC98 2522 if (com != NULL 2523 && !com->gone 2524 && IS_8251(com->pc98_if_type)){ 2525 siointr1(com); 2526 } else 2527#endif /* PC98 */ 2528#ifdef PC98 2529 if (com != NULL 2530 && !com->gone 2531 && com->pc98_if_type == COM_IF_RSA98III) { 2532 rsa_buf_status = inb(com->rsabase + rsa_srr) & 0xc9; 2533 if ((rsa_buf_status & 0xc8) 2534 || !(rsa_buf_status & 0x01)) { 2535 siointr1(com); 2536 if(rsa_buf_status 2537 != (inb(com->rsabase + rsa_srr) & 0xc9)) 2538 possibly_more_intrs = TRUE; 2539 } 2540 } else 2541#endif 2542 if (com != NULL 2543 && !com->gone 2544 && (inb(com->int_id_port) & IIR_IMASK) 2545 != IIR_NOPEND) { 2546 siointr1(com); 2547 possibly_more_intrs = TRUE; 2548 } 2549 /* XXX COM_UNLOCK(); */ 2550 } 2551 } while (possibly_more_intrs); 2552 COM_UNLOCK(); 2553#endif /* COM_MULTIPORT */ 2554} 2555 2556static void 2557siointr1(com) 2558 struct com_s *com; 2559{ 2560 u_char line_status; 2561 u_char modem_status; 2562 u_char *ioptr; 2563 u_char recv_data; 2564 u_char int_ctl; 2565 u_char int_ctl_new; 2566 struct timecounter *tc; 2567 u_int count; 2568 2569#ifdef PC98 2570 u_char tmp=0; 2571 u_char rsa_buf_status = 0; 2572 int rsa_tx_fifo_size=0; 2573 recv_data=0; 2574#endif /* PC98 */ 2575 2576 int_ctl = inb(com->intr_ctl_port); 2577 int_ctl_new = int_ctl; 2578 2579 while (!com->gone) { 2580#ifdef PC98 2581status_read:; 2582 if (IS_8251(com->pc98_if_type)) { 2583 tmp = inb(com->sts_port); 2584more_intr: 2585 line_status = 0; 2586 if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY; 2587 if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY; 2588 if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE; 2589 if (tmp & STS8251_PE) line_status |= LSR_PE; 2590 if (tmp & STS8251_OE) line_status |= LSR_OE; 2591 if (tmp & STS8251_FE) line_status |= LSR_FE; 2592 if (tmp & STS8251_BD_SD) line_status |= LSR_BI; 2593 } else { 2594#endif /* PC98 */ 2595 if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) { 2596 modem_status = inb(com->modem_status_port); 2597 if ((modem_status ^ com->last_modem_status) & MSR_DCD) { 2598 tc = timecounter; 2599 count = tc->tc_get_timecount(tc); 2600 pps_event(&com->pps, tc, count, 2601 (modem_status & MSR_DCD) ? 2602 PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); 2603 } 2604 } 2605 line_status = inb(com->line_status_port); 2606#ifdef PC98 2607 } 2608 if (com->pc98_if_type == COM_IF_RSA98III) 2609 rsa_buf_status = inb(com->rsabase + rsa_srr); 2610#endif /* PC98 */ 2611 2612 /* input event? (check first to help avoid overruns) */ 2613#ifndef PC98 2614 while (line_status & LSR_RCV_MASK) { 2615#else 2616 while ((line_status & LSR_RCV_MASK) 2617 || (com->pc98_if_type == COM_IF_RSA98III 2618 && (rsa_buf_status & 0x08))) { 2619#endif /* PC98 */ 2620 /* break/unnattached error bits or real input? */ 2621#ifdef PC98 2622 if (IS_8251(com->pc98_if_type)) { 2623 recv_data = inb(com->data_port); 2624 if (tmp & 0x78) { 2625 pc98_i8251_or_cmd(com,CMD8251_ER); 2626 recv_data = 0; 2627 } 2628 } else { 2629#endif /* PC98 */ 2630#ifdef PC98 2631 if (com->pc98_if_type == COM_IF_RSA98III) { 2632 if (!(rsa_buf_status & 0x08)) 2633 recv_data = 0; 2634 else { 2635 recv_data = inb(com->data_port); 2636 } 2637 } else 2638#endif 2639 if (!(line_status & LSR_RXRDY)) 2640 recv_data = 0; 2641 else 2642 recv_data = inb(com->data_port); 2643#ifdef PC98 2644 } 2645#endif 2646 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) { 2647 /* 2648 * Don't store BI if IGNBRK or FE/PE if IGNPAR. 2649 * Otherwise, push the work to a higher level 2650 * (to handle PARMRK) if we're bypassing. 2651 * Otherwise, convert BI/FE and PE+INPCK to 0. 2652 * 2653 * This makes bypassing work right in the 2654 * usual "raw" case (IGNBRK set, and IGNPAR 2655 * and INPCK clear). 2656 * 2657 * Note: BI together with FE/PE means just BI. 2658 */ 2659 if (line_status & LSR_BI) { 2660#if defined(DDB) && defined(BREAK_TO_DEBUGGER) 2661 if (com->unit == comconsole) { 2662 breakpoint(); 2663 goto cont; 2664 } 2665#endif 2666 if (com->tp == NULL 2667 || com->tp->t_iflag & IGNBRK) 2668 goto cont; 2669 } else { 2670 if (com->tp == NULL 2671 || com->tp->t_iflag & IGNPAR) 2672 goto cont; 2673 } 2674 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT 2675 && (line_status & (LSR_BI | LSR_FE) 2676 || com->tp->t_iflag & INPCK)) 2677 recv_data = 0; 2678 } 2679 ++com->bytes_in; 2680 if (com->hotchar != 0 && recv_data == com->hotchar) 2681 setsofttty(); 2682 ioptr = com->iptr; 2683 if (ioptr >= com->ibufend) 2684 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 2685 else { 2686 if (com->do_timestamp) 2687 microtime(&com->timestamp); 2688 ++com_events; 2689 schedsofttty(); 2690#if 0 /* for testing input latency vs efficiency */ 2691if (com->iptr - com->ibuf == 8) 2692 setsofttty(); 2693#endif 2694 ioptr[0] = recv_data; 2695 ioptr[com->ierroff] = line_status; 2696 com->iptr = ++ioptr; 2697 if (ioptr == com->ihighwater 2698 && com->state & CS_RTS_IFLOW) 2699#ifdef PC98 2700 if (IS_8251(com->pc98_if_type)) 2701 com_tiocm_bic(com, TIOCM_RTS); 2702 else 2703#endif 2704 outb(com->modem_ctl_port, 2705 com->mcr_image &= ~MCR_RTS); 2706 if (line_status & LSR_OE) 2707 CE_RECORD(com, CE_OVERRUN); 2708 } 2709cont: 2710 /* 2711 * "& 0x7F" is to avoid the gcc-1.40 generating a slow 2712 * jump from the top of the loop to here 2713 */ 2714#ifdef PC98 2715 if (IS_8251(com->pc98_if_type)) 2716 goto status_read; 2717 else 2718#endif 2719 line_status = inb(com->line_status_port) & 0x7F; 2720#ifdef PC98 2721 if (com->pc98_if_type == COM_IF_RSA98III) 2722 rsa_buf_status = inb(com->rsabase + rsa_srr); 2723#endif /* PC98 */ 2724 } 2725 2726 /* modem status change? (always check before doing output) */ 2727#ifdef PC98 2728 if (!IS_8251(com->pc98_if_type)) { 2729#endif 2730 modem_status = inb(com->modem_status_port); 2731 if (modem_status != com->last_modem_status) { 2732 if (com->do_dcd_timestamp 2733 && !(com->last_modem_status & MSR_DCD) 2734 && modem_status & MSR_DCD) 2735 microtime(&com->dcd_timestamp); 2736 2737 /* 2738 * Schedule high level to handle DCD changes. Note 2739 * that we don't use the delta bits anywhere. Some 2740 * UARTs mess them up, and it's easy to remember the 2741 * previous bits and calculate the delta. 2742 */ 2743 com->last_modem_status = modem_status; 2744 if (!(com->state & CS_CHECKMSR)) { 2745 com_events += LOTS_OF_EVENTS; 2746 com->state |= CS_CHECKMSR; 2747 setsofttty(); 2748 } 2749 2750 /* handle CTS change immediately for crisp flow ctl */ 2751 if (com->state & CS_CTS_OFLOW) { 2752 if (modem_status & MSR_CTS) 2753 com->state |= CS_ODEVREADY; 2754 else 2755 com->state &= ~CS_ODEVREADY; 2756 } 2757 } 2758#ifdef PC98 2759 } 2760#endif 2761 2762 /* output queued and everything ready? */ 2763#ifndef PC98 2764 if (line_status & LSR_TXRDY 2765 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2766#else 2767 if (((com->pc98_if_type == COM_IF_RSA98III) 2768 ? (rsa_buf_status & 0x02) 2769 : (line_status & LSR_TXRDY)) 2770 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2771#endif 2772 ioptr = com->obufq.l_head; 2773 if (com->tx_fifo_size > 1) { 2774 u_int ocount; 2775 2776 ocount = com->obufq.l_tail - ioptr; 2777#ifdef PC98 2778 if (com->pc98_if_type == COM_IF_RSA98III) { 2779 rsa_buf_status = inb(com->rsabase + rsa_srr); 2780 rsa_tx_fifo_size = 1024; 2781 if (!(rsa_buf_status & 0x01)) 2782 rsa_tx_fifo_size = 2048; 2783 if (ocount > rsa_tx_fifo_size) 2784 ocount = rsa_tx_fifo_size; 2785 } else 2786#endif 2787 if (ocount > com->tx_fifo_size) 2788 ocount = com->tx_fifo_size; 2789 com->bytes_out += ocount; 2790 do 2791 outb(com->data_port, *ioptr++); 2792 while (--ocount != 0); 2793 } else { 2794 outb(com->data_port, *ioptr++); 2795 ++com->bytes_out; 2796 } 2797#ifdef PC98 2798 if (IS_8251(com->pc98_if_type)) 2799 if (!(pc98_check_i8251_interrupt(com) & IEN_TxFLAG)) 2800 com_int_Tx_enable(com); 2801#endif 2802 com->obufq.l_head = ioptr; 2803 if (COM_IIR_TXRDYBUG(com->flags)) { 2804 int_ctl_new = int_ctl | IER_ETXRDY; 2805 } 2806 if (ioptr >= com->obufq.l_tail) { 2807 struct lbq *qp; 2808 2809 qp = com->obufq.l_next; 2810 qp->l_queued = FALSE; 2811 qp = qp->l_next; 2812 if (qp != NULL) { 2813 com->obufq.l_head = qp->l_head; 2814 com->obufq.l_tail = qp->l_tail; 2815 com->obufq.l_next = qp; 2816 } else { 2817 /* output just completed */ 2818 if (COM_IIR_TXRDYBUG(com->flags)) { 2819 int_ctl_new = int_ctl & ~IER_ETXRDY; 2820 } 2821 com->state &= ~CS_BUSY; 2822#if defined(PC98) 2823 if (IS_8251(com->pc98_if_type)) 2824 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2825 com_int_Tx_disable(com); 2826#endif 2827 } 2828 if (!(com->state & CS_ODONE)) { 2829 com_events += LOTS_OF_EVENTS; 2830 com->state |= CS_ODONE; 2831 setsofttty(); /* handle at high level ASAP */ 2832 } 2833 } 2834 if (COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) { 2835#ifdef PC98 2836 if (com->pc98_if_type == COM_IF_RSA98III) { 2837 int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY); 2838 outb(com->intr_ctl_port, int_ctl_new); 2839 outb(com->rsabase + rsa_ier, 0x1d); 2840 } else 2841#endif 2842 outb(com->intr_ctl_port, int_ctl_new); 2843 } 2844 } 2845#ifdef PC98 2846 else if (line_status & LSR_TXRDY) { 2847 if (IS_8251(com->pc98_if_type)) 2848 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2849 com_int_Tx_disable(com); 2850 } 2851 if (IS_8251(com->pc98_if_type)) 2852 if ((tmp = inb(com->sts_port)) & STS8251_RxRDY) 2853 goto more_intr; 2854#endif 2855 2856 /* finished? */ 2857#ifndef COM_MULTIPORT 2858#ifdef PC98 2859 if (IS_8251(com->pc98_if_type)) 2860 return; 2861#endif 2862 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) 2863#endif /* COM_MULTIPORT */ 2864 return; 2865 } 2866} 2867 2868static int 2869sioioctl(dev, cmd, data, flag, p) 2870 dev_t dev; 2871 u_long cmd; 2872 caddr_t data; 2873 int flag; 2874 struct proc *p; 2875{ 2876 struct com_s *com; 2877 int error; 2878 Port_t iobase; 2879 int mynor; 2880 int s; 2881 struct tty *tp; 2882#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2883 u_long oldcmd; 2884 struct termios term; 2885#endif 2886 2887 mynor = minor(dev); 2888 com = com_addr(MINOR_TO_UNIT(mynor)); 2889 if (com->gone) 2890 return (ENODEV); 2891 iobase = com->iobase; 2892 if (mynor & CONTROL_MASK) { 2893 struct termios *ct; 2894 2895 switch (mynor & CONTROL_MASK) { 2896 case CONTROL_INIT_STATE: 2897 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 2898 break; 2899 case CONTROL_LOCK_STATE: 2900 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 2901 break; 2902 default: 2903 return (ENODEV); /* /dev/nodev */ 2904 } 2905 switch (cmd) { 2906 case TIOCSETA: 2907 error = suser(p); 2908 if (error != 0) 2909 return (error); 2910 *ct = *(struct termios *)data; 2911 return (0); 2912 case TIOCGETA: 2913 *(struct termios *)data = *ct; 2914 return (0); 2915 case TIOCGETD: 2916 *(int *)data = TTYDISC; 2917 return (0); 2918 case TIOCGWINSZ: 2919 bzero(data, sizeof(struct winsize)); 2920 return (0); 2921 default: 2922 return (ENOTTY); 2923 } 2924 } 2925 tp = com->tp; 2926#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2927 term = tp->t_termios; 2928 oldcmd = cmd; 2929 error = ttsetcompat(tp, &cmd, data, &term); 2930 if (error != 0) 2931 return (error); 2932 if (cmd != oldcmd) 2933 data = (caddr_t)&term; 2934#endif 2935 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 2936 int cc; 2937 struct termios *dt = (struct termios *)data; 2938 struct termios *lt = mynor & CALLOUT_MASK 2939 ? &com->lt_out : &com->lt_in; 2940 2941 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 2942 | (dt->c_iflag & ~lt->c_iflag); 2943 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 2944 | (dt->c_oflag & ~lt->c_oflag); 2945 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 2946 | (dt->c_cflag & ~lt->c_cflag); 2947 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 2948 | (dt->c_lflag & ~lt->c_lflag); 2949 for (cc = 0; cc < NCCS; ++cc) 2950 if (lt->c_cc[cc] != 0) 2951 dt->c_cc[cc] = tp->t_cc[cc]; 2952 if (lt->c_ispeed != 0) 2953 dt->c_ispeed = tp->t_ispeed; 2954 if (lt->c_ospeed != 0) 2955 dt->c_ospeed = tp->t_ospeed; 2956 } 2957 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 2958 if (error != ENOIOCTL) 2959 return (error); 2960 s = spltty(); 2961 error = ttioctl(tp, cmd, data, flag); 2962 disc_optim(tp, &tp->t_termios, com); 2963 if (error != ENOIOCTL) { 2964 splx(s); 2965 return (error); 2966 } 2967#ifdef PC98 2968 if (IS_8251(com->pc98_if_type)) { 2969 switch (cmd) { 2970 case TIOCSBRK: 2971 com_send_break_on( com ); 2972 break; 2973 case TIOCCBRK: 2974 com_send_break_off( com ); 2975 break; 2976 case TIOCSDTR: 2977 com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS ); 2978 break; 2979 case TIOCCDTR: 2980 com_tiocm_bic(com, TIOCM_DTR); 2981 break; 2982 /* 2983 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2984 * changes get undone on the next call to comparam(). 2985 */ 2986 case TIOCMSET: 2987 com_tiocm_set( com, *(int *)data ); 2988 break; 2989 case TIOCMBIS: 2990 com_tiocm_bis( com, *(int *)data ); 2991 break; 2992 case TIOCMBIC: 2993 com_tiocm_bic( com, *(int *)data ); 2994 break; 2995 case TIOCMGET: 2996 *(int *)data = com_tiocm_get(com); 2997 break; 2998 case TIOCMSDTRWAIT: 2999 /* must be root since the wait applies to following logins */ 3000 error = suser(p); 3001 if (error != 0) { 3002 splx(s); 3003 return (error); 3004 } 3005 com->dtr_wait = *(int *)data * hz / 100; 3006 break; 3007 case TIOCMGDTRWAIT: 3008 *(int *)data = com->dtr_wait * 100 / hz; 3009 break; 3010 case TIOCTIMESTAMP: 3011 com->do_timestamp = TRUE; 3012 *(struct timeval *)data = com->timestamp; 3013 break; 3014 case TIOCDCDTIMESTAMP: 3015 com->do_dcd_timestamp = TRUE; 3016 *(struct timeval *)data = com->dcd_timestamp; 3017 break; 3018 default: 3019 splx(s); 3020 return (ENOTTY); 3021 } 3022 } else { 3023 int port_shift; 3024 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 3025#endif 3026 switch (cmd) { 3027 case TIOCSBRK: 3028#ifdef PC98 3029 outb(iobase + (com_cfcr << port_shift), 3030 com->cfcr_image |= CFCR_SBREAK); 3031#else 3032 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 3033#endif 3034 break; 3035 case TIOCCBRK: 3036#ifdef PC98 3037 outb(iobase + (com_cfcr << port_shift), 3038 com->cfcr_image &= ~CFCR_SBREAK); 3039#else 3040 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 3041#endif 3042 break; 3043 case TIOCSDTR: 3044 (void)commctl(com, TIOCM_DTR, DMBIS); 3045 break; 3046 case TIOCCDTR: 3047 (void)commctl(com, TIOCM_DTR, DMBIC); 3048 break; 3049 /* 3050 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 3051 * changes get undone on the next call to comparam(). 3052 */ 3053 case TIOCMSET: 3054 (void)commctl(com, *(int *)data, DMSET); 3055 break; 3056 case TIOCMBIS: 3057 (void)commctl(com, *(int *)data, DMBIS); 3058 break; 3059 case TIOCMBIC: 3060 (void)commctl(com, *(int *)data, DMBIC); 3061 break; 3062 case TIOCMGET: 3063 *(int *)data = commctl(com, 0, DMGET); 3064 break; 3065 case TIOCMSDTRWAIT: 3066 /* must be root since the wait applies to following logins */ 3067 error = suser(p); 3068 if (error != 0) { 3069 splx(s); 3070 return (error); 3071 } 3072 com->dtr_wait = *(int *)data * hz / 100; 3073 break; 3074 case TIOCMGDTRWAIT: 3075 *(int *)data = com->dtr_wait * 100 / hz; 3076 break; 3077 case TIOCTIMESTAMP: 3078 com->do_timestamp = TRUE; 3079 *(struct timeval *)data = com->timestamp; 3080 break; 3081 case TIOCDCDTIMESTAMP: 3082 com->do_dcd_timestamp = TRUE; 3083 *(struct timeval *)data = com->dcd_timestamp; 3084 break; 3085 default: 3086 splx(s); 3087 error = pps_ioctl(cmd, data, &com->pps); 3088 if (error == ENODEV) 3089 error = ENOTTY; 3090 return (error); 3091 } 3092#ifdef PC98 3093 } 3094#endif 3095 splx(s); 3096 return (0); 3097} 3098 3099static void 3100siopoll() 3101{ 3102 int unit; 3103 3104 if (com_events == 0) 3105 return; 3106repeat: 3107 for (unit = 0; unit < sio_numunits; ++unit) { 3108 struct com_s *com; 3109 int incc; 3110 struct tty *tp; 3111 3112 com = com_addr(unit); 3113 if (com == NULL) 3114 continue; 3115 tp = com->tp; 3116 if (tp == NULL || com->gone) { 3117 /* 3118 * Discard any events related to never-opened or 3119 * going-away devices. 3120 */ 3121 disable_intr(); 3122 incc = com->iptr - com->ibuf; 3123 com->iptr = com->ibuf; 3124 if (com->state & CS_CHECKMSR) { 3125 incc += LOTS_OF_EVENTS; 3126 com->state &= ~CS_CHECKMSR; 3127 } 3128 com_events -= incc; 3129 enable_intr(); 3130 continue; 3131 } 3132 if (com->iptr != com->ibuf) { 3133 disable_intr(); 3134 sioinput(com); 3135 enable_intr(); 3136 } 3137 if (com->state & CS_CHECKMSR) { 3138 u_char delta_modem_status; 3139 3140#ifdef PC98 3141 if (!IS_8251(com->pc98_if_type)) { 3142#endif 3143 disable_intr(); 3144 delta_modem_status = com->last_modem_status 3145 ^ com->prev_modem_status; 3146 com->prev_modem_status = com->last_modem_status; 3147 com_events -= LOTS_OF_EVENTS; 3148 com->state &= ~CS_CHECKMSR; 3149 enable_intr(); 3150 if (delta_modem_status & MSR_DCD) 3151 (*linesw[tp->t_line].l_modem) 3152 (tp, com->prev_modem_status & MSR_DCD); 3153#ifdef PC98 3154 } 3155#endif 3156 } 3157 if (com->state & CS_ODONE) { 3158 disable_intr(); 3159 com_events -= LOTS_OF_EVENTS; 3160 com->state &= ~CS_ODONE; 3161 enable_intr(); 3162 if (!(com->state & CS_BUSY) 3163 && !(com->extra_state & CSE_BUSYCHECK)) { 3164 timeout(siobusycheck, com, hz / 100); 3165 com->extra_state |= CSE_BUSYCHECK; 3166 } 3167 (*linesw[tp->t_line].l_start)(tp); 3168 } 3169 if (com_events == 0) 3170 break; 3171 } 3172 if (com_events >= LOTS_OF_EVENTS) 3173 goto repeat; 3174} 3175 3176static int 3177comparam(tp, t) 3178 struct tty *tp; 3179 struct termios *t; 3180{ 3181 u_int cfcr; 3182 int cflag; 3183 struct com_s *com; 3184 int divisor; 3185 u_char dlbh; 3186 u_char dlbl; 3187 Port_t iobase; 3188 int s; 3189 int unit; 3190#ifdef PC98 3191 int port_shift = 0; 3192 u_char param = 0; 3193#endif 3194 3195#ifdef PC98 3196 cfcr = 0; 3197 unit = DEV_TO_UNIT(tp->t_dev); 3198 com = com_addr(unit); 3199 iobase = com->iobase; 3200 if (IS_8251(com->pc98_if_type)) { 3201 divisor = pc98_ttspeedtab(com, t->c_ospeed); 3202 } else { 3203 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 3204 3205 /* do historical conversions */ 3206 if (t->c_ispeed == 0) 3207 t->c_ispeed = t->c_ospeed; 3208 3209 /* check requested parameters */ 3210 divisor = ttspeedtab(t->c_ospeed, 3211 if_16550a_type[com->pc98_if_type & 0x0f].speedtab); 3212 } 3213#else 3214 /* do historical conversions */ 3215 if (t->c_ispeed == 0) 3216 t->c_ispeed = t->c_ospeed; 3217 3218 /* check requested parameters */ 3219 divisor = ttspeedtab(t->c_ospeed, comspeedtab); 3220#endif 3221 if (divisor < 0 || (divisor > 0 && t->c_ispeed != t->c_ospeed)) 3222 return (EINVAL); 3223 3224 /* parameters are OK, convert them to the com struct and the device */ 3225#ifndef PC98 3226 unit = DEV_TO_UNIT(tp->t_dev); 3227 com = com_addr(unit); 3228 iobase = com->iobase; 3229#endif 3230 s = spltty(); 3231#ifdef PC98 3232 if (IS_8251(com->pc98_if_type)) { 3233 if (divisor == 0) 3234 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 3235 else 3236 com_tiocm_bis( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 3237 } else { 3238#endif 3239 if (divisor == 0) 3240 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 3241 else 3242 (void)commctl(com, TIOCM_DTR, DMBIS); 3243#ifdef PC98 3244 } 3245#endif 3246 cflag = t->c_cflag; 3247#ifdef PC98 3248 if (!IS_8251(com->pc98_if_type)) { 3249#endif 3250 switch (cflag & CSIZE) { 3251 case CS5: 3252 cfcr = CFCR_5BITS; 3253 break; 3254 case CS6: 3255 cfcr = CFCR_6BITS; 3256 break; 3257 case CS7: 3258 cfcr = CFCR_7BITS; 3259 break; 3260 default: 3261 cfcr = CFCR_8BITS; 3262 break; 3263 } 3264 if (cflag & PARENB) { 3265 cfcr |= CFCR_PENAB; 3266 if (!(cflag & PARODD)) 3267 cfcr |= CFCR_PEVEN; 3268 } 3269 if (cflag & CSTOPB) 3270 cfcr |= CFCR_STOPB; 3271 3272 if (com->hasfifo && divisor != 0) { 3273 /* 3274 * Use a fifo trigger level low enough so that the input 3275 * latency from the fifo is less than about 16 msec and 3276 * the total latency is less than about 30 msec. These 3277 * latencies are reasonable for humans. Serial comms 3278 * protocols shouldn't expect anything better since modem 3279 * latencies are larger. 3280 */ 3281 com->fifo_image = t->c_ospeed <= 4800 3282 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; 3283#ifdef COM_ESP 3284 /* 3285 * The Hayes ESP card needs the fifo DMA mode bit set 3286 * in compatibility mode. If not, it will interrupt 3287 * for each character received. 3288 */ 3289 if (com->esp) 3290 com->fifo_image |= FIFO_DMA_MODE; 3291#endif 3292#ifdef PC98 3293 outb(iobase + (com_fifo << port_shift), com->fifo_image); 3294#else 3295 outb(iobase + com_fifo, com->fifo_image); 3296#endif 3297 } 3298#ifdef PC98 3299 } 3300#endif 3301 3302 /* 3303 * This returns with interrupts disabled so that we can complete 3304 * the speed change atomically. Keeping interrupts disabled is 3305 * especially important while com_data is hidden. 3306 */ 3307 (void) siosetwater(com, t->c_ispeed); 3308 3309#ifdef PC98 3310 if (IS_8251(com->pc98_if_type)) 3311 com_cflag_and_speed_set(com, cflag, t->c_ospeed); 3312 else { 3313#endif 3314 if (divisor != 0) { 3315#ifdef PC98 3316 outb(iobase + (com_cfcr << port_shift), cfcr | CFCR_DLAB); 3317#else 3318 outb(iobase + com_cfcr, cfcr | CFCR_DLAB); 3319#endif 3320 /* 3321 * Only set the divisor registers if they would change, 3322 * since on some 16550 incompatibles (UMC8669F), setting 3323 * them while input is arriving them loses sync until 3324 * data stops arriving. 3325 */ 3326 dlbl = divisor & 0xFF; 3327#ifdef PC98 3328 if (inb(iobase + (com_dlbl << port_shift)) != dlbl) 3329 outb(iobase + (com_dlbl << port_shift), dlbl); 3330 dlbh = (u_int) divisor >> 8; 3331 if (inb(iobase + (com_dlbh << port_shift)) != dlbh) 3332 outb(iobase + (com_dlbh << port_shift), dlbh); 3333#else 3334 if (inb(iobase + com_dlbl) != dlbl) 3335 outb(iobase + com_dlbl, dlbl); 3336 dlbh = (u_int) divisor >> 8; 3337 if (inb(iobase + com_dlbh) != dlbh) 3338 outb(iobase + com_dlbh, dlbh); 3339#endif 3340 } 3341 3342 3343#ifdef PC98 3344 } 3345 outb(iobase + (com_cfcr << port_shift), com->cfcr_image = cfcr); 3346#else 3347 outb(iobase + com_cfcr, com->cfcr_image = cfcr); 3348#endif 3349 3350 if (!(tp->t_state & TS_TTSTOP)) 3351 com->state |= CS_TTGO; 3352 3353 if (cflag & CRTS_IFLOW) { 3354 if (com->st16650a) { 3355 outb(iobase + com_cfcr, 0xbf); 3356 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40); 3357 } 3358 com->state |= CS_RTS_IFLOW; 3359 /* 3360 * If CS_RTS_IFLOW just changed from off to on, the change 3361 * needs to be propagated to MCR_RTS. This isn't urgent, 3362 * so do it later by calling comstart() instead of repeating 3363 * a lot of code from comstart() here. 3364 */ 3365 } else if (com->state & CS_RTS_IFLOW) { 3366 com->state &= ~CS_RTS_IFLOW; 3367 /* 3368 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 3369 * on here, since comstart() won't do it later. 3370 */ 3371#ifdef PC98 3372 if (IS_8251(com->pc98_if_type)) 3373 com_tiocm_bis(com, TIOCM_RTS); 3374 else 3375#endif 3376 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 3377 if (com->st16650a) { 3378 outb(iobase + com_cfcr, 0xbf); 3379 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40); 3380 } 3381 } 3382 3383 3384 /* 3385 * Set up state to handle output flow control. 3386 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 3387 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 3388 */ 3389 com->state |= CS_ODEVREADY; 3390 com->state &= ~CS_CTS_OFLOW; 3391#ifdef PC98 3392 if (com->pc98_if_type == COM_IF_RSA98III) { 3393 param = inb(com->rsabase + rsa_msr); 3394 outb(com->rsabase + rsa_msr, param & 0x14); 3395 } 3396#endif 3397 if (cflag & CCTS_OFLOW) { 3398 com->state |= CS_CTS_OFLOW; 3399#ifdef PC98 3400 if (IS_8251(com->pc98_if_type)) { 3401 if (!(pc98_get_modem_status(com) & TIOCM_CTS)) 3402 com->state &= ~CS_ODEVREADY; 3403 } else { 3404#endif 3405#ifdef PC98 3406 if (com->pc98_if_type == COM_IF_RSA98III) { 3407 /* Set automatic flow control mode */ 3408 outb(com->rsabase + rsa_msr, param | 0x08); 3409 } else 3410#endif 3411 if (!(com->last_modem_status & MSR_CTS)) 3412 com->state &= ~CS_ODEVREADY; 3413 if (com->st16650a) { 3414 outb(iobase + com_cfcr, 0xbf); 3415 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80); 3416 } 3417#ifdef PC98 3418 } 3419#endif 3420 } else { 3421 if (com->st16650a) { 3422 outb(iobase + com_cfcr, 0xbf); 3423 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80); 3424 } 3425 } 3426 3427 3428#ifdef PC98 3429 outb(iobase + (com_cfcr << port_shift), com->cfcr_image); 3430#else 3431 outb(iobase + com_cfcr, com->cfcr_image); 3432#endif 3433 3434 3435 /* XXX shouldn't call functions while intrs are disabled. */ 3436 disc_optim(tp, t, com); 3437 /* 3438 * Recover from fiddling with CS_TTGO. We used to call siointr1() 3439 * unconditionally, but that defeated the careful discarding of 3440 * stale input in sioopen(). 3441 */ 3442 if (com->state >= (CS_BUSY | CS_TTGO)) 3443 siointr1(com); 3444 3445 enable_intr(); 3446 splx(s); 3447 comstart(tp); 3448 if (com->ibufold != NULL) { 3449 free(com->ibufold, M_DEVBUF); 3450 com->ibufold = NULL; 3451 } 3452 return (0); 3453} 3454 3455static int 3456siosetwater(com, speed) 3457 struct com_s *com; 3458 speed_t speed; 3459{ 3460 int cp4ticks; 3461 u_char *ibuf; 3462 int ibufsize; 3463 struct tty *tp; 3464 3465 /* 3466 * Make the buffer size large enough to handle a softtty interrupt 3467 * latency of about 2 ticks without loss of throughput or data 3468 * (about 3 ticks if input flow control is not used or not honoured, 3469 * but a bit less for CS5-CS7 modes). 3470 */ 3471 cp4ticks = speed / 10 / hz * 4; 3472 for (ibufsize = 128; ibufsize < cp4ticks;) 3473 ibufsize <<= 1; 3474#ifdef PC98 3475 if (com->pc98_if_type == COM_IF_RSA98III) 3476 ibufsize = 2048; 3477#endif 3478 if (ibufsize == com->ibufsize) { 3479 disable_intr(); 3480 return (0); 3481 } 3482 3483 /* 3484 * Allocate input buffer. The extra factor of 2 in the size is 3485 * to allow for an error byte for each input byte. 3486 */ 3487 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 3488 if (ibuf == NULL) { 3489 disable_intr(); 3490 return (ENOMEM); 3491 } 3492 3493 /* Initialize non-critical variables. */ 3494 com->ibufold = com->ibuf; 3495 com->ibufsize = ibufsize; 3496 tp = com->tp; 3497 if (tp != NULL) { 3498 tp->t_ififosize = 2 * ibufsize; 3499 tp->t_ispeedwat = (speed_t)-1; 3500 tp->t_ospeedwat = (speed_t)-1; 3501 } 3502 3503 /* 3504 * Read current input buffer, if any. Continue with interrupts 3505 * disabled. 3506 */ 3507 disable_intr(); 3508 if (com->iptr != com->ibuf) 3509 sioinput(com); 3510 3511 /*- 3512 * Initialize critical variables, including input buffer watermarks. 3513 * The external device is asked to stop sending when the buffer 3514 * exactly reaches high water, or when the high level requests it. 3515 * The high level is notified immediately (rather than at a later 3516 * clock tick) when this watermark is reached. 3517 * The buffer size is chosen so the watermark should almost never 3518 * be reached. 3519 * The low watermark is invisibly 0 since the buffer is always 3520 * emptied all at once. 3521 */ 3522 com->iptr = com->ibuf = ibuf; 3523 com->ibufend = ibuf + ibufsize; 3524 com->ierroff = ibufsize; 3525 com->ihighwater = ibuf + 3 * ibufsize / 4; 3526 return (0); 3527} 3528 3529static void 3530comstart(tp) 3531 struct tty *tp; 3532{ 3533 struct com_s *com; 3534 int s; 3535 int unit; 3536#ifdef PC98 3537 int tmp; 3538#endif 3539 3540 unit = DEV_TO_UNIT(tp->t_dev); 3541 com = com_addr(unit); 3542 s = spltty(); 3543 disable_intr(); 3544 if (tp->t_state & TS_TTSTOP) 3545 com->state &= ~CS_TTGO; 3546 else 3547 com->state |= CS_TTGO; 3548 if (tp->t_state & TS_TBLOCK) { 3549#ifdef PC98 3550 if (IS_8251(com->pc98_if_type)) 3551 tmp = com_tiocm_get(com) & TIOCM_RTS; 3552 else 3553 tmp = com->mcr_image & MCR_RTS; 3554 if (tmp && (com->state & CS_RTS_IFLOW)) 3555#else 3556 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 3557#endif 3558#ifdef PC98 3559 if (IS_8251(com->pc98_if_type)) 3560 com_tiocm_bic(com, TIOCM_RTS); 3561 else 3562#endif 3563 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 3564 } else { 3565#ifdef PC98 3566 if (IS_8251(com->pc98_if_type)) 3567 tmp = com_tiocm_get(com) & TIOCM_RTS; 3568 else 3569 tmp = com->mcr_image & MCR_RTS; 3570 if (!(tmp) && com->iptr < com->ihighwater 3571 && com->state & CS_RTS_IFLOW) 3572#else 3573 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater 3574 && com->state & CS_RTS_IFLOW) 3575#endif 3576#ifdef PC98 3577 if (IS_8251(com->pc98_if_type)) 3578 com_tiocm_bis(com, TIOCM_RTS); 3579 else 3580#endif 3581 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 3582 } 3583 enable_intr(); 3584 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 3585 ttwwakeup(tp); 3586#ifdef PC98 3587/* if(IS_8251(com->pc98_if_type)) 3588 com_int_Tx_enable(com); */ 3589#endif 3590 splx(s); 3591 return; 3592 } 3593 if (tp->t_outq.c_cc != 0) { 3594 struct lbq *qp; 3595 struct lbq *next; 3596 3597 if (!com->obufs[0].l_queued) { 3598 com->obufs[0].l_tail 3599 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 3600#ifndef PC98 3601 sizeof com->obuf1); 3602#else 3603 com->obufsize); 3604#endif 3605 com->obufs[0].l_next = NULL; 3606 com->obufs[0].l_queued = TRUE; 3607 disable_intr(); 3608 if (com->state & CS_BUSY) { 3609 qp = com->obufq.l_next; 3610 while ((next = qp->l_next) != NULL) 3611 qp = next; 3612 qp->l_next = &com->obufs[0]; 3613 } else { 3614 com->obufq.l_head = com->obufs[0].l_head; 3615 com->obufq.l_tail = com->obufs[0].l_tail; 3616 com->obufq.l_next = &com->obufs[0]; 3617 com->state |= CS_BUSY; 3618 } 3619 enable_intr(); 3620 } 3621 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 3622 com->obufs[1].l_tail 3623 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 3624#ifndef PC98 3625 sizeof com->obuf2); 3626#else 3627 com->obufsize); 3628#endif 3629 com->obufs[1].l_next = NULL; 3630 com->obufs[1].l_queued = TRUE; 3631 disable_intr(); 3632 if (com->state & CS_BUSY) { 3633 qp = com->obufq.l_next; 3634 while ((next = qp->l_next) != NULL) 3635 qp = next; 3636 qp->l_next = &com->obufs[1]; 3637 } else { 3638 com->obufq.l_head = com->obufs[1].l_head; 3639 com->obufq.l_tail = com->obufs[1].l_tail; 3640 com->obufq.l_next = &com->obufs[1]; 3641 com->state |= CS_BUSY; 3642 } 3643 enable_intr(); 3644 } 3645 tp->t_state |= TS_BUSY; 3646 } 3647 disable_intr(); 3648 if (com->state >= (CS_BUSY | CS_TTGO)) 3649 siointr1(com); /* fake interrupt to start output */ 3650 enable_intr(); 3651#ifdef PC98 3652/* if(IS_8251(com->pc98_if_type)) 3653 com_int_Tx_enable(com); */ 3654#endif 3655 ttwwakeup(tp); 3656 splx(s); 3657} 3658 3659static void 3660comstop(tp, rw) 3661 struct tty *tp; 3662 int rw; 3663{ 3664 struct com_s *com; 3665#ifdef PC98 3666 int port_shift = 0; 3667 int rsa98_tmp = 0; 3668#endif 3669 3670 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 3671 if (com->gone) 3672 return; 3673#ifdef PC98 3674 if (!IS_8251(com->pc98_if_type)) 3675 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 3676#endif 3677 disable_intr(); 3678 if (rw & FWRITE) { 3679 if (com->hasfifo) 3680#ifdef COM_ESP 3681 /* XXX avoid h/w bug. */ 3682 if (!com->esp) 3683#endif 3684#ifdef PC98 3685 outb(com->iobase + (com_fifo << port_shift), 3686 FIFO_XMT_RST | com->fifo_image); 3687 if (com->pc98_if_type == COM_IF_RSA98III) 3688 for(rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++) 3689 outb(com->iobase + (com_fifo << port_shift), 3690 FIFO_XMT_RST | com->fifo_image); 3691#else 3692 outb(com->iobase + com_fifo, 3693 FIFO_XMT_RST | com->fifo_image); 3694#endif 3695 com->obufs[0].l_queued = FALSE; 3696 com->obufs[1].l_queued = FALSE; 3697 if (com->state & CS_ODONE) 3698 com_events -= LOTS_OF_EVENTS; 3699 com->state &= ~(CS_ODONE | CS_BUSY); 3700 com->tp->t_state &= ~TS_BUSY; 3701 } 3702 if (rw & FREAD) { 3703 if (com->hasfifo) 3704#ifdef COM_ESP 3705 /* XXX avoid h/w bug. */ 3706 if (!com->esp) 3707#endif 3708#ifdef PC98 3709 if (com->pc98_if_type == COM_IF_RSA98III) { 3710 for(rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++) 3711 inb(com->data_port); 3712 } 3713 outb(com->iobase + (com_fifo << port_shift), 3714 FIFO_RCV_RST | com->fifo_image); 3715#else 3716 outb(com->iobase + com_fifo, 3717 FIFO_RCV_RST | com->fifo_image); 3718#endif 3719 com_events -= (com->iptr - com->ibuf); 3720 com->iptr = com->ibuf; 3721 } 3722 enable_intr(); 3723 comstart(tp); 3724} 3725 3726static int 3727commctl(com, bits, how) 3728 struct com_s *com; 3729 int bits; 3730 int how; 3731{ 3732 int mcr; 3733 int msr; 3734 3735 if (how == DMGET) { 3736 bits = TIOCM_LE; /* XXX - always enabled while open */ 3737 mcr = com->mcr_image; 3738 if (mcr & MCR_DTR) 3739 bits |= TIOCM_DTR; 3740 if (mcr & MCR_RTS) 3741 bits |= TIOCM_RTS; 3742 msr = com->prev_modem_status; 3743 if (msr & MSR_CTS) 3744 bits |= TIOCM_CTS; 3745 if (msr & MSR_DCD) 3746 bits |= TIOCM_CD; 3747 if (msr & MSR_DSR) 3748 bits |= TIOCM_DSR; 3749 /* 3750 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI 3751 * more volatile by reading the modem status a lot. Perhaps 3752 * we should latch both bits until the status is read here. 3753 */ 3754 if (msr & (MSR_RI | MSR_TERI)) 3755 bits |= TIOCM_RI; 3756 return (bits); 3757 } 3758 mcr = 0; 3759 if (bits & TIOCM_DTR) 3760 mcr |= MCR_DTR; 3761 if (bits & TIOCM_RTS) 3762 mcr |= MCR_RTS; 3763 if (com->gone) 3764 return(0); 3765 disable_intr(); 3766 switch (how) { 3767 case DMSET: 3768 outb(com->modem_ctl_port, 3769 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); 3770 break; 3771 case DMBIS: 3772 outb(com->modem_ctl_port, com->mcr_image |= mcr); 3773 break; 3774 case DMBIC: 3775 outb(com->modem_ctl_port, com->mcr_image &= ~mcr); 3776 break; 3777 } 3778 enable_intr(); 3779 return (0); 3780} 3781 3782static void 3783siosettimeout() 3784{ 3785 struct com_s *com; 3786 bool_t someopen; 3787 int unit; 3788 3789 /* 3790 * Set our timeout period to 1 second if no polled devices are open. 3791 * Otherwise set it to max(1/200, 1/hz). 3792 * Enable timeouts iff some device is open. 3793 */ 3794 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3795 sio_timeout = hz; 3796 someopen = FALSE; 3797 for (unit = 0; unit < sio_numunits; ++unit) { 3798 com = com_addr(unit); 3799 if (com != NULL && com->tp != NULL 3800 && com->tp->t_state & TS_ISOPEN && !com->gone) { 3801 someopen = TRUE; 3802 if (com->poll || com->poll_output) { 3803 sio_timeout = hz > 200 ? hz / 200 : 1; 3804 break; 3805 } 3806 } 3807 } 3808 if (someopen) { 3809 sio_timeouts_until_log = hz / sio_timeout; 3810 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 3811 sio_timeout); 3812 } else { 3813 /* Flush error messages, if any. */ 3814 sio_timeouts_until_log = 1; 3815 comwakeup((void *)NULL); 3816 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3817 } 3818} 3819 3820static void 3821comwakeup(chan) 3822 void *chan; 3823{ 3824 struct com_s *com; 3825 int unit; 3826 3827 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 3828 3829 /* 3830 * Recover from lost output interrupts. 3831 * Poll any lines that don't use interrupts. 3832 */ 3833 for (unit = 0; unit < sio_numunits; ++unit) { 3834 com = com_addr(unit); 3835 if (com != NULL && !com->gone 3836 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 3837 disable_intr(); 3838 siointr1(com); 3839 enable_intr(); 3840 } 3841 } 3842 3843 /* 3844 * Check for and log errors, but not too often. 3845 */ 3846 if (--sio_timeouts_until_log > 0) 3847 return; 3848 sio_timeouts_until_log = hz / sio_timeout; 3849 for (unit = 0; unit < sio_numunits; ++unit) { 3850 int errnum; 3851 3852 com = com_addr(unit); 3853 if (com == NULL) 3854 continue; 3855 if (com->gone) 3856 continue; 3857 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 3858 u_int delta; 3859 u_long total; 3860 3861 disable_intr(); 3862 delta = com->delta_error_counts[errnum]; 3863 com->delta_error_counts[errnum] = 0; 3864 enable_intr(); 3865 if (delta == 0) 3866 continue; 3867 total = com->error_counts[errnum] += delta; 3868 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", 3869 unit, delta, error_desc[errnum], 3870 delta == 1 ? "" : "s", total); 3871 } 3872 } 3873} 3874 3875#ifdef PC98 3876/* commint is called when modem control line changes */ 3877static void 3878commint(dev_t dev) 3879{ 3880 register struct tty *tp; 3881 int stat,delta; 3882 struct com_s *com; 3883 int mynor,unit; 3884 3885 mynor = minor(dev); 3886 unit = MINOR_TO_UNIT(mynor); 3887 com = com_addr(unit); 3888 tp = com->tp; 3889 3890 stat = com_tiocm_get(com); 3891 delta = com_tiocm_get_delta(com); 3892 3893 if (com->state & CS_CTS_OFLOW) { 3894 if (stat & TIOCM_CTS) 3895 com->state |= CS_ODEVREADY; 3896 else 3897 com->state &= ~CS_ODEVREADY; 3898 } 3899 if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) { 3900 if (stat & TIOCM_CAR ) 3901 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 3902 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 3903 /* negate DTR, RTS */ 3904 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ? 3905 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE ); 3906 /* disable IENABLE */ 3907 com_int_TxRx_disable( com ); 3908 } 3909 } 3910} 3911#endif 3912 3913static void 3914disc_optim(tp, t, com) 3915 struct tty *tp; 3916 struct termios *t; 3917 struct com_s *com; 3918{ 3919 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 3920 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 3921 && (!(t->c_iflag & PARMRK) 3922 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 3923 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 3924 && linesw[tp->t_line].l_rint == ttyinput) 3925 tp->t_state |= TS_CAN_BYPASS_L_RINT; 3926 else 3927 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 3928 com->hotchar = linesw[tp->t_line].l_hotchar; 3929} 3930 3931/* 3932 * Following are all routines needed for SIO to act as console 3933 */ 3934#include <sys/cons.h> 3935 3936struct siocnstate { 3937 u_char dlbl; 3938 u_char dlbh; 3939 u_char ier; 3940 u_char cfcr; 3941 u_char mcr; 3942}; 3943 3944static speed_t siocngetspeed __P((Port_t, struct speedtab *)); 3945static void siocnclose __P((struct siocnstate *sp, Port_t iobase)); 3946static void siocnopen __P((struct siocnstate *sp, Port_t iobase, int speed)); 3947static void siocntxwait __P((Port_t iobase)); 3948 3949static cn_probe_t siocnprobe; 3950static cn_init_t siocninit; 3951static cn_checkc_t siocncheckc; 3952static cn_getc_t siocngetc; 3953static cn_putc_t siocnputc; 3954 3955#ifdef __i386__ 3956CONS_DRIVER(sio, siocnprobe, siocninit, NULL, siocngetc, siocncheckc, siocnputc); 3957 3958#endif 3959 3960/* To get the GDB related variables */ 3961#if DDB > 0 3962#include <ddb/ddb.h> 3963#endif 3964 3965static void 3966siocntxwait(iobase) 3967 Port_t iobase; 3968{ 3969 int timo; 3970 3971 /* 3972 * Wait for any pending transmission to finish. Required to avoid 3973 * the UART lockup bug when the speed is changed, and for normal 3974 * transmits. 3975 */ 3976 timo = 100000; 3977 while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) 3978 != (LSR_TSRE | LSR_TXRDY) && --timo != 0) 3979 ; 3980} 3981 3982/* 3983 * Read the serial port specified and try to figure out what speed 3984 * it's currently running at. We're assuming the serial port has 3985 * been initialized and is basicly idle. This routine is only intended 3986 * to be run at system startup. 3987 * 3988 * If the value read from the serial port doesn't make sense, return 0. 3989 */ 3990 3991static speed_t 3992siocngetspeed(iobase, table) 3993 Port_t iobase; 3994 struct speedtab *table; 3995{ 3996 int code; 3997 u_char dlbh; 3998 u_char dlbl; 3999 u_char cfcr; 4000 4001 cfcr = inb(iobase + com_cfcr); 4002 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 4003 4004 dlbl = inb(iobase + com_dlbl); 4005 dlbh = inb(iobase + com_dlbh); 4006 4007 outb(iobase + com_cfcr, cfcr); 4008 4009 code = dlbh << 8 | dlbl; 4010 4011 for (; table->sp_speed != -1; table++) 4012 if (table->sp_code == code) 4013 return (table->sp_speed); 4014 4015 return 0; /* didn't match anything sane */ 4016} 4017 4018static void 4019siocnopen(sp, iobase, speed) 4020 struct siocnstate *sp; 4021 Port_t iobase; 4022 int speed; 4023{ 4024 int divisor; 4025 u_char dlbh; 4026 u_char dlbl; 4027 4028 /* 4029 * Save all the device control registers except the fifo register 4030 * and set our default ones (cs8 -parenb speed=comdefaultrate). 4031 * We can't save the fifo register since it is read-only. 4032 */ 4033 sp->ier = inb(iobase + com_ier); 4034 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ 4035 siocntxwait(iobase); 4036 sp->cfcr = inb(iobase + com_cfcr); 4037 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 4038 sp->dlbl = inb(iobase + com_dlbl); 4039 sp->dlbh = inb(iobase + com_dlbh); 4040 /* 4041 * Only set the divisor registers if they would change, since on 4042 * some 16550 incompatibles (Startech), setting them clears the 4043 * data input register. This also reduces the effects of the 4044 * UMC8669F bug. 4045 */ 4046 divisor = ttspeedtab(speed, comspeedtab); 4047 dlbl = divisor & 0xFF; 4048 if (sp->dlbl != dlbl) 4049 outb(iobase + com_dlbl, dlbl); 4050 dlbh = (u_int) divisor >> 8; 4051 if (sp->dlbh != dlbh) 4052 outb(iobase + com_dlbh, dlbh); 4053 outb(iobase + com_cfcr, CFCR_8BITS); 4054 sp->mcr = inb(iobase + com_mcr); 4055 /* 4056 * We don't want interrupts, but must be careful not to "disable" 4057 * them by clearing the MCR_IENABLE bit, since that might cause 4058 * an interrupt by floating the IRQ line. 4059 */ 4060 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); 4061} 4062 4063static void 4064siocnclose(sp, iobase) 4065 struct siocnstate *sp; 4066 Port_t iobase; 4067{ 4068 /* 4069 * Restore the device control registers. 4070 */ 4071 siocntxwait(iobase); 4072 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 4073 if (sp->dlbl != inb(iobase + com_dlbl)) 4074 outb(iobase + com_dlbl, sp->dlbl); 4075 if (sp->dlbh != inb(iobase + com_dlbh)) 4076 outb(iobase + com_dlbh, sp->dlbh); 4077 outb(iobase + com_cfcr, sp->cfcr); 4078 /* 4079 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. 4080 */ 4081 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); 4082 outb(iobase + com_ier, sp->ier); 4083} 4084 4085static void 4086siocnprobe(cp) 4087 struct consdev *cp; 4088{ 4089 speed_t boot_speed; 4090 u_char cfcr; 4091 int s, unit; 4092 struct siocnstate sp; 4093 4094 /* 4095 * Find our first enabled console, if any. If it is a high-level 4096 * console device, then initialize it and return successfully. 4097 * If it is a low-level console device, then initialize it and 4098 * return unsuccessfully. It must be initialized in both cases 4099 * for early use by console drivers and debuggers. Initializing 4100 * the hardware is not necessary in all cases, since the i/o 4101 * routines initialize it on the fly, but it is necessary if 4102 * input might arrive while the hardware is switched back to an 4103 * uninitialized state. We can't handle multiple console devices 4104 * yet because our low-level routines don't take a device arg. 4105 * We trust the user to set the console flags properly so that we 4106 * don't need to probe. 4107 */ 4108 cp->cn_pri = CN_DEAD; 4109 4110 for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */ 4111 int flags; 4112 int disabled; 4113 if (resource_int_value("sio", unit, "disabled", &disabled) == 0) { 4114 if (disabled) 4115 continue; 4116 } 4117 if (resource_int_value("sio", unit, "flags", &flags)) 4118 continue; 4119 if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) { 4120 int port; 4121 Port_t iobase; 4122 4123 if (resource_int_value("sio", unit, "port", &port)) 4124 continue; 4125 iobase = port; 4126 s = spltty(); 4127 if (boothowto & RB_SERIAL) { 4128 boot_speed = siocngetspeed(iobase, comspeedtab); 4129 if (boot_speed) 4130 comdefaultrate = boot_speed; 4131 } 4132 4133 /* 4134 * Initialize the divisor latch. We can't rely on 4135 * siocnopen() to do this the first time, since it 4136 * avoids writing to the latch if the latch appears 4137 * to have the correct value. Also, if we didn't 4138 * just read the speed from the hardware, then we 4139 * need to set the speed in hardware so that 4140 * switching it later is null. 4141 */ 4142 cfcr = inb(iobase + com_cfcr); 4143 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 4144 outb(iobase + com_dlbl, 4145 COMBRD(comdefaultrate) & 0xff); 4146 outb(iobase + com_dlbh, 4147 (u_int) COMBRD(comdefaultrate) >> 8); 4148 outb(iobase + com_cfcr, cfcr); 4149 4150 siocnopen(&sp, iobase, comdefaultrate); 4151 4152 splx(s); 4153 if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) { 4154 cp->cn_dev = makedev(CDEV_MAJOR, unit); 4155 cp->cn_pri = COM_FORCECONSOLE(flags) 4156 || boothowto & RB_SERIAL 4157 ? CN_REMOTE : CN_NORMAL; 4158 siocniobase = iobase; 4159 siocnunit = unit; 4160 } 4161 if (COM_DEBUGGER(flags)) { 4162 printf("sio%d: gdb debugging port\n", unit); 4163 siogdbiobase = iobase; 4164 siogdbunit = unit; 4165#if DDB > 0 4166 gdbdev = makedev(CDEV_MAJOR, unit); 4167 gdb_getc = siocngetc; 4168 gdb_putc = siocnputc; 4169#endif 4170 } 4171 } 4172 } 4173#ifdef __i386__ 4174#if DDB > 0 4175 /* 4176 * XXX Ugly Compatability. 4177 * If no gdb port has been specified, set it to be the console 4178 * as some configuration files don't specify the gdb port. 4179 */ 4180 if (gdbdev == NODEV && (boothowto & RB_GDB)) { 4181 printf("Warning: no GDB port specified. Defaulting to sio%d.\n", 4182 siocnunit); 4183 printf("Set flag 0x80 on desired GDB port in your\n"); 4184 printf("configuration file (currently sio only).\n"); 4185 siogdbiobase = siocniobase; 4186 siogdbunit = siocnunit; 4187 gdbdev = makedev(CDEV_MAJOR, siocnunit); 4188 gdb_getc = siocngetc; 4189 gdb_putc = siocnputc; 4190 } 4191#endif 4192#endif 4193} 4194 4195#ifdef __alpha__ 4196 4197CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc); 4198 4199int 4200siocnattach(port, speed) 4201 int port; 4202 int speed; 4203{ 4204 int s; 4205 u_char cfcr; 4206 struct siocnstate sp; 4207 4208 siocniobase = port; 4209 comdefaultrate = speed; 4210 sio_consdev.cn_pri = CN_NORMAL; 4211 sio_consdev.cn_dev = makedev(CDEV_MAJOR, 0); 4212 4213 s = spltty(); 4214 4215 /* 4216 * Initialize the divisor latch. We can't rely on 4217 * siocnopen() to do this the first time, since it 4218 * avoids writing to the latch if the latch appears 4219 * to have the correct value. Also, if we didn't 4220 * just read the speed from the hardware, then we 4221 * need to set the speed in hardware so that 4222 * switching it later is null. 4223 */ 4224 cfcr = inb(siocniobase + com_cfcr); 4225 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr); 4226 outb(siocniobase + com_dlbl, 4227 COMBRD(comdefaultrate) & 0xff); 4228 outb(siocniobase + com_dlbh, 4229 (u_int) COMBRD(comdefaultrate) >> 8); 4230 outb(siocniobase + com_cfcr, cfcr); 4231 4232 siocnopen(&sp, siocniobase, comdefaultrate); 4233 splx(s); 4234 4235 cn_tab = &sio_consdev; 4236 return 0; 4237} 4238 4239int 4240siogdbattach(port, speed) 4241 int port; 4242 int speed; 4243{ 4244 int s; 4245 u_char cfcr; 4246 struct siocnstate sp; 4247 4248 siogdbiobase = port; 4249 gdbdefaultrate = speed; 4250 4251 s = spltty(); 4252 4253 /* 4254 * Initialize the divisor latch. We can't rely on 4255 * siocnopen() to do this the first time, since it 4256 * avoids writing to the latch if the latch appears 4257 * to have the correct value. Also, if we didn't 4258 * just read the speed from the hardware, then we 4259 * need to set the speed in hardware so that 4260 * switching it later is null. 4261 */ 4262 cfcr = inb(siogdbiobase + com_cfcr); 4263 outb(siogdbiobase + com_cfcr, CFCR_DLAB | cfcr); 4264 outb(siogdbiobase + com_dlbl, 4265 COMBRD(gdbdefaultrate) & 0xff); 4266 outb(siogdbiobase + com_dlbh, 4267 (u_int) COMBRD(gdbdefaultrate) >> 8); 4268 outb(siogdbiobase + com_cfcr, cfcr); 4269 4270 siocnopen(&sp, siogdbiobase, gdbdefaultrate); 4271 splx(s); 4272 4273 return 0; 4274} 4275 4276#endif 4277 4278static void 4279siocninit(cp) 4280 struct consdev *cp; 4281{ 4282 comconsole = DEV_TO_UNIT(cp->cn_dev); 4283} 4284 4285static int 4286siocncheckc(dev) 4287 dev_t dev; 4288{ 4289 int c; 4290 Port_t iobase; 4291 int s; 4292 struct siocnstate sp; 4293 4294 if (minor(dev) == siogdbunit) 4295 iobase = siogdbiobase; 4296 else 4297 iobase = siocniobase; 4298 s = spltty(); 4299 siocnopen(&sp, iobase, comdefaultrate); 4300 if (inb(iobase + com_lsr) & LSR_RXRDY) 4301 c = inb(iobase + com_data); 4302 else 4303 c = -1; 4304 siocnclose(&sp, iobase); 4305 splx(s); 4306 return (c); 4307} 4308 4309 4310int 4311siocngetc(dev) 4312 dev_t dev; 4313{ 4314 int c; 4315 Port_t iobase; 4316 int s; 4317 struct siocnstate sp; 4318 4319 if (minor(dev) == siogdbunit) 4320 iobase = siogdbiobase; 4321 else 4322 iobase = siocniobase; 4323 s = spltty(); 4324 siocnopen(&sp, iobase, comdefaultrate); 4325 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 4326 ; 4327 c = inb(iobase + com_data); 4328 siocnclose(&sp, iobase); 4329 splx(s); 4330 return (c); 4331} 4332 4333void 4334siocnputc(dev, c) 4335 dev_t dev; 4336 int c; 4337{ 4338 int s; 4339 struct siocnstate sp; 4340 Port_t iobase; 4341 4342 if (minor(dev) == siogdbunit) 4343 iobase = siogdbiobase; 4344 else 4345 iobase = siocniobase; 4346 s = spltty(); 4347 siocnopen(&sp, iobase, comdefaultrate); 4348 siocntxwait(iobase); 4349 outb(iobase + com_data, c); 4350 siocnclose(&sp, iobase); 4351 splx(s); 4352} 4353 4354#ifdef __alpha__ 4355int 4356siogdbgetc() 4357{ 4358 int c; 4359 Port_t iobase; 4360 int s; 4361 struct siocnstate sp; 4362 4363 iobase = siogdbiobase; 4364 s = spltty(); 4365 siocnopen(&sp, iobase, gdbdefaultrate); 4366 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 4367 ; 4368 c = inb(iobase + com_data); 4369 siocnclose(&sp, iobase); 4370 splx(s); 4371 return (c); 4372} 4373 4374void 4375siogdbputc(c) 4376 int c; 4377{ 4378 int s; 4379 struct siocnstate sp; 4380 4381 s = spltty(); 4382 siocnopen(&sp, siogdbiobase, gdbdefaultrate); 4383 siocntxwait(siogdbiobase); 4384 outb(siogdbiobase + com_data, c); 4385 siocnclose(&sp, siogdbiobase); 4386 splx(s); 4387} 4388#endif 4389 4390DRIVER_MODULE(sio, isa, sio_isa_driver, sio_devclass, 0, 0); 4391#if NCARD > 0 4392DRIVER_MODULE(sio, pccard, sio_pccard_driver, sio_devclass, 0, 0); 4393#endif 4394 4395#ifdef PC98 4396/* 4397 * pc98 local function 4398 */ 4399 4400static void 4401com_tiocm_set(struct com_s *com, int msr) 4402{ 4403 int s; 4404 int tmp = 0; 4405 int mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS; 4406 4407 s=spltty(); 4408 com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ) 4409 | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4410 tmp |= (CMD8251_TxEN|CMD8251_RxEN); 4411 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4412 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4413 pc98_i8251_clear_or_cmd( com, mask, tmp ); 4414 splx(s); 4415} 4416 4417static void 4418com_tiocm_bis(struct com_s *com, int msr) 4419{ 4420 int s; 4421 int tmp = 0; 4422 4423 s=spltty(); 4424 com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4425 tmp |= CMD8251_TxEN|CMD8251_RxEN; 4426 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4427 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4428 4429 pc98_i8251_or_cmd( com, tmp ); 4430 splx(s); 4431} 4432 4433static void 4434com_tiocm_bic(struct com_s *com, int msr) 4435{ 4436 int s; 4437 int tmp = msr; 4438 4439 s=spltty(); 4440 com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4441 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4442 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4443 4444 pc98_i8251_clear_cmd( com, tmp ); 4445 splx(s); 4446} 4447 4448static int 4449com_tiocm_get(struct com_s *com) 4450{ 4451 return( com->pc98_prev_modem_status ); 4452} 4453 4454static int 4455com_tiocm_get_delta(struct com_s *com) 4456{ 4457 int tmp; 4458 4459 tmp = com->pc98_modem_delta; 4460 com->pc98_modem_delta = 0; 4461 return( tmp ); 4462} 4463 4464/* convert to TIOCM_?? ( ioctl.h ) */ 4465static int 4466pc98_get_modem_status(struct com_s *com) 4467{ 4468 int stat, stat2; 4469 register int msr; 4470 4471 stat = inb(com->sts_port); 4472 stat2 = inb(com->in_modem_port); 4473 msr = com->pc98_prev_modem_status 4474 & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 4475 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR; 4476 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI; 4477 if ( stat & STS8251_DSR ) msr |= TIOCM_DSR; 4478 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS; 4479#if COM_CARRIER_DETECT_EMULATE 4480 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { 4481 msr |= TIOCM_CAR; 4482 } 4483#endif 4484 return(msr); 4485} 4486 4487static void 4488pc98_check_msr(void* chan) 4489{ 4490 int msr, delta; 4491 int s; 4492 register struct tty *tp; 4493 struct com_s *com; 4494 int mynor; 4495 int unit; 4496 dev_t dev; 4497 4498 dev=(dev_t)chan; 4499 mynor = minor(dev); 4500 unit = MINOR_TO_UNIT(mynor); 4501 com = com_addr(unit); 4502 tp = com->tp; 4503 4504 s = spltty(); 4505 msr = pc98_get_modem_status(com); 4506 /* make change flag */ 4507 delta = msr ^ com->pc98_prev_modem_status; 4508 if ( delta & TIOCM_CAR ) { 4509 if ( com->modem_car_chg_timer ) { 4510 if ( -- com->modem_car_chg_timer ) 4511 msr ^= TIOCM_CAR; 4512 } else { 4513 if ((com->modem_car_chg_timer = (msr & TIOCM_CAR) ? 4514 DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE) != 0) 4515 msr ^= TIOCM_CAR; 4516 } 4517 } else 4518 com->modem_car_chg_timer = 0; 4519 delta = ( msr ^ com->pc98_prev_modem_status ) & 4520 (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 4521 com->pc98_prev_modem_status = msr; 4522 delta = ( com->pc98_modem_delta |= delta ); 4523 splx(s); 4524 if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) { 4525 if ( delta ) { 4526 commint(dev); 4527 } 4528 timeout(pc98_check_msr, (caddr_t)dev, 4529 PC98_CHECK_MODEM_INTERVAL); 4530 } else { 4531 com->modem_checking = 0; 4532 } 4533} 4534 4535static void 4536pc98_msrint_start(dev_t dev) 4537{ 4538 struct com_s *com; 4539 int mynor; 4540 int unit; 4541 int s = spltty(); 4542 4543 mynor = minor(dev); 4544 unit = MINOR_TO_UNIT(mynor); 4545 com = com_addr(unit); 4546 /* modem control line check routine envoke interval is 1/10 sec */ 4547 if ( com->modem_checking == 0 ) { 4548 com->pc98_prev_modem_status = pc98_get_modem_status(com); 4549 com->pc98_modem_delta = 0; 4550 timeout(pc98_check_msr, (caddr_t)dev, 4551 PC98_CHECK_MODEM_INTERVAL); 4552 com->modem_checking = 1; 4553 } 4554 splx(s); 4555} 4556 4557static void 4558pc98_disable_i8251_interrupt(struct com_s *com, int mod) 4559{ 4560 /* disable interrupt */ 4561 register int tmp; 4562 4563 mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4564 COM_INT_DISABLE 4565 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4566 outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp ); 4567 COM_INT_ENABLE 4568} 4569 4570static void 4571pc98_enable_i8251_interrupt(struct com_s *com, int mod) 4572{ 4573 register int tmp; 4574 4575 COM_INT_DISABLE 4576 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4577 outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp ); 4578 COM_INT_ENABLE 4579} 4580 4581static int 4582pc98_check_i8251_interrupt(struct com_s *com) 4583{ 4584 return ( com->intr_enable & 0x07 ); 4585} 4586 4587static void 4588pc98_i8251_clear_cmd(struct com_s *com, int x) 4589{ 4590 int tmp; 4591 4592 COM_INT_DISABLE 4593 tmp = com->pc98_prev_siocmd & ~(x); 4594 outb(com->cmd_port, tmp); 4595 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4596 COM_INT_ENABLE 4597} 4598 4599static void 4600pc98_i8251_or_cmd(struct com_s *com, int x) 4601{ 4602 int tmp; 4603 4604 COM_INT_DISABLE 4605 tmp = com->pc98_prev_siocmd | (x); 4606 outb(com->cmd_port, tmp); 4607 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4608 COM_INT_ENABLE 4609} 4610 4611static void 4612pc98_i8251_set_cmd(struct com_s *com, int x) 4613{ 4614 int tmp; 4615 4616 COM_INT_DISABLE 4617 tmp = (x); 4618 outb(com->cmd_port, tmp); 4619 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4620 COM_INT_ENABLE 4621} 4622 4623static void 4624pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x) 4625{ 4626 int tmp; 4627 COM_INT_DISABLE 4628 tmp = com->pc98_prev_siocmd & ~(clr); 4629 tmp |= (x); 4630 outb(com->cmd_port, tmp); 4631 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4632 COM_INT_ENABLE 4633} 4634 4635static int 4636pc98_i8251_get_cmd(struct com_s *com) 4637{ 4638 return com->pc98_prev_siocmd; 4639} 4640 4641static int 4642pc98_i8251_get_mod(struct com_s *com) 4643{ 4644 return com->pc98_prev_siomod; 4645} 4646 4647static void 4648pc98_i8251_reset(struct com_s *com, int mode, int command) 4649{ 4650 outb(com->cmd_port, 0); /* dummy */ 4651 DELAY(2); 4652 outb(com->cmd_port, 0); /* dummy */ 4653 DELAY(2); 4654 outb(com->cmd_port, 0); /* dummy */ 4655 DELAY(2); 4656 outb(com->cmd_port, CMD8251_RESET); /* internal reset */ 4657 DELAY(2); 4658 outb(com->cmd_port, mode ); /* mode register */ 4659 com->pc98_prev_siomod = mode; 4660 DELAY(2); 4661 pc98_i8251_set_cmd( com, (command|CMD8251_ER) ); 4662} 4663 4664static void 4665pc98_check_sysclock(void) 4666{ 4667 /* get system clock from port */ 4668 if ( pc98_machine_type & M_8M ) { 4669 /* 8 MHz system & H98 */ 4670 sysclock = 8; 4671 } else { 4672 /* 5 MHz system */ 4673 sysclock = 5; 4674 } 4675} 4676 4677static void 4678com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) 4679{ 4680 int cfcr=0, count; 4681 int previnterrupt; 4682 4683 count = pc98_ttspeedtab( com, speed ); 4684 if ( count < 0 ) return; 4685 4686 previnterrupt = pc98_check_i8251_interrupt(com); 4687 pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx ); 4688 4689 switch ( cflag&CSIZE ) { 4690 case CS5: 4691 cfcr = MOD8251_5BITS; break; 4692 case CS6: 4693 cfcr = MOD8251_6BITS; break; 4694 case CS7: 4695 cfcr = MOD8251_7BITS; break; 4696 case CS8: 4697 cfcr = MOD8251_8BITS; break; 4698 } 4699 if ( cflag&PARENB ) { 4700 if ( cflag&PARODD ) 4701 cfcr |= MOD8251_PODD; 4702 else 4703 cfcr |= MOD8251_PEVEN; 4704 } else 4705 cfcr |= MOD8251_PDISAB; 4706 4707 if ( cflag&CSTOPB ) 4708 cfcr |= MOD8251_STOP2; 4709 else 4710 cfcr |= MOD8251_STOP1; 4711 4712 if ( count & 0x10000 ) 4713 cfcr |= MOD8251_CLKX1; 4714 else 4715 cfcr |= MOD8251_CLKX16; 4716 4717 if (epson_machine_id != 0x20) { /* XXX */ 4718 int tmp; 4719 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP)) 4720 ; 4721 } 4722 /* set baud rate from ospeed */ 4723 pc98_set_baud_rate( com, count ); 4724 4725 if ( cfcr != pc98_i8251_get_mod(com) ) 4726 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) ); 4727 4728 pc98_enable_i8251_interrupt( com, previnterrupt ); 4729} 4730 4731static int 4732pc98_ttspeedtab(struct com_s *com, int speed) 4733{ 4734 int if_type, effect_sp, count = -1, mod; 4735 4736 if_type = com->pc98_if_type & 0x0f; 4737 4738 switch (com->pc98_if_type) { 4739 case COM_IF_INTERNAL: 4740 if (PC98SIO_baud_rate_port(if_type) != -1) { 4741 count = ttspeedtab(speed, if_8251_type[if_type].speedtab); 4742 if (count > 0) { 4743 count |= COM1_EXT_CLOCK; 4744 break; 4745 } 4746 } 4747 4748 /* for *1CLK asynchronous! mode, TEFUTEFU */ 4749 mod = (sysclock == 5) ? 2457600 : 1996800; 4750 effect_sp = ttspeedtab( speed, pc98speedtab ); 4751 if ( effect_sp < 0 ) /* XXX */ 4752 effect_sp = ttspeedtab( (speed - 1), pc98speedtab ); 4753 if ( effect_sp <= 0 ) 4754 return effect_sp; 4755 if ( effect_sp == speed ) 4756 mod /= 16; 4757 if ( mod % effect_sp ) 4758 return(-1); 4759 count = mod / effect_sp; 4760 if ( count > 65535 ) 4761 return(-1); 4762 if ( effect_sp != speed ) 4763 count |= 0x10000; 4764 break; 4765 case COM_IF_PC9861K_1: 4766 case COM_IF_PC9861K_2: 4767 count = 1; 4768 break; 4769 case COM_IF_IND_SS_1: 4770 case COM_IF_IND_SS_2: 4771 case COM_IF_PIO9032B_1: 4772 case COM_IF_PIO9032B_2: 4773 if ( speed == 0 ) return 0; 4774 count = ttspeedtab( speed, if_8251_type[if_type].speedtab ); 4775 break; 4776 case COM_IF_B98_01_1: 4777 case COM_IF_B98_01_2: 4778 if ( speed == 0 ) return 0; 4779 count = ttspeedtab( speed, if_8251_type[if_type].speedtab ); 4780#ifdef B98_01_OLD 4781 if (count == 0 || count == 1) { 4782 count += 4; 4783 count |= 0x20000; /* x1 mode for 76800 and 153600 */ 4784 } 4785#endif 4786 break; 4787 } 4788 4789 return count; 4790} 4791 4792static void 4793pc98_set_baud_rate( struct com_s *com, int count ) 4794{ 4795 int if_type, io, s; 4796 4797 if_type = com->pc98_if_type & 0x0f; 4798 io = com->iobase & 0xff00; 4799 4800 switch (com->pc98_if_type) { 4801 case COM_IF_INTERNAL: 4802 if (PC98SIO_baud_rate_port(if_type) != -1) { 4803 if (count & COM1_EXT_CLOCK) { 4804 outb((Port_t)PC98SIO_baud_rate_port(if_type), count & 0xff); 4805 break; 4806 } else { 4807 outb((Port_t)PC98SIO_baud_rate_port(if_type), 0x09); 4808 } 4809 } 4810 4811 if ( count < 0 ) { 4812 printf( "[ Illegal count : %d ]", count ); 4813 return; 4814 } else if ( count == 0 ) 4815 return; 4816 /* set i8253 */ 4817 s = splclock(); 4818 if (count != 3) 4819 outb( 0x77, 0xb6 ); 4820 else 4821 outb( 0x77, 0xb4 ); 4822 outb( 0x5f, 0); 4823 outb( 0x75, count & 0xff ); 4824 outb( 0x5f, 0); 4825 outb( 0x75, (count >> 8) & 0xff ); 4826 splx(s); 4827 break; 4828 case COM_IF_IND_SS_1: 4829 case COM_IF_IND_SS_2: 4830 outb(io | PC98SIO_intr_ctrl_port(if_type), 0); 4831 outb(io | PC98SIO_baud_rate_port(if_type), 0); 4832 outb(io | PC98SIO_baud_rate_port(if_type), 0xc0); 4833 outb(io | PC98SIO_baud_rate_port(if_type), (count >> 8) | 0x80); 4834 outb(io | PC98SIO_baud_rate_port(if_type), count & 0xff); 4835 break; 4836 case COM_IF_PIO9032B_1: 4837 case COM_IF_PIO9032B_2: 4838 outb(io | PC98SIO_baud_rate_port(if_type), count); 4839 break; 4840 case COM_IF_B98_01_1: 4841 case COM_IF_B98_01_2: 4842 outb(io | PC98SIO_baud_rate_port(if_type), count & 0x0f); 4843#ifdef B98_01_OLD 4844 /* 4845 * Some old B98_01 board should be controlled 4846 * in different way, but this hasn't been tested yet. 4847 */ 4848 outb(io | PC98SIO_func_port(if_type), 4849 (count & 0x20000) ? 0xf0 : 0xf2); 4850#endif 4851 break; 4852 } 4853} 4854static int 4855pc98_check_if_type(device_t dev, struct siodev *iod) 4856{ 4857 int irr, io, if_type, tmp; 4858 static short irq_tab[2][8] = { 4859 { 3, 5, 6, 9, 10, 12, 13, -1}, 4860 { 3, 10, 12, 13, 5, 6, 9, -1} 4861 }; 4862 4863 iod->if_type = if_type = GET_IFTYPE(device_get_flags(dev)); 4864 if ((if_type < 0 || if_type > COM_IF_END1) && 4865 (if_type < 0x10 || if_type > COM_IF_END2)) 4866 return(-1); 4867 if_type &= 0x0f; 4868 iod->irq = 0; 4869 io = isa_get_port(dev) & 0xff00; 4870 4871 if (IS_8251(iod->if_type)) { 4872 if (PC98SIO_func_port(if_type) != -1) { 4873 outb(io | PC98SIO_func_port(if_type), 0xf2); 4874 tmp = ttspeedtab(9600, if_8251_type[if_type].speedtab); 4875 if (tmp != -1 && PC98SIO_baud_rate_port(if_type) != -1) 4876 outb(io | PC98SIO_baud_rate_port(if_type), tmp); 4877 } 4878 4879 iod->cmd = io | PC98SIO_cmd_port(if_type); 4880 iod->sts = io | PC98SIO_sts_port(if_type); 4881 iod->mod = io | PC98SIO_in_modem_port(if_type); 4882 iod->ctrl = io | PC98SIO_intr_ctrl_port(if_type); 4883 4884 if (iod->if_type == COM_IF_INTERNAL) { 4885 iod->irq = 4; 4886 4887 /* XXX check new internal port. */ 4888 outb(0x13a, 0); 4889 DELAY(10); 4890 for (tmp = 0; tmp < 100; tmp++) { 4891 if ((inb(0x13a) & 0x80) == 0) { 4892 PC98SIO_baud_rate_port(if_type) = 0x13a; 4893 if_8251_type[if_type].name = " (internal fast)"; 4894 if_8251_type[if_type].speedtab = pc98fast_speedtab; 4895 break; 4896 } 4897 DELAY(1); 4898 } 4899 } else { 4900 tmp = inb( iod->mod ) & if_8251_type[if_type].irr_mask; 4901 if ((isa_get_port(dev) & 0xff) == IO_COM2) 4902 iod->irq = irq_tab[0][tmp]; 4903 else 4904 iod->irq = irq_tab[1][tmp]; 4905 } 4906 } else { 4907 irr = if_16550a_type[if_type].irr_read; 4908#ifdef COM_MULTIPORT 4909 if (!COM_ISMULTIPORT(device_get_flags(dev)) || 4910 device_get_unit(dev) == COM_MPMASTER(device_get_flags(dev))) 4911#endif 4912 if (irr != -1) { 4913 tmp = inb(io | irr); 4914 if (isa_get_port(dev) & 0x01) /* XXX depend on RSB-384 */ 4915 iod->irq = irq_tab[1][tmp >> 3]; 4916 else 4917 iod->irq = irq_tab[0][tmp & 0x07]; 4918 } 4919 } 4920 if ( iod->irq == -1 ) return -1; 4921 4922 return 0; 4923} 4924static int 4925pc98_set_ioport( struct com_s *com, int id_flags ) 4926{ 4927 int io, if_type; 4928 4929 if_type = GET_IFTYPE(id_flags); 4930 if (IS_8251(if_type)) { 4931 pc98_check_sysclock(); 4932 io = com->iobase & 0xff00; 4933 com->pc98_if_type = if_type; 4934 if_type &= 0x0f; 4935 com->data_port = io | PC98SIO_data_port(if_type); 4936 com->cmd_port = io | PC98SIO_cmd_port(if_type); 4937 com->sts_port = io | PC98SIO_sts_port(if_type); 4938 com->in_modem_port = io | PC98SIO_in_modem_port(if_type); 4939 com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(if_type); 4940 return 0; 4941 } 4942 4943 return -1; 4944} 4945#endif /* PC98 defined */ 4946