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