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