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