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