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