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