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