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