sio.c revision 40565
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.67 1998/09/14 11:37:29 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_ident; 1960 u_char int_ctl; 1961 u_char int_ctl_new; 1962 1963#ifdef PC98 1964 u_char tmp=0; 1965recv_data=0; 1966#endif /* PC98 */ 1967 1968 int_ctl = inb(com->intr_ctl_port); 1969 int_ctl_new = int_ctl; 1970 1971 while (!com->gone) { 1972#ifdef PC98 1973status_read:; 1974 if (IS_8251(com->pc98_if_type)) { 1975 tmp = inb(com->sts_port); 1976more_intr: 1977 line_status = 0; 1978 if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY; 1979 if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY; 1980 if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE; 1981 if (tmp & STS8251_PE) line_status |= LSR_PE; 1982 if (tmp & STS8251_OE) line_status |= LSR_OE; 1983 if (tmp & STS8251_FE) line_status |= LSR_FE; 1984 if (tmp & STS8251_BD_SD) line_status |= LSR_BI; 1985 } else 1986#endif /* PC98 */ 1987 line_status = inb(com->line_status_port); 1988 1989 /* input event? (check first to help avoid overruns) */ 1990 while (line_status & LSR_RCV_MASK) { 1991 /* break/unnattached error bits or real input? */ 1992#ifdef PC98 1993 if(IS_8251(com->pc98_if_type)){ 1994 recv_data = inb(com->data_port); 1995 if(tmp & 0x78){ 1996 pc98_i8251_or_cmd(com,CMD8251_ER); 1997 recv_data = 0; 1998 } 1999 } else { 2000#endif /* PC98 */ 2001 if (!(line_status & LSR_RXRDY)) 2002 recv_data = 0; 2003 else 2004 recv_data = inb(com->data_port); 2005#ifdef PC98 2006 } 2007#endif 2008 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) { 2009 /* 2010 * Don't store BI if IGNBRK or FE/PE if IGNPAR. 2011 * Otherwise, push the work to a higher level 2012 * (to handle PARMRK) if we're bypassing. 2013 * Otherwise, convert BI/FE and PE+INPCK to 0. 2014 * 2015 * This makes bypassing work right in the 2016 * usual "raw" case (IGNBRK set, and IGNPAR 2017 * and INPCK clear). 2018 * 2019 * Note: BI together with FE/PE means just BI. 2020 */ 2021 if (line_status & LSR_BI) { 2022#if defined(DDB) && defined(BREAK_TO_DEBUGGER) 2023 if (com->unit == comconsole) { 2024 breakpoint(); 2025 goto cont; 2026 } 2027#endif 2028 if (com->tp == NULL 2029 || com->tp->t_iflag & IGNBRK) 2030 goto cont; 2031 } else { 2032 if (com->tp == NULL 2033 || com->tp->t_iflag & IGNPAR) 2034 goto cont; 2035 } 2036 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT 2037 && (line_status & (LSR_BI | LSR_FE) 2038 || com->tp->t_iflag & INPCK)) 2039 recv_data = 0; 2040 } 2041 ++com->bytes_in; 2042 if (com->hotchar != 0 && recv_data == com->hotchar) 2043 setsofttty(); 2044 ioptr = com->iptr; 2045 if (ioptr >= com->ibufend) 2046 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 2047 else { 2048 if (com->do_timestamp) 2049 microtime(&com->timestamp); 2050 ++com_events; 2051 schedsofttty(); 2052#if 0 /* for testing input latency vs efficiency */ 2053if (com->iptr - com->ibuf == 8) 2054 setsofttty(); 2055#endif 2056 ioptr[0] = recv_data; 2057 ioptr[CE_INPUT_OFFSET] = line_status; 2058 com->iptr = ++ioptr; 2059 if (ioptr == com->ihighwater 2060 && com->state & CS_RTS_IFLOW) 2061#ifdef PC98 2062 if(IS_8251(com->pc98_if_type)) 2063 com_tiocm_bic(com, TIOCM_RTS); 2064 else 2065#endif 2066 outb(com->modem_ctl_port, 2067 com->mcr_image &= ~MCR_RTS); 2068 if (line_status & LSR_OE) 2069 CE_RECORD(com, CE_OVERRUN); 2070 } 2071cont: 2072 /* 2073 * "& 0x7F" is to avoid the gcc-1.40 generating a slow 2074 * jump from the top of the loop to here 2075 */ 2076#ifdef PC98 2077 if(IS_8251(com->pc98_if_type)) 2078 goto status_read; 2079 else 2080#endif 2081 line_status = inb(com->line_status_port) & 0x7F; 2082 } 2083 2084 /* modem status change? (always check before doing output) */ 2085#ifdef PC98 2086 if(!IS_8251(com->pc98_if_type)){ 2087#endif 2088 modem_status = inb(com->modem_status_port); 2089 if (modem_status != com->last_modem_status) { 2090 if (com->do_dcd_timestamp 2091 && !(com->last_modem_status & MSR_DCD) 2092 && modem_status & MSR_DCD) 2093 microtime(&com->dcd_timestamp); 2094 2095 /* 2096 * Schedule high level to handle DCD changes. Note 2097 * that we don't use the delta bits anywhere. Some 2098 * UARTs mess them up, and it's easy to remember the 2099 * previous bits and calculate the delta. 2100 */ 2101 com->last_modem_status = modem_status; 2102 if (!(com->state & CS_CHECKMSR)) { 2103 com_events += LOTS_OF_EVENTS; 2104 com->state |= CS_CHECKMSR; 2105 setsofttty(); 2106 } 2107 2108 /* handle CTS change immediately for crisp flow ctl */ 2109 if (com->state & CS_CTS_OFLOW) { 2110 if (modem_status & MSR_CTS) 2111 com->state |= CS_ODEVREADY; 2112 else 2113 com->state &= ~CS_ODEVREADY; 2114 } 2115 } 2116#ifdef PC98 2117 } 2118#endif 2119 2120 /* output queued and everything ready? */ 2121 if (line_status & LSR_TXRDY 2122 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2123 ioptr = com->obufq.l_head; 2124 if (com->tx_fifo_size > 1) { 2125 u_int ocount; 2126 2127 ocount = com->obufq.l_tail - ioptr; 2128 if (ocount > com->tx_fifo_size) 2129 ocount = com->tx_fifo_size; 2130 com->bytes_out += ocount; 2131 do 2132 outb(com->data_port, *ioptr++); 2133 while (--ocount != 0); 2134 } else { 2135 outb(com->data_port, *ioptr++); 2136 ++com->bytes_out; 2137 } 2138#ifdef PC98 2139 if(IS_8251(com->pc98_if_type)) 2140 if ( !(pc98_check_i8251_interrupt(com) & IEN_TxFLAG) ) 2141 com_int_Tx_enable(com); 2142#endif 2143 com->obufq.l_head = ioptr; 2144 if (COM_IIR_TXRDYBUG(com)) { 2145 int_ctl_new = int_ctl | IER_ETXRDY; 2146 } 2147 if (ioptr >= com->obufq.l_tail) { 2148 struct lbq *qp; 2149 2150 qp = com->obufq.l_next; 2151 qp->l_queued = FALSE; 2152 qp = qp->l_next; 2153 if (qp != NULL) { 2154 com->obufq.l_head = qp->l_head; 2155 com->obufq.l_tail = qp->l_tail; 2156 com->obufq.l_next = qp; 2157 } else { 2158 /* output just completed */ 2159 if ( COM_IIR_TXRDYBUG(com) ) { 2160 int_ctl_new = int_ctl & ~IER_ETXRDY; 2161 } 2162 com->state &= ~CS_BUSY; 2163#if defined(PC98) 2164 if(IS_8251(com->pc98_if_type)) 2165 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2166 com_int_Tx_disable(com); 2167#endif 2168 } 2169 if (!(com->state & CS_ODONE)) { 2170 com_events += LOTS_OF_EVENTS; 2171 com->state |= CS_ODONE; 2172 setsofttty(); /* handle at high level ASAP */ 2173 } 2174 } 2175 if ( COM_IIR_TXRDYBUG(com) && (int_ctl != int_ctl_new)) { 2176 outb(com->intr_ctl_port, int_ctl_new); 2177 } 2178 } 2179#ifdef PC98 2180 else if (line_status & LSR_TXRDY) { 2181 if(IS_8251(com->pc98_if_type)) 2182 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2183 com_int_Tx_disable(com); 2184 } 2185 if(IS_8251(com->pc98_if_type)) 2186 if ((tmp = inb(com->sts_port)) & STS8251_RxRDY) 2187 goto more_intr; 2188#endif 2189 2190 /* finished? */ 2191#ifndef COM_MULTIPORT 2192#ifdef PC98 2193 if(IS_8251(com->pc98_if_type)) 2194 return; 2195#endif 2196 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) 2197#endif /* COM_MULTIPORT */ 2198 return; 2199 } 2200} 2201 2202static int 2203sioioctl(dev, cmd, data, flag, p) 2204 dev_t dev; 2205 u_long cmd; 2206 caddr_t data; 2207 int flag; 2208 struct proc *p; 2209{ 2210 struct com_s *com; 2211 int error; 2212 Port_t iobase; 2213 int mynor; 2214 int s; 2215 struct tty *tp; 2216#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2217 int oldcmd; 2218 struct termios term; 2219#endif 2220 2221 mynor = minor(dev); 2222 com = com_addr(MINOR_TO_UNIT(mynor)); 2223 if (com->gone) 2224 return (ENODEV); 2225 iobase = com->iobase; 2226 if (mynor & CONTROL_MASK) { 2227 struct termios *ct; 2228 2229 switch (mynor & CONTROL_MASK) { 2230 case CONTROL_INIT_STATE: 2231 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 2232 break; 2233 case CONTROL_LOCK_STATE: 2234 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 2235 break; 2236 default: 2237 return (ENODEV); /* /dev/nodev */ 2238 } 2239 switch (cmd) { 2240 case TIOCSETA: 2241 error = suser(p->p_ucred, &p->p_acflag); 2242 if (error != 0) 2243 return (error); 2244 *ct = *(struct termios *)data; 2245 return (0); 2246 case TIOCGETA: 2247 *(struct termios *)data = *ct; 2248 return (0); 2249 case TIOCGETD: 2250 *(int *)data = TTYDISC; 2251 return (0); 2252 case TIOCGWINSZ: 2253 bzero(data, sizeof(struct winsize)); 2254 return (0); 2255#ifdef DSI_SOFT_MODEM 2256 /* 2257 * Download micro-code to Digicom modem. 2258 */ 2259 case TIOCDSIMICROCODE: 2260 { 2261 u_long l; 2262 u_char *p,*pi; 2263 2264 pi = (u_char*)(*(caddr_t*)data); 2265 error = copyin(pi,&l,sizeof l); 2266 if(error) 2267 {return error;}; 2268 pi += sizeof l; 2269 2270 p = malloc(l,M_TEMP,M_NOWAIT); 2271 if(!p) 2272 {return ENOBUFS;} 2273 error = copyin(pi,p,l); 2274 if(error) 2275 {free(p,M_TEMP); return error;}; 2276 if(error = LoadSoftModem( 2277 MINOR_TO_UNIT(mynor),iobase,l,p)) 2278 {free(p,M_TEMP); return error;} 2279 free(p,M_TEMP); 2280 return(0); 2281 } 2282#endif /* DSI_SOFT_MODEM */ 2283 default: 2284 return (ENOTTY); 2285 } 2286 } 2287 tp = com->tp; 2288#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2289 term = tp->t_termios; 2290 oldcmd = cmd; 2291 error = ttsetcompat(tp, &cmd, data, &term); 2292 if (error != 0) 2293 return (error); 2294 if (cmd != oldcmd) 2295 data = (caddr_t)&term; 2296#endif 2297 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 2298 int cc; 2299 struct termios *dt = (struct termios *)data; 2300 struct termios *lt = mynor & CALLOUT_MASK 2301 ? &com->lt_out : &com->lt_in; 2302 2303 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 2304 | (dt->c_iflag & ~lt->c_iflag); 2305 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 2306 | (dt->c_oflag & ~lt->c_oflag); 2307 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 2308 | (dt->c_cflag & ~lt->c_cflag); 2309 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 2310 | (dt->c_lflag & ~lt->c_lflag); 2311 for (cc = 0; cc < NCCS; ++cc) 2312 if (lt->c_cc[cc] != 0) 2313 dt->c_cc[cc] = tp->t_cc[cc]; 2314 if (lt->c_ispeed != 0) 2315 dt->c_ispeed = tp->t_ispeed; 2316 if (lt->c_ospeed != 0) 2317 dt->c_ospeed = tp->t_ospeed; 2318 } 2319 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 2320 if (error != ENOIOCTL) 2321 return (error); 2322 s = spltty(); 2323 error = ttioctl(tp, cmd, data, flag); 2324 disc_optim(tp, &tp->t_termios, com); 2325 if (error != ENOIOCTL) { 2326 splx(s); 2327 return (error); 2328 } 2329#ifdef PC98 2330 if(IS_8251(com->pc98_if_type)){ 2331 switch (cmd) { 2332 case TIOCSBRK: 2333 com_send_break_on( com ); 2334 break; 2335 case TIOCCBRK: 2336 com_send_break_off( com ); 2337 break; 2338 case TIOCSDTR: 2339 com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS ); 2340 break; 2341 case TIOCCDTR: 2342 com_tiocm_bic(com, TIOCM_DTR); 2343 break; 2344 /* 2345 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2346 * changes get undone on the next call to comparam(). 2347 */ 2348 case TIOCMSET: 2349 com_tiocm_set( com, *(int *)data ); 2350 break; 2351 case TIOCMBIS: 2352 com_tiocm_bis( com, *(int *)data ); 2353 break; 2354 case TIOCMBIC: 2355 com_tiocm_bic( com, *(int *)data ); 2356 break; 2357 case TIOCMGET: 2358 *(int *)data = com_tiocm_get(com); 2359 break; 2360 case TIOCMSDTRWAIT: 2361 /* must be root since the wait applies to following logins */ 2362 error = suser(p->p_ucred, &p->p_acflag); 2363 if (error != 0) { 2364 splx(s); 2365 return (error); 2366 } 2367 com->dtr_wait = *(int *)data * hz / 100; 2368 break; 2369 case TIOCMGDTRWAIT: 2370 *(int *)data = com->dtr_wait * 100 / hz; 2371 break; 2372 case TIOCTIMESTAMP: 2373 com->do_timestamp = TRUE; 2374 *(struct timeval *)data = com->timestamp; 2375 break; 2376 case TIOCDCDTIMESTAMP: 2377 com->do_dcd_timestamp = TRUE; 2378 *(struct timeval *)data = com->dcd_timestamp; 2379 break; 2380 default: 2381 splx(s); 2382 return (ENOTTY); 2383 } 2384 } else { 2385#endif 2386 switch (cmd) { 2387 case TIOCSBRK: 2388 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 2389 break; 2390 case TIOCCBRK: 2391 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 2392 break; 2393 case TIOCSDTR: 2394 (void)commctl(com, TIOCM_DTR, DMBIS); 2395 break; 2396 case TIOCCDTR: 2397 (void)commctl(com, TIOCM_DTR, DMBIC); 2398 break; 2399 /* 2400 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2401 * changes get undone on the next call to comparam(). 2402 */ 2403 case TIOCMSET: 2404 (void)commctl(com, *(int *)data, DMSET); 2405 break; 2406 case TIOCMBIS: 2407 (void)commctl(com, *(int *)data, DMBIS); 2408 break; 2409 case TIOCMBIC: 2410 (void)commctl(com, *(int *)data, DMBIC); 2411 break; 2412 case TIOCMGET: 2413 *(int *)data = commctl(com, 0, DMGET); 2414 break; 2415 case TIOCMSDTRWAIT: 2416 /* must be root since the wait applies to following logins */ 2417 error = suser(p->p_ucred, &p->p_acflag); 2418 if (error != 0) { 2419 splx(s); 2420 return (error); 2421 } 2422 com->dtr_wait = *(int *)data * hz / 100; 2423 break; 2424 case TIOCMGDTRWAIT: 2425 *(int *)data = com->dtr_wait * 100 / hz; 2426 break; 2427 case TIOCTIMESTAMP: 2428 com->do_timestamp = TRUE; 2429 *(struct timeval *)data = com->timestamp; 2430 break; 2431 case TIOCDCDTIMESTAMP: 2432 com->do_dcd_timestamp = TRUE; 2433 *(struct timeval *)data = com->dcd_timestamp; 2434 break; 2435 default: 2436 splx(s); 2437 return (ENOTTY); 2438 } 2439#ifdef PC98 2440 } 2441#endif 2442 splx(s); 2443 return (0); 2444} 2445 2446static void 2447siopoll() 2448{ 2449 int unit; 2450 2451 if (com_events == 0) 2452 return; 2453repeat: 2454 for (unit = 0; unit < NSIOTOT; ++unit) { 2455 u_char *buf; 2456 struct com_s *com; 2457 u_char *ibuf; 2458 int incc; 2459 struct tty *tp; 2460#ifdef PC98 2461 int tmp; 2462#endif 2463 2464 com = com_addr(unit); 2465 if (com == NULL) 2466 continue; 2467 tp = com->tp; 2468 if (tp == NULL || com->gone) { 2469 /* 2470 * Discard any events related to never-opened or 2471 * going-away devices. 2472 */ 2473 disable_intr(); 2474 incc = com->iptr - com->ibuf; 2475 com->iptr = com->ibuf; 2476 if (com->state & CS_CHECKMSR) { 2477 incc += LOTS_OF_EVENTS; 2478 com->state &= ~CS_CHECKMSR; 2479 } 2480 com_events -= incc; 2481 enable_intr(); 2482 continue; 2483 } 2484 2485 /* switch the role of the low-level input buffers */ 2486 if (com->iptr == (ibuf = com->ibuf)) { 2487 buf = NULL; /* not used, but compiler can't tell */ 2488 incc = 0; 2489 } else { 2490 buf = ibuf; 2491 disable_intr(); 2492 incc = com->iptr - buf; 2493 com_events -= incc; 2494 if (ibuf == com->ibuf1) 2495 ibuf = com->ibuf2; 2496 else 2497 ibuf = com->ibuf1; 2498 com->ibufend = ibuf + RS_IBUFSIZE; 2499 com->ihighwater = ibuf + RS_IHIGHWATER; 2500 com->iptr = ibuf; 2501 2502 /* 2503 * There is now room for another low-level buffer full 2504 * of input, so enable RTS if it is now disabled and 2505 * there is room in the high-level buffer. 2506 */ 2507#ifdef PC98 2508 if(IS_8251(com->pc98_if_type)) 2509 tmp = com_tiocm_get(com) & TIOCM_RTS; 2510 else 2511 tmp = com->mcr_image & MCR_RTS; 2512#endif 2513 if ((com->state & CS_RTS_IFLOW) 2514#ifdef PC98 2515 && !(tmp) 2516#else 2517 && !(com->mcr_image & MCR_RTS) 2518#endif 2519 && !(tp->t_state & TS_TBLOCK)) 2520#ifdef PC98 2521 if(IS_8251(com->pc98_if_type)) 2522 com_tiocm_bis(com, TIOCM_RTS); 2523 else 2524#endif 2525 outb(com->modem_ctl_port, 2526 com->mcr_image |= MCR_RTS); 2527 enable_intr(); 2528 com->ibuf = ibuf; 2529 } 2530 2531 if (com->state & CS_CHECKMSR) { 2532 u_char delta_modem_status; 2533 2534#ifdef PC98 2535 if(!IS_8251(com->pc98_if_type)){ 2536#endif 2537 disable_intr(); 2538 delta_modem_status = com->last_modem_status 2539 ^ com->prev_modem_status; 2540 com->prev_modem_status = com->last_modem_status; 2541 com_events -= LOTS_OF_EVENTS; 2542 com->state &= ~CS_CHECKMSR; 2543 enable_intr(); 2544 if (delta_modem_status & MSR_DCD) 2545 (*linesw[tp->t_line].l_modem) 2546 (tp, com->prev_modem_status & MSR_DCD); 2547#ifdef PC98 2548 } 2549#endif 2550 } 2551 if (com->state & CS_ODONE) { 2552 disable_intr(); 2553 com_events -= LOTS_OF_EVENTS; 2554 com->state &= ~CS_ODONE; 2555 enable_intr(); 2556 if (!(com->state & CS_BUSY) 2557 && !(com->extra_state & CSE_BUSYCHECK)) { 2558 timeout(siobusycheck, com, hz / 100); 2559 com->extra_state |= CSE_BUSYCHECK; 2560 } 2561 (*linesw[tp->t_line].l_start)(tp); 2562 } 2563 if (incc <= 0 || !(tp->t_state & TS_ISOPEN) || 2564 !(tp->t_cflag & CREAD)) 2565 continue; 2566 /* 2567 * Avoid the grotesquely inefficient lineswitch routine 2568 * (ttyinput) in "raw" mode. It usually takes about 450 2569 * instructions (that's without canonical processing or echo!). 2570 * slinput is reasonably fast (usually 40 instructions plus 2571 * call overhead). 2572 */ 2573 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 2574 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 2575 && (com->state & CS_RTS_IFLOW 2576 || tp->t_iflag & IXOFF) 2577 && !(tp->t_state & TS_TBLOCK)) 2578 ttyblock(tp); 2579 tk_nin += incc; 2580 tk_rawcc += incc; 2581 tp->t_rawcc += incc; 2582 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 2583 += b_to_q((char *)buf, incc, &tp->t_rawq); 2584 ttwakeup(tp); 2585 if (tp->t_state & TS_TTSTOP 2586 && (tp->t_iflag & IXANY 2587 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 2588 tp->t_state &= ~TS_TTSTOP; 2589 tp->t_lflag &= ~FLUSHO; 2590 comstart(tp); 2591 } 2592 } else { 2593 do { 2594 u_char line_status; 2595 int recv_data; 2596 2597 line_status = (u_char) buf[CE_INPUT_OFFSET]; 2598 recv_data = (u_char) *buf++; 2599 if (line_status 2600 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 2601 if (line_status & LSR_BI) 2602 recv_data |= TTY_BI; 2603 if (line_status & LSR_FE) 2604 recv_data |= TTY_FE; 2605 if (line_status & LSR_OE) 2606 recv_data |= TTY_OE; 2607 if (line_status & LSR_PE) 2608 recv_data |= TTY_PE; 2609 } 2610 (*linesw[tp->t_line].l_rint)(recv_data, tp); 2611 } while (--incc > 0); 2612 } 2613 if (com_events == 0) 2614 break; 2615 } 2616 if (com_events >= LOTS_OF_EVENTS) 2617 goto repeat; 2618} 2619 2620static int 2621comparam(tp, t) 2622 struct tty *tp; 2623 struct termios *t; 2624{ 2625 u_int cfcr; 2626 int cflag; 2627 struct com_s *com; 2628 int divisor; 2629 u_char dlbh; 2630 u_char dlbl; 2631 int error; 2632 Port_t iobase; 2633 int s; 2634 int unit; 2635 int txtimeout; 2636#ifdef PC98 2637 Port_t tmp_port; 2638 int tmp_flg; 2639#endif 2640 2641#ifdef PC98 2642 cfcr = 0; 2643 unit = DEV_TO_UNIT(tp->t_dev); 2644 com = com_addr(unit); 2645 iobase = com->iobase; 2646 if(IS_8251(com->pc98_if_type)) { 2647 divisor = pc98_ttspeedtab(com, t->c_ospeed); 2648 } else 2649#endif 2650 /* do historical conversions */ 2651 if (t->c_ispeed == 0) 2652 t->c_ispeed = t->c_ospeed; 2653 2654 /* check requested parameters */ 2655 divisor = ttspeedtab(t->c_ospeed, comspeedtab); 2656 if (divisor < 0 || divisor > 0 && t->c_ispeed != t->c_ospeed) 2657 return (EINVAL); 2658 2659 /* parameters are OK, convert them to the com struct and the device */ 2660#ifndef PC98 2661 unit = DEV_TO_UNIT(tp->t_dev); 2662 com = com_addr(unit); 2663 iobase = com->iobase; 2664#endif 2665 s = spltty(); 2666#ifdef PC98 2667 if(IS_8251(com->pc98_if_type)){ 2668 if(divisor == 0) 2669 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 2670 else 2671 com_tiocm_bis( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 2672 } else { 2673#endif 2674 if (divisor == 0) 2675 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 2676 else 2677 (void)commctl(com, TIOCM_DTR, DMBIS); 2678#ifdef PC98 2679 } 2680#endif 2681 cflag = t->c_cflag; 2682#ifdef PC98 2683 if(!IS_8251(com->pc98_if_type)){ 2684#endif 2685 switch (cflag & CSIZE) { 2686 case CS5: 2687 cfcr = CFCR_5BITS; 2688 break; 2689 case CS6: 2690 cfcr = CFCR_6BITS; 2691 break; 2692 case CS7: 2693 cfcr = CFCR_7BITS; 2694 break; 2695 default: 2696 cfcr = CFCR_8BITS; 2697 break; 2698 } 2699 if (cflag & PARENB) { 2700 cfcr |= CFCR_PENAB; 2701 if (!(cflag & PARODD)) 2702 cfcr |= CFCR_PEVEN; 2703 } 2704 if (cflag & CSTOPB) 2705 cfcr |= CFCR_STOPB; 2706 2707 if (com->hasfifo && divisor != 0) { 2708 /* 2709 * Use a fifo trigger level low enough so that the input 2710 * latency from the fifo is less than about 16 msec and 2711 * the total latency is less than about 30 msec. These 2712 * latencies are reasonable for humans. Serial comms 2713 * protocols shouldn't expect anything better since modem 2714 * latencies are larger. 2715 */ 2716 com->fifo_image = t->c_ospeed <= 4800 2717 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; 2718#ifdef COM_ESP 2719 /* 2720 * The Hayes ESP card needs the fifo DMA mode bit set 2721 * in compatibility mode. If not, it will interrupt 2722 * for each character received. 2723 */ 2724 if (com->esp) 2725 com->fifo_image |= FIFO_DMA_MODE; 2726#endif 2727 outb(iobase + com_fifo, com->fifo_image); 2728 } 2729 2730 /* 2731 * Some UARTs lock up if the divisor latch registers are selected 2732 * while the UART is doing output (they refuse to transmit anything 2733 * more until given a hard reset). Fix this by stopping filling 2734 * the device buffers and waiting for them to drain. Reading the 2735 * line status port outside of siointr1() might lose some receiver 2736 * error bits, but that is acceptable here. 2737 */ 2738#ifdef PC98 2739 } 2740#endif 2741 disable_intr(); 2742retry: 2743 com->state &= ~CS_TTGO; 2744 txtimeout = tp->t_timeout; 2745 enable_intr(); 2746#ifdef PC98 2747 if(IS_8251(com->pc98_if_type)){ 2748 tmp_port = com->sts_port; 2749 tmp_flg = (STS8251_TxRDY|STS8251_TxEMP); 2750 } else { 2751 tmp_port = com->line_status_port; 2752 tmp_flg = (LSR_TSRE|LSR_TXRDY); 2753 } 2754 while ((inb(tmp_port) & tmp_flg) != tmp_flg) { 2755#else 2756 while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2757 != (LSR_TSRE | LSR_TXRDY)) { 2758#endif 2759 tp->t_state |= TS_SO_OCOMPLETE; 2760 error = ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI | PCATCH, 2761 "siotx", hz / 100); 2762 if ( txtimeout != 0 2763 && (!error || error == EAGAIN) 2764 && (txtimeout -= hz / 100) <= 0 2765 ) 2766 error = EIO; 2767 if (com->gone) 2768 error = ENODEV; 2769 if (error != 0 && error != EAGAIN) { 2770 if (!(tp->t_state & TS_TTSTOP)) { 2771 disable_intr(); 2772 com->state |= CS_TTGO; 2773 enable_intr(); 2774 } 2775 splx(s); 2776 return (error); 2777 } 2778 } 2779 2780 disable_intr(); /* very important while com_data is hidden */ 2781 2782 /* 2783 * XXX - clearing CS_TTGO is not sufficient to stop further output, 2784 * because siopoll() calls comstart() which usually sets it again 2785 * because TS_TTSTOP is clear. Setting TS_TTSTOP would not be 2786 * sufficient, for similar reasons. 2787 */ 2788#ifdef PC98 2789 if ((inb(tmp_port) & tmp_flg) != tmp_flg) 2790#else 2791 if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2792 != (LSR_TSRE | LSR_TXRDY)) 2793#endif 2794 goto retry; 2795 2796#ifdef PC98 2797 if(!IS_8251(com->pc98_if_type)){ 2798#endif 2799 if (divisor != 0) { 2800 outb(iobase + com_cfcr, cfcr | CFCR_DLAB); 2801 /* 2802 * Only set the divisor registers if they would change, 2803 * since on some 16550 incompatibles (UMC8669F), setting 2804 * them while input is arriving them loses sync until 2805 * data stops arriving. 2806 */ 2807 dlbl = divisor & 0xFF; 2808 if (inb(iobase + com_dlbl) != dlbl) 2809 outb(iobase + com_dlbl, dlbl); 2810 dlbh = (u_int) divisor >> 8; 2811 if (inb(iobase + com_dlbh) != dlbh) 2812 outb(iobase + com_dlbh, dlbh); 2813 } 2814 2815 2816 outb(iobase + com_cfcr, com->cfcr_image = cfcr); 2817 2818#ifdef PC98 2819 } else 2820 com_cflag_and_speed_set(com, cflag, t->c_ospeed); 2821#endif 2822 if (!(tp->t_state & TS_TTSTOP)) 2823 com->state |= CS_TTGO; 2824 2825 if (cflag & CRTS_IFLOW) { 2826 if (com->st16650a) { 2827 outb(iobase + com_cfcr, 0xbf); 2828 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40); 2829 } 2830 com->state |= CS_RTS_IFLOW; 2831 /* 2832 * If CS_RTS_IFLOW just changed from off to on, the change 2833 * needs to be propagated to MCR_RTS. This isn't urgent, 2834 * so do it later by calling comstart() instead of repeating 2835 * a lot of code from comstart() here. 2836 */ 2837 } else if (com->state & CS_RTS_IFLOW) { 2838 com->state &= ~CS_RTS_IFLOW; 2839 /* 2840 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2841 * on here, since comstart() won't do it later. 2842 */ 2843#ifdef PC98 2844 if(IS_8251(com->pc98_if_type)) 2845 com_tiocm_bis(com, TIOCM_RTS); 2846 else 2847#endif 2848 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2849 if (com->st16650a) { 2850 outb(iobase + com_cfcr, 0xbf); 2851 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40); 2852 } 2853 } 2854 2855 2856 /* 2857 * Set up state to handle output flow control. 2858 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2859 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2860 */ 2861 com->state |= CS_ODEVREADY; 2862 com->state &= ~CS_CTS_OFLOW; 2863 if (cflag & CCTS_OFLOW) { 2864 com->state |= CS_CTS_OFLOW; 2865#ifdef PC98 2866 if(IS_8251(com->pc98_if_type)){ 2867 if (!(pc98_get_modem_status(com) & TIOCM_CTS)) 2868 com->state &= ~CS_ODEVREADY; 2869 } else { 2870#endif 2871 if (!(com->last_modem_status & MSR_CTS)) 2872 com->state &= ~CS_ODEVREADY; 2873 if (com->st16650a) { 2874 outb(iobase + com_cfcr, 0xbf); 2875 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80); 2876 } 2877#ifdef PC98 2878 } 2879#endif 2880 } else { 2881 if (com->st16650a) { 2882 outb(iobase + com_cfcr, 0xbf); 2883 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80); 2884 } 2885 } 2886 2887 2888 outb(iobase + com_cfcr, com->cfcr_image); 2889 2890 2891 /* XXX shouldn't call functions while intrs are disabled. */ 2892 disc_optim(tp, t, com); 2893 /* 2894 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2895 * unconditionally, but that defeated the careful discarding of 2896 * stale input in sioopen(). 2897 */ 2898 if (com->state >= (CS_BUSY | CS_TTGO)) 2899 siointr1(com); 2900 2901 enable_intr(); 2902 splx(s); 2903 comstart(tp); 2904 return (0); 2905} 2906 2907static void 2908comstart(tp) 2909 struct tty *tp; 2910{ 2911 struct com_s *com; 2912 int s; 2913 int unit; 2914#ifdef PC98 2915 int tmp; 2916#endif 2917 2918 unit = DEV_TO_UNIT(tp->t_dev); 2919 com = com_addr(unit); 2920 s = spltty(); 2921 disable_intr(); 2922 if (tp->t_state & TS_TTSTOP) 2923 com->state &= ~CS_TTGO; 2924 else 2925 com->state |= CS_TTGO; 2926 if (tp->t_state & TS_TBLOCK) { 2927#ifdef PC98 2928 if(IS_8251(com->pc98_if_type)) 2929 tmp = com_tiocm_get(com) & TIOCM_RTS; 2930 else 2931 tmp = com->mcr_image & MCR_RTS; 2932 if (tmp && (com->state & CS_RTS_IFLOW)) 2933#else 2934 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 2935#endif 2936#ifdef PC98 2937 if(IS_8251(com->pc98_if_type)) 2938 com_tiocm_bic(com, TIOCM_RTS); 2939 else 2940#endif 2941 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2942 } else { 2943#ifdef PC98 2944 if(IS_8251(com->pc98_if_type)) 2945 tmp = com_tiocm_get(com) & TIOCM_RTS; 2946 else 2947 tmp = com->mcr_image & MCR_RTS; 2948 if (!(tmp) && com->iptr < com->ihighwater 2949 && com->state & CS_RTS_IFLOW) 2950#else 2951 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater 2952 && com->state & CS_RTS_IFLOW) 2953#endif 2954#ifdef PC98 2955 if(IS_8251(com->pc98_if_type)) 2956 com_tiocm_bis(com, TIOCM_RTS); 2957 else 2958#endif 2959 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2960 } 2961 enable_intr(); 2962 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2963 ttwwakeup(tp); 2964#ifdef PC98 2965/* if(IS_8251(com->pc98_if_type)) 2966 com_int_Tx_enable(com); */ 2967#endif 2968 splx(s); 2969 return; 2970 } 2971 if (tp->t_outq.c_cc != 0) { 2972 struct lbq *qp; 2973 struct lbq *next; 2974 2975 if (!com->obufs[0].l_queued) { 2976 com->obufs[0].l_tail 2977 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2978 sizeof com->obuf1); 2979 com->obufs[0].l_next = NULL; 2980 com->obufs[0].l_queued = TRUE; 2981 disable_intr(); 2982 if (com->state & CS_BUSY) { 2983 qp = com->obufq.l_next; 2984 while ((next = qp->l_next) != NULL) 2985 qp = next; 2986 qp->l_next = &com->obufs[0]; 2987 } else { 2988 com->obufq.l_head = com->obufs[0].l_head; 2989 com->obufq.l_tail = com->obufs[0].l_tail; 2990 com->obufq.l_next = &com->obufs[0]; 2991 com->state |= CS_BUSY; 2992 } 2993 enable_intr(); 2994 } 2995 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2996 com->obufs[1].l_tail 2997 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2998 sizeof com->obuf2); 2999 com->obufs[1].l_next = NULL; 3000 com->obufs[1].l_queued = TRUE; 3001 disable_intr(); 3002 if (com->state & CS_BUSY) { 3003 qp = com->obufq.l_next; 3004 while ((next = qp->l_next) != NULL) 3005 qp = next; 3006 qp->l_next = &com->obufs[1]; 3007 } else { 3008 com->obufq.l_head = com->obufs[1].l_head; 3009 com->obufq.l_tail = com->obufs[1].l_tail; 3010 com->obufq.l_next = &com->obufs[1]; 3011 com->state |= CS_BUSY; 3012 } 3013 enable_intr(); 3014 } 3015 tp->t_state |= TS_BUSY; 3016 } 3017 disable_intr(); 3018 if (com->state >= (CS_BUSY | CS_TTGO)) 3019 siointr1(com); /* fake interrupt to start output */ 3020 enable_intr(); 3021#ifdef PC98 3022/* if(IS_8251(com->pc98_if_type)) 3023 com_int_Tx_enable(com); */ 3024#endif 3025 ttwwakeup(tp); 3026 splx(s); 3027} 3028 3029static void 3030siostop(tp, rw) 3031 struct tty *tp; 3032 int rw; 3033{ 3034 struct com_s *com; 3035 3036 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 3037 if (com->gone) 3038 return; 3039 disable_intr(); 3040 if (rw & FWRITE) { 3041 if (com->hasfifo) 3042#ifdef COM_ESP 3043 /* XXX avoid h/w bug. */ 3044 if (!com->esp) 3045#endif 3046 /* XXX does this flush everything? */ 3047 outb(com->iobase + com_fifo, 3048 FIFO_XMT_RST | com->fifo_image); 3049 com->obufs[0].l_queued = FALSE; 3050 com->obufs[1].l_queued = FALSE; 3051 if (com->state & CS_ODONE) 3052 com_events -= LOTS_OF_EVENTS; 3053 com->state &= ~(CS_ODONE | CS_BUSY); 3054 com->tp->t_state &= ~TS_BUSY; 3055 } 3056 if (rw & FREAD) { 3057 if (com->hasfifo) 3058#ifdef COM_ESP 3059 /* XXX avoid h/w bug. */ 3060 if (!com->esp) 3061#endif 3062 /* XXX does this flush everything? */ 3063 outb(com->iobase + com_fifo, 3064 FIFO_RCV_RST | com->fifo_image); 3065 com_events -= (com->iptr - com->ibuf); 3066 com->iptr = com->ibuf; 3067 } 3068 enable_intr(); 3069 comstart(tp); 3070} 3071 3072static struct tty * 3073siodevtotty(dev) 3074 dev_t dev; 3075{ 3076 int mynor; 3077 int unit; 3078 3079 mynor = minor(dev); 3080 if (mynor & CONTROL_MASK) 3081 return (NULL); 3082 unit = MINOR_TO_UNIT(mynor); 3083 if ((u_int) unit >= NSIOTOT) 3084 return (NULL); 3085 return (&sio_tty[unit]); 3086} 3087 3088static int 3089commctl(com, bits, how) 3090 struct com_s *com; 3091 int bits; 3092 int how; 3093{ 3094 int mcr; 3095 int msr; 3096 3097 if (how == DMGET) { 3098 bits = TIOCM_LE; /* XXX - always enabled while open */ 3099 mcr = com->mcr_image; 3100 if (mcr & MCR_DTR) 3101 bits |= TIOCM_DTR; 3102 if (mcr & MCR_RTS) 3103 bits |= TIOCM_RTS; 3104 msr = com->prev_modem_status; 3105 if (msr & MSR_CTS) 3106 bits |= TIOCM_CTS; 3107 if (msr & MSR_DCD) 3108 bits |= TIOCM_CD; 3109 if (msr & MSR_DSR) 3110 bits |= TIOCM_DSR; 3111 /* 3112 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI 3113 * more volatile by reading the modem status a lot. Perhaps 3114 * we should latch both bits until the status is read here. 3115 */ 3116 if (msr & (MSR_RI | MSR_TERI)) 3117 bits |= TIOCM_RI; 3118 return (bits); 3119 } 3120 mcr = 0; 3121 if (bits & TIOCM_DTR) 3122 mcr |= MCR_DTR; 3123 if (bits & TIOCM_RTS) 3124 mcr |= MCR_RTS; 3125 if (com->gone) 3126 return(0); 3127 disable_intr(); 3128 switch (how) { 3129 case DMSET: 3130 outb(com->modem_ctl_port, 3131 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); 3132 break; 3133 case DMBIS: 3134 outb(com->modem_ctl_port, com->mcr_image |= mcr); 3135 break; 3136 case DMBIC: 3137 outb(com->modem_ctl_port, com->mcr_image &= ~mcr); 3138 break; 3139 } 3140 enable_intr(); 3141 return (0); 3142} 3143 3144static void 3145siosettimeout() 3146{ 3147 struct com_s *com; 3148 bool_t someopen; 3149 int unit; 3150 3151 /* 3152 * Set our timeout period to 1 second if no polled devices are open. 3153 * Otherwise set it to max(1/200, 1/hz). 3154 * Enable timeouts iff some device is open. 3155 */ 3156 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3157 sio_timeout = hz; 3158 someopen = FALSE; 3159 for (unit = 0; unit < NSIOTOT; ++unit) { 3160 com = com_addr(unit); 3161 if (com != NULL && com->tp != NULL 3162 && com->tp->t_state & TS_ISOPEN && !com->gone) { 3163 someopen = TRUE; 3164 if (com->poll || com->poll_output) { 3165 sio_timeout = hz > 200 ? hz / 200 : 1; 3166 break; 3167 } 3168 } 3169 } 3170 if (someopen) { 3171 sio_timeouts_until_log = hz / sio_timeout; 3172 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 3173 sio_timeout); 3174 } else { 3175 /* Flush error messages, if any. */ 3176 sio_timeouts_until_log = 1; 3177 comwakeup((void *)NULL); 3178 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3179 } 3180} 3181 3182static void 3183comwakeup(chan) 3184 void *chan; 3185{ 3186 struct com_s *com; 3187 int unit; 3188 3189 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 3190 3191 /* 3192 * Recover from lost output interrupts. 3193 * Poll any lines that don't use interrupts. 3194 */ 3195 for (unit = 0; unit < NSIOTOT; ++unit) { 3196 com = com_addr(unit); 3197 if (com != NULL && !com->gone 3198 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 3199 disable_intr(); 3200 siointr1(com); 3201 enable_intr(); 3202 } 3203 } 3204 3205 /* 3206 * Check for and log errors, but not too often. 3207 */ 3208 if (--sio_timeouts_until_log > 0) 3209 return; 3210 sio_timeouts_until_log = hz / sio_timeout; 3211 for (unit = 0; unit < NSIOTOT; ++unit) { 3212 int errnum; 3213 3214 com = com_addr(unit); 3215 if (com == NULL) 3216 continue; 3217 if (com->gone) 3218 continue; 3219 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 3220 u_int delta; 3221 u_long total; 3222 3223 disable_intr(); 3224 delta = com->delta_error_counts[errnum]; 3225 com->delta_error_counts[errnum] = 0; 3226 enable_intr(); 3227 if (delta == 0) 3228 continue; 3229 total = com->error_counts[errnum] += delta; 3230 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", 3231 unit, delta, error_desc[errnum], 3232 delta == 1 ? "" : "s", total); 3233 } 3234 } 3235} 3236 3237#ifdef PC98 3238/* commint is called when modem control line changes */ 3239static void 3240commint(dev_t dev) 3241{ 3242 register struct tty *tp; 3243 int stat,delta; 3244 struct com_s *com; 3245 int mynor,unit; 3246 3247 mynor = minor(dev); 3248 unit = MINOR_TO_UNIT(mynor); 3249 com = com_addr(unit); 3250 tp = com->tp; 3251 3252 stat = com_tiocm_get(com); 3253 delta = com_tiocm_get_delta(com); 3254 3255 if (com->state & CS_CTS_OFLOW) { 3256 if (stat & TIOCM_CTS) 3257 com->state |= CS_ODEVREADY; 3258 else 3259 com->state &= ~CS_ODEVREADY; 3260 } 3261 if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) { 3262 if (stat & TIOCM_CAR ) 3263 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 3264 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 3265 /* negate DTR, RTS */ 3266 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ? 3267 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE ); 3268 /* disable IENABLE */ 3269 com_int_TxRx_disable( com ); 3270 } 3271 } 3272} 3273#endif 3274 3275static void 3276disc_optim(tp, t, com) 3277 struct tty *tp; 3278 struct termios *t; 3279 struct com_s *com; 3280{ 3281 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 3282 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 3283 && (!(t->c_iflag & PARMRK) 3284 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 3285 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 3286 && linesw[tp->t_line].l_rint == ttyinput) 3287 tp->t_state |= TS_CAN_BYPASS_L_RINT; 3288 else 3289 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 3290 com->hotchar = linesw[tp->t_line].l_hotchar; 3291} 3292 3293/* 3294 * Following are all routines needed for SIO to act as console 3295 */ 3296#include <machine/cons.h> 3297 3298struct siocnstate { 3299 u_char dlbl; 3300 u_char dlbh; 3301 u_char ier; 3302 u_char cfcr; 3303 u_char mcr; 3304}; 3305 3306static speed_t siocngetspeed __P((Port_t, struct speedtab *)); 3307static void siocnclose __P((struct siocnstate *sp)); 3308static void siocnopen __P((struct siocnstate *sp)); 3309static void siocntxwait __P((void)); 3310 3311static void 3312siocntxwait() 3313{ 3314 int timo; 3315 3316 /* 3317 * Wait for any pending transmission to finish. Required to avoid 3318 * the UART lockup bug when the speed is changed, and for normal 3319 * transmits. 3320 */ 3321 timo = 100000; 3322 while ((inb(siocniobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) 3323 != (LSR_TSRE | LSR_TXRDY) && --timo != 0) 3324 ; 3325} 3326 3327/* 3328 * Read the serial port specified and try to figure out what speed 3329 * it's currently running at. We're assuming the serial port has 3330 * been initialized and is basicly idle. This routine is only intended 3331 * to be run at system startup. 3332 * 3333 * If the value read from the serial port doesn't make sense, return 0. 3334 */ 3335 3336static speed_t 3337siocngetspeed(iobase, table) 3338 Port_t iobase; 3339 struct speedtab *table; 3340{ 3341 int code; 3342 u_char dlbh; 3343 u_char dlbl; 3344 u_char cfcr; 3345 3346 cfcr = inb(iobase + com_cfcr); 3347 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 3348 3349 dlbl = inb(iobase + com_dlbl); 3350 dlbh = inb(iobase + com_dlbh); 3351 3352 outb(iobase + com_cfcr, cfcr); 3353 3354 code = dlbh << 8 | dlbl; 3355 3356 for ( ; table->sp_speed != -1; table++) 3357 if (table->sp_code == code) 3358 return (table->sp_speed); 3359 3360 return 0; /* didn't match anything sane */ 3361} 3362 3363static void 3364siocnopen(sp) 3365 struct siocnstate *sp; 3366{ 3367 int divisor; 3368 u_char dlbh; 3369 u_char dlbl; 3370 Port_t iobase; 3371 3372 /* 3373 * Save all the device control registers except the fifo register 3374 * and set our default ones (cs8 -parenb speed=comdefaultrate). 3375 * We can't save the fifo register since it is read-only. 3376 */ 3377 iobase = siocniobase; 3378 sp->ier = inb(iobase + com_ier); 3379 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ 3380 siocntxwait(); 3381 sp->cfcr = inb(iobase + com_cfcr); 3382 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3383 sp->dlbl = inb(iobase + com_dlbl); 3384 sp->dlbh = inb(iobase + com_dlbh); 3385 /* 3386 * Only set the divisor registers if they would change, since on 3387 * some 16550 incompatibles (Startech), setting them clears the 3388 * data input register. This also reduces the effects of the 3389 * UMC8669F bug. 3390 */ 3391 divisor = ttspeedtab(comdefaultrate, comspeedtab); 3392 dlbl = divisor & 0xFF; 3393 if (sp->dlbl != dlbl) 3394 outb(iobase + com_dlbl, dlbl); 3395 dlbh = (u_int) divisor >> 8; 3396 if (sp->dlbh != dlbh) 3397 outb(iobase + com_dlbh, dlbh); 3398 outb(iobase + com_cfcr, CFCR_8BITS); 3399 sp->mcr = inb(iobase + com_mcr); 3400 /* 3401 * We don't want interrupts, but must be careful not to "disable" 3402 * them by clearing the MCR_IENABLE bit, since that might cause 3403 * an interrupt by floating the IRQ line. 3404 */ 3405 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); 3406} 3407 3408static void 3409siocnclose(sp) 3410 struct siocnstate *sp; 3411{ 3412 Port_t iobase; 3413 3414 /* 3415 * Restore the device control registers. 3416 */ 3417 siocntxwait(); 3418 iobase = siocniobase; 3419 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3420 if (sp->dlbl != inb(iobase + com_dlbl)) 3421 outb(iobase + com_dlbl, sp->dlbl); 3422 if (sp->dlbh != inb(iobase + com_dlbh)) 3423 outb(iobase + com_dlbh, sp->dlbh); 3424 outb(iobase + com_cfcr, sp->cfcr); 3425 /* 3426 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. 3427 */ 3428 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); 3429 outb(iobase + com_ier, sp->ier); 3430} 3431 3432void 3433siocnprobe(cp) 3434 struct consdev *cp; 3435{ 3436 speed_t boot_speed; 3437 u_char cfcr; 3438 struct isa_device *dvp; 3439 int s; 3440 struct siocnstate sp; 3441 3442 /* 3443 * Find our first enabled console, if any. If it is a high-level 3444 * console device, then initialize it and return successfully. 3445 * If it is a low-level console device, then initialize it and 3446 * return unsuccessfully. It must be initialized in both cases 3447 * for early use by console drivers and debuggers. Initializing 3448 * the hardware is not necessary in all cases, since the i/o 3449 * routines initialize it on the fly, but it is necessary if 3450 * input might arrive while the hardware is switched back to an 3451 * uninitialized state. We can't handle multiple console devices 3452 * yet because our low-level routines don't take a device arg. 3453 * We trust the user to set the console flags properly so that we 3454 * don't need to probe. 3455 */ 3456 cp->cn_pri = CN_DEAD; 3457 for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) 3458 if (dvp->id_driver == &siodriver && dvp->id_enabled 3459 && COM_CONSOLE(dvp)) { 3460 siocniobase = dvp->id_iobase; 3461 s = spltty(); 3462 if (boothowto & RB_SERIAL) { 3463 boot_speed = siocngetspeed(siocniobase, 3464 comspeedtab); 3465 if (boot_speed) 3466 comdefaultrate = boot_speed; 3467 } 3468 3469 /* 3470 * Initialize the divisor latch. We can't rely on 3471 * siocnopen() to do this the first time, since it 3472 * avoids writing to the latch if the latch appears 3473 * to have the correct value. Also, if we didn't 3474 * just read the speed from the hardware, then we 3475 * need to set the speed in hardware so that 3476 * switching it later is null. 3477 */ 3478 cfcr = inb(siocniobase + com_cfcr); 3479 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr); 3480 outb(siocniobase + com_dlbl, 3481 COMBRD(comdefaultrate) & 0xff); 3482 outb(siocniobase + com_dlbh, 3483 (u_int) COMBRD(comdefaultrate) >> 8); 3484 outb(siocniobase + com_cfcr, cfcr); 3485 3486 siocnopen(&sp); 3487 splx(s); 3488 if (!COM_LLCONSOLE(dvp)) { 3489 cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit); 3490 cp->cn_pri = COM_FORCECONSOLE(dvp) 3491 || boothowto & RB_SERIAL 3492 ? CN_REMOTE : CN_NORMAL; 3493 } 3494 break; 3495 } 3496} 3497 3498void 3499siocninit(cp) 3500 struct consdev *cp; 3501{ 3502 comconsole = DEV_TO_UNIT(cp->cn_dev); 3503} 3504 3505int 3506siocncheckc(dev) 3507 dev_t dev; 3508{ 3509 int c; 3510 Port_t iobase; 3511 int s; 3512 struct siocnstate sp; 3513 3514 iobase = siocniobase; 3515 s = spltty(); 3516 siocnopen(&sp); 3517 if (inb(iobase + com_lsr) & LSR_RXRDY) 3518 c = inb(iobase + com_data); 3519 else 3520 c = -1; 3521 siocnclose(&sp); 3522 splx(s); 3523 return (c); 3524} 3525 3526 3527int 3528siocngetc(dev) 3529 dev_t dev; 3530{ 3531 int c; 3532 Port_t iobase; 3533 int s; 3534 struct siocnstate sp; 3535 3536 iobase = siocniobase; 3537 s = spltty(); 3538 siocnopen(&sp); 3539 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 3540 ; 3541 c = inb(iobase + com_data); 3542 siocnclose(&sp); 3543 splx(s); 3544 return (c); 3545} 3546 3547void 3548siocnputc(dev, c) 3549 dev_t dev; 3550 int c; 3551{ 3552 int s; 3553 struct siocnstate sp; 3554 3555 s = spltty(); 3556 siocnopen(&sp); 3557 siocntxwait(); 3558 outb(siocniobase + com_data, c); 3559 siocnclose(&sp); 3560 splx(s); 3561} 3562 3563#ifdef DSI_SOFT_MODEM 3564/* 3565 * The magic code to download microcode to a "Connection 14.4+Fax" 3566 * modem from Digicom Systems Inc. Very magic. 3567 */ 3568 3569#define DSI_ERROR(str) { ptr = str; goto error; } 3570static int 3571LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr) 3572{ 3573 int int_c,int_k; 3574 int data_0188, data_0187; 3575 3576 /* 3577 * First see if it is a DSI SoftModem 3578 */ 3579 if(!((inb(base_io+7) ^ inb(base_io+7)) & 0x80)) 3580 return ENODEV; 3581 3582 data_0188 = inb(base_io+4); 3583 data_0187 = inb(base_io+3); 3584 outb(base_io+3,0x80); 3585 outb(base_io+4,0x0C); 3586 outb(base_io+0,0x31); 3587 outb(base_io+1,0x8C); 3588 outb(base_io+7,0x10); 3589 outb(base_io+7,0x19); 3590 3591 if(0x18 != (inb(base_io+7) & 0x1A)) 3592 DSI_ERROR("dsp bus not granted"); 3593 3594 if(0x01 != (inb(base_io+7) & 0x01)) { 3595 outb(base_io+7,0x18); 3596 outb(base_io+7,0x19); 3597 if(0x01 != (inb(base_io+7) & 0x01)) 3598 DSI_ERROR("program mem not granted"); 3599 } 3600 3601 int_c = 0; 3602 3603 while(1) { 3604 if(int_c >= 7 || size <= 0x1800) 3605 break; 3606 3607 for(int_k = 0 ; int_k < 0x800; int_k++) { 3608 outb(base_io+0,*ptr++); 3609 outb(base_io+1,*ptr++); 3610 outb(base_io+2,*ptr++); 3611 } 3612 3613 size -= 0x1800; 3614 int_c++; 3615 } 3616 3617 if(size > 0x1800) { 3618 outb(base_io+7,0x18); 3619 outb(base_io+7,0x19); 3620 if(0x00 != (inb(base_io+7) & 0x01)) 3621 DSI_ERROR("program data not granted"); 3622 3623 for(int_k = 0 ; int_k < 0x800; int_k++) { 3624 outb(base_io+1,*ptr++); 3625 outb(base_io+2,0); 3626 outb(base_io+1,*ptr++); 3627 outb(base_io+2,*ptr++); 3628 } 3629 3630 size -= 0x1800; 3631 3632 while(size > 0x1800) { 3633 for(int_k = 0 ; int_k < 0xC00; int_k++) { 3634 outb(base_io+1,*ptr++); 3635 outb(base_io+2,*ptr++); 3636 } 3637 size -= 0x1800; 3638 } 3639 3640 if(size < 0x1800) { 3641 for(int_k=0;int_k<size/2;int_k++) { 3642 outb(base_io+1,*ptr++); 3643 outb(base_io+2,*ptr++); 3644 } 3645 } 3646 3647 } else if (size > 0) { 3648 if(int_c == 7) { 3649 outb(base_io+7,0x18); 3650 outb(base_io+7,0x19); 3651 if(0x00 != (inb(base_io+7) & 0x01)) 3652 DSI_ERROR("program data not granted"); 3653 for(int_k = 0 ; int_k < size/3; int_k++) { 3654 outb(base_io+1,*ptr++); 3655 outb(base_io+2,0); 3656 outb(base_io+1,*ptr++); 3657 outb(base_io+2,*ptr++); 3658 } 3659 } else { 3660 for(int_k = 0 ; int_k < size/3; int_k++) { 3661 outb(base_io+0,*ptr++); 3662 outb(base_io+1,*ptr++); 3663 outb(base_io+2,*ptr++); 3664 } 3665 } 3666 } 3667 outb(base_io+7,0x11); 3668 outb(base_io+7,3); 3669 3670 outb(base_io+4,data_0188 & 0xfb); 3671 3672 outb(base_io+3,data_0187); 3673 3674 return 0; 3675error: 3676 printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",unit,ptr); 3677 outb(base_io+7,0x00); \ 3678 outb(base_io+3,data_0187); \ 3679 outb(base_io+4,data_0188); \ 3680 return EIO; 3681} 3682#endif /* DSI_SOFT_MODEM */ 3683 3684/* 3685 * support PnP cards if we are using 'em 3686 */ 3687 3688#if NPNP > 0 3689 3690static pnpid_t siopnp_ids[] = { 3691 { 0x5015f435, "MOT1550"}, 3692 { 0x8113b04e, "Supra1381"}, 3693 { 0x9012b04e, "Supra1290"}, 3694 { 0x7121b04e, "SupraExpress 56i Sp"}, 3695 { 0x11007256, "USR0011"}, 3696 { 0x30207256, "USR2030"}, 3697 { 0 } 3698}; 3699 3700static char *siopnp_probe(u_long csn, u_long vend_id); 3701static void siopnp_attach(u_long csn, u_long vend_id, char *name, 3702 struct isa_device *dev); 3703static u_long nsiopnp = NSIO; 3704 3705static struct pnp_device siopnp = { 3706 "siopnp", 3707 siopnp_probe, 3708 siopnp_attach, 3709 &nsiopnp, 3710 &tty_imask 3711}; 3712DATA_SET (pnpdevice_set, siopnp); 3713 3714static char * 3715siopnp_probe(u_long csn, u_long vend_id) 3716{ 3717 pnpid_t *id; 3718 char *s = NULL; 3719 3720 for(id = siopnp_ids; id->vend_id != 0; id++) { 3721 if (vend_id == id->vend_id) { 3722 s = id->id_str; 3723 break; 3724 } 3725 } 3726 3727 if (s) { 3728 struct pnp_cinfo d; 3729 read_pnp_parms(&d, 0); 3730 if (d.enable == 0 || d.flags & 1) { 3731 printf("CSN %lu is disabled.\n", csn); 3732 return (NULL); 3733 } 3734 3735 } 3736 3737 return (s); 3738} 3739 3740static void 3741siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) 3742{ 3743 struct pnp_cinfo d; 3744 struct isa_device *dvp; 3745 3746 if (dev->id_unit >= NSIOTOT) 3747 return; 3748 3749 if (read_pnp_parms(&d, 0) == 0) { 3750 printf("failed to read pnp parms\n"); 3751 return; 3752 } 3753 3754 write_pnp_parms(&d, 0); 3755 3756 enable_pnp_card(); 3757 3758 dev->id_iobase = d.port[0]; 3759 dev->id_irq = (1 << d.irq[0]); 3760 dev->id_intr = siointr; 3761 dev->id_ri_flags = RI_FAST; 3762 dev->id_drq = -1; 3763 3764 if (dev->id_driver == NULL) { 3765 dev->id_driver = &siodriver; 3766 dvp = find_isadev(isa_devtab_tty, &siodriver, 0); 3767 if (dvp != NULL) 3768 dev->id_id = dvp->id_id; 3769 } 3770 3771 if ((dev->id_alive = sioprobe(dev)) != 0) 3772 sioattach(dev); 3773 else 3774 printf("sio%d: probe failed\n", dev->id_unit); 3775} 3776#endif 3777#ifdef PC98 3778/* 3779 * pc98 local function 3780 */ 3781 3782static void 3783com_tiocm_set(struct com_s *com, int msr) 3784{ 3785 int s; 3786 int tmp = 0; 3787 int mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS; 3788 3789 s=spltty(); 3790 com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ) 3791 | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3792 tmp |= (CMD8251_TxEN|CMD8251_RxEN); 3793 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3794 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3795 pc98_i8251_clear_or_cmd( com, mask, tmp ); 3796 splx(s); 3797} 3798 3799static void 3800com_tiocm_bis(struct com_s *com, int msr) 3801{ 3802 int s; 3803 int tmp = 0; 3804 3805 s=spltty(); 3806 com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3807 tmp |= CMD8251_TxEN|CMD8251_RxEN; 3808 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3809 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3810 3811 pc98_i8251_or_cmd( com, tmp ); 3812 splx(s); 3813} 3814 3815static void 3816com_tiocm_bic(struct com_s *com, int msr) 3817{ 3818 int s; 3819 int tmp = msr; 3820 3821 s=spltty(); 3822 com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3823 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3824 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3825 3826 pc98_i8251_clear_cmd( com, tmp ); 3827 splx(s); 3828} 3829 3830static int 3831com_tiocm_get(struct com_s *com) 3832{ 3833 return( com->pc98_prev_modem_status ); 3834} 3835 3836static int 3837com_tiocm_get_delta(struct com_s *com) 3838{ 3839 int tmp; 3840 3841 tmp = com->pc98_modem_delta; 3842 com->pc98_modem_delta = 0; 3843 return( tmp ); 3844} 3845 3846/* convert to TIOCM_?? ( ioctl.h ) */ 3847static int 3848pc98_get_modem_status(struct com_s *com) 3849{ 3850 int stat, stat2; 3851 register int msr; 3852 3853 stat = inb(com->sts_port); 3854 stat2 = inb(com->in_modem_port); 3855 msr = com->pc98_prev_modem_status 3856 & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3857 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR; 3858 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI; 3859 if ( stat & STS8251_DSR ) msr |= TIOCM_DSR; 3860 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS; 3861#if COM_CARRIER_DETECT_EMULATE 3862 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { 3863 msr |= TIOCM_CAR; 3864 } 3865#endif 3866 return(msr); 3867} 3868 3869static void 3870pc98_check_msr(void* chan) 3871{ 3872 int msr, delta; 3873 int s; 3874 register struct tty *tp; 3875 struct com_s *com; 3876 int mynor; 3877 int unit; 3878 dev_t dev; 3879 3880 dev=(dev_t)chan; 3881 mynor = minor(dev); 3882 unit = MINOR_TO_UNIT(mynor); 3883 com = com_addr(unit); 3884 tp = com->tp; 3885 3886 s = spltty(); 3887 msr = pc98_get_modem_status(com); 3888 /* make change flag */ 3889 delta = msr ^ com->pc98_prev_modem_status; 3890 if ( delta & TIOCM_CAR ) { 3891 if ( com->modem_car_chg_timer ) { 3892 if ( -- com->modem_car_chg_timer ) 3893 msr ^= TIOCM_CAR; 3894 } else { 3895 if ( com->modem_car_chg_timer = ( msr & TIOCM_CAR ) ? 3896 DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE ) 3897 msr ^= TIOCM_CAR; 3898 } 3899 } else 3900 com->modem_car_chg_timer = 0; 3901 delta = ( msr ^ com->pc98_prev_modem_status ) & 3902 (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3903 com->pc98_prev_modem_status = msr; 3904 delta = ( com->pc98_modem_delta |= delta ); 3905 splx(s); 3906 if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) { 3907 if ( delta ) { 3908 commint(dev); 3909 } 3910 timeout(pc98_check_msr, (caddr_t)dev, 3911 PC98_CHECK_MODEM_INTERVAL); 3912 } else { 3913 com->modem_checking = 0; 3914 } 3915} 3916 3917static void 3918pc98_msrint_start(dev_t dev) 3919{ 3920 struct com_s *com; 3921 int mynor; 3922 int unit; 3923 int s = spltty(); 3924 3925 mynor = minor(dev); 3926 unit = MINOR_TO_UNIT(mynor); 3927 com = com_addr(unit); 3928 /* modem control line check routine envoke interval is 1/10 sec */ 3929 if ( com->modem_checking == 0 ) { 3930 com->pc98_prev_modem_status = pc98_get_modem_status(com); 3931 com->pc98_modem_delta = 0; 3932 timeout(pc98_check_msr, (caddr_t)dev, 3933 PC98_CHECK_MODEM_INTERVAL); 3934 com->modem_checking = 1; 3935 } 3936 splx(s); 3937} 3938 3939static void 3940pc98_disable_i8251_interrupt(struct com_s *com, int mod) 3941{ 3942 /* disable interrupt */ 3943 register int tmp; 3944 3945 mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3946 COM_INT_DISABLE 3947 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3948 outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp ); 3949 COM_INT_ENABLE 3950} 3951 3952static void 3953pc98_enable_i8251_interrupt(struct com_s *com, int mod) 3954{ 3955 register int tmp; 3956 3957 COM_INT_DISABLE 3958 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3959 outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp ); 3960 COM_INT_ENABLE 3961} 3962 3963static int 3964pc98_check_i8251_interrupt(struct com_s *com) 3965{ 3966 return ( com->intr_enable & 0x07 ); 3967} 3968 3969static void 3970pc98_i8251_clear_cmd(struct com_s *com, int x) 3971{ 3972 int tmp; 3973 3974 COM_INT_DISABLE 3975 tmp = com->pc98_prev_siocmd & ~(x); 3976 outb(com->cmd_port, tmp); 3977 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3978 COM_INT_ENABLE 3979} 3980 3981static void 3982pc98_i8251_or_cmd(struct com_s *com, int x) 3983{ 3984 int tmp; 3985 3986 COM_INT_DISABLE 3987 tmp = com->pc98_prev_siocmd | (x); 3988 outb(com->cmd_port, tmp); 3989 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3990 COM_INT_ENABLE 3991} 3992 3993static void 3994pc98_i8251_set_cmd(struct com_s *com, int x) 3995{ 3996 int tmp; 3997 3998 COM_INT_DISABLE 3999 tmp = (x); 4000 outb(com->cmd_port, tmp); 4001 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4002 COM_INT_ENABLE 4003} 4004 4005static void 4006pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x) 4007{ 4008 int tmp; 4009 COM_INT_DISABLE 4010 tmp = com->pc98_prev_siocmd & ~(clr); 4011 tmp |= (x); 4012 outb(com->cmd_port, tmp); 4013 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4014 COM_INT_ENABLE 4015} 4016 4017static int 4018pc98_i8251_get_cmd(struct com_s *com) 4019{ 4020 return com->pc98_prev_siocmd; 4021} 4022 4023static int 4024pc98_i8251_get_mod(struct com_s *com) 4025{ 4026 return com->pc98_prev_siomod; 4027} 4028 4029static void 4030pc98_i8251_reset(struct com_s *com, int mode, int command) 4031{ 4032 outb(com->cmd_port, 0); /* dummy */ 4033 DELAY(2); 4034 outb(com->cmd_port, 0); /* dummy */ 4035 DELAY(2); 4036 outb(com->cmd_port, 0); /* dummy */ 4037 DELAY(2); 4038 outb(com->cmd_port, CMD8251_RESET); /* internal reset */ 4039 DELAY(2); 4040 outb(com->cmd_port, mode ); /* mode register */ 4041 com->pc98_prev_siomod = mode; 4042 DELAY(2); 4043 pc98_i8251_set_cmd( com, (command|CMD8251_ER) ); 4044} 4045 4046static void 4047pc98_check_sysclock(void) 4048{ 4049 /* get system clock from port */ 4050 if ( pc98_machine_type & M_8M ) { 4051 /* 8 MHz system & H98 */ 4052 sysclock = 8; 4053 } else { 4054 /* 5 MHz system */ 4055 sysclock = 5; 4056 } 4057} 4058 4059static void 4060com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) 4061{ 4062 int cfcr=0, count; 4063 int previnterrupt; 4064 4065 count = pc98_ttspeedtab( com, speed ); 4066 if ( count < 0 ) return; 4067 4068 previnterrupt = pc98_check_i8251_interrupt(com); 4069 pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx ); 4070 4071 switch ( cflag&CSIZE ) { 4072 case CS5: 4073 cfcr = MOD8251_5BITS; break; 4074 case CS6: 4075 cfcr = MOD8251_6BITS; break; 4076 case CS7: 4077 cfcr = MOD8251_7BITS; break; 4078 case CS8: 4079 cfcr = MOD8251_8BITS; break; 4080 } 4081 if ( cflag&PARENB ) { 4082 if ( cflag&PARODD ) 4083 cfcr |= MOD8251_PODD; 4084 else 4085 cfcr |= MOD8251_PEVEN; 4086 } else 4087 cfcr |= MOD8251_PDISAB; 4088 4089 if ( cflag&CSTOPB ) 4090 cfcr |= MOD8251_STOP2; 4091 else 4092 cfcr |= MOD8251_STOP1; 4093 4094 if ( count & 0x10000 ) 4095 cfcr |= MOD8251_CLKX1; 4096 else 4097 cfcr |= MOD8251_CLKX16; 4098 4099 if (epson_machine_id != 0x20) { /* XXX */ 4100 { 4101 int tmp; 4102 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP)) 4103 ; 4104 } 4105 } 4106 /* set baud rate from ospeed */ 4107 pc98_set_baud_rate( com, count ); 4108 4109 if ( cfcr != pc98_i8251_get_mod(com) ) 4110 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) ); 4111 4112 pc98_enable_i8251_interrupt( com, previnterrupt ); 4113} 4114 4115static int 4116pc98_ttspeedtab(struct com_s *com, int speed) 4117{ 4118 int effect_sp, count=-1, mod; 4119 4120 switch ( com->pc98_if_type ) { 4121 case COM_IF_INTERNAL: 4122 /* for *1CLK asynchronous! mode , TEFUTEFU */ 4123 effect_sp = ttspeedtab( speed, pc98speedtab ); 4124 if ( effect_sp < 0 ) 4125 effect_sp = ttspeedtab( (speed-1), pc98speedtab ); 4126 if ( effect_sp <= 0 ) 4127 return effect_sp; 4128 mod = (sysclock == 5 ? 2457600 : 1996800); 4129 if ( effect_sp == speed ) 4130 mod /= 16; 4131 count = mod / effect_sp; 4132 if ( count > 65535 ) 4133 return(-1); 4134 if ( effect_sp >= 2400 ) 4135 if ( !(sysclock != 5 && 4136 (effect_sp == 19200 || effect_sp == 38400)) ) 4137 if ( ( mod % effect_sp ) != 0 ) 4138 return(-1); 4139 if ( effect_sp != speed ) 4140 count |= 0x10000; 4141 break; 4142#ifdef COM_IF_PC9861K 4143 case COM_IF_PC9861K: 4144 effect_sp = speed; 4145 count = 1; 4146 break; 4147#endif 4148#ifdef COM_IF_PIO9032B 4149 case COM_IF_PIO9032B: 4150 if ( speed == 0 ) return 0; 4151 count = ttspeedtab( speed, comspeedtab_pio9032b ); 4152 if ( count < 0 ) return count; 4153 effect_sp = speed; 4154 break; 4155#endif 4156#ifdef COM_IF_B98_01 4157 case COM_IF_B98_01: 4158 effect_sp=speed; 4159 count = ttspeedtab( speed, comspeedtab_b98_01 ); 4160 if ( count <= 3 ) 4161 return -1; /* invalid speed/count */ 4162 if ( count <= 5 ) 4163 count |= 0x10000; /* x1 mode for 76800 and 153600 */ 4164 else 4165 count -= 4; /* x16 mode for slower */ 4166 break; 4167#endif 4168 } 4169 return count; 4170} 4171 4172static void 4173pc98_set_baud_rate( struct com_s *com, int count) 4174{ 4175 int s; 4176 4177 switch ( com->pc98_if_type ) { 4178 case COM_IF_INTERNAL: 4179 if ( count < 0 ) { 4180 printf( "[ Illegal count : %d ]", count ); 4181 return; 4182 } else if ( count == 0) 4183 return; 4184 /* set i8253 */ 4185 s = splclock(); 4186 outb( 0x77, 0xb6 ); 4187 outb( 0x5f, 0); 4188 outb( 0x75, count & 0xff ); 4189 outb( 0x5f, 0); 4190 outb( 0x75, (count >> 8) & 0xff ); 4191 splx(s); 4192 break; 4193#if 0 4194#ifdef COM_IF_PC9861K 4195 case COM_IF_PC9861K: 4196 break; 4197 /* ext. RS232C board: speed is determined by DIP switch */ 4198#endif 4199#endif /* 0 */ 4200#ifdef COM_IF_PIO9032B 4201 case COM_IF_PIO9032B: 4202 outb( com_addr[unit], count & 0x07 ); 4203 break; 4204#endif 4205#ifdef COM_IF_B98_01 4206 case COM_IF_B98_01: 4207 outb( com->iobase, count & 0x0f ); 4208#ifdef B98_01_OLD 4209 /* some old board should be controlled in different way, 4210 but this hasn't been tested yet.*/ 4211 outb( com->iobase+2, ( count & 0x10000 ) ? 0xf0 : 0xf2 ); 4212#endif 4213 break; 4214#endif 4215 } 4216} 4217static int 4218pc98_check_if_type( int iobase, struct siodev *iod) 4219{ 4220 int irr = 0, tmp = 0; 4221 int ret = 0; 4222 static short irq_tab[2][8] = { 4223 { 3, 5, 6, 9, 10, 12, 13, -1}, 4224 { 3, 10, 12, 13, 5, 6, 9, -1} 4225 }; 4226 iod->irq = 0; 4227 switch ( iobase & 0xff ) { 4228 case IO_COM1: 4229 iod->if_type = COM_IF_INTERNAL; 4230 ret = 0; iod->irq = 4; break; 4231#ifdef COM_IF_PC9861K 4232 case IO_COM2: 4233 iod->if_type = COM_IF_PC9861K; 4234 ret = 1; irr = 0; tmp = 3; break; 4235 case IO_COM3: 4236 iod->if_type = COM_IF_PC9861K; 4237 ret = 2; irr = 1; tmp = 3; break; 4238#endif 4239#ifdef COM_IF_PIO9032B 4240 case IO_COM_PIO9032B_2: 4241 iod->if_type = COM_IF_PIO9032B; 4242 ret = 1; irr = 0; tmp = 7; break; 4243 case IO_COM_PIO9032B_3: 4244 iod->if_type = COM_IF_PIO9032B; 4245 ret = 2; irr = 1; tmp = 7; break; 4246#endif 4247#ifdef COM_IF_B98_01 4248 case IO_COM_B98_01_2: 4249 iod->if_type = COM_IF_B98_01; 4250 ret = 1; irr = 0; tmp = 7; 4251 outb(iobase + 2, 0xf2); 4252 outb(iobase, 4); 4253 break; 4254 case IO_COM_B98_01_3: 4255 iod->if_type = COM_IF_B98_01; 4256 ret = 2; irr = 1; tmp = 7; 4257 outb(iobase + 2, 0xf2); 4258 outb(iobase , 4); 4259 break; 4260#endif 4261 default: 4262 if((iobase & 0x0f0) == 0xd0){ 4263 iod->if_type = MC16550; 4264 return 0; 4265 } 4266 return -1; 4267 } 4268 4269 iod->cmd = ( iobase & 0xff00 )|PC98SIO_cmd_port(ret); 4270 iod->sts = ( iobase & 0xff00 )|PC98SIO_sts_port(ret); 4271 iod->mod = ( iobase & 0xff00 )|PC98SIO_in_modem_port(ret); 4272 iod->ctrl = ( iobase & 0xff00 )|PC98SIO_intr_ctrl_port(ret); 4273 4274 if ( iod->irq == 0 ) { 4275 tmp &= inb( iod->mod ); 4276 iod->irq = irq_tab[irr][tmp]; 4277 if ( iod->irq == -1 ) return -1; 4278 } 4279 return 0; 4280} 4281static int 4282pc98_set_ioport( struct com_s *com, int io_base ) 4283{ 4284 int a, io, type; 4285 4286 switch ( io_base & 0xff ) { 4287 case IO_COM1: a = 0; io = 0; type = COM_IF_INTERNAL; 4288 pc98_check_sysclock(); break; 4289#ifdef COM_IF_PC9861K 4290 case IO_COM2: a = 1; io = 0; type = COM_IF_PC9861K; break; 4291 case IO_COM3: a = 2; io = 0; type = COM_IF_PC9861K; break; 4292#endif /* COM_IF_PC9861K */ 4293#ifdef COM_IF_PIO9032B 4294 /* PIO9032B : I/O address is changeable */ 4295 case IO_COM_PIO9032B_2: 4296 a = 1; io = io_base & 0xff00; 4297 type = COM_IF_PIO9032B; break; 4298 case IO_COM_PIO9032B_3: 4299 a = 2; io = io_base & 0xff00; 4300 type = COM_IF_PIO9032B; break; 4301#endif /* COM_IF_PIO9032B */ 4302#ifdef COM_IF_B98_01 4303 case IO_COM_B98_01_2: 4304 a = 1; io = 0; type = COM_IF_B98_01; break; 4305 case IO_COM_B98_01_3: 4306 a = 2; io = 0; type = COM_IF_B98_01; break; 4307#endif /* COM_IF_B98_01*/ 4308 default: /* i/o address not match */ 4309 return -1; 4310 } 4311 4312 com->pc98_if_type = type; 4313 com->data_port = io | PC98SIO_data_port(a); 4314 com->cmd_port = io | PC98SIO_cmd_port(a); 4315 com->sts_port = io | PC98SIO_sts_port(a); 4316 com->in_modem_port = io | PC98SIO_in_modem_port(a); 4317 com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(a); 4318 return 0; 4319} 4320#endif /* PC98 defined */ 4321