sio.c revision 22200
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 * $FreeBSD: head/sys/pc98/cbus/sio.c 22200 1997-02-02 08:09:41Z kato $ 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 /* 1257 * Set 16550 compatibility mode. 1258 * We don't use the ESP_MODE_SCALE bit to increase the 1259 * fifo trigger levels because we can't handle large 1260 * bursts of input. 1261 * XXX flow control should be set in comparam(), not here. 1262 */ 1263 outb(com->esp_port + ESP_CMD1, ESP_SETMODE); 1264 outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); 1265 1266 /* Set RTS/CTS flow control. */ 1267 outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE); 1268 outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS); 1269 outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS); 1270 1271 /* Set flow-control levels. */ 1272 outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW); 1273 outb(com->esp_port + ESP_CMD2, HIBYTE(768)); 1274 outb(com->esp_port + ESP_CMD2, LOBYTE(768)); 1275 outb(com->esp_port + ESP_CMD2, HIBYTE(512)); 1276 outb(com->esp_port + ESP_CMD2, LOBYTE(512)); 1277 } 1278#endif /* COM_ESP */ 1279 outb(iobase + com_fifo, 0); 1280determined_type: ; 1281 1282#ifdef COM_MULTIPORT 1283 if (COM_ISMULTIPORT(isdp)) { 1284 com->multiport = TRUE; 1285 printf(" (multiport"); 1286 if (unit == COM_MPMASTER(isdp)) 1287 printf(" master"); 1288 printf(")"); 1289 com->no_irq = find_isadev(isa_devtab_tty, &siodriver, 1290 COM_MPMASTER(isdp))->id_irq == 0; 1291 } 1292#endif /* COM_MULTIPORT */ 1293#ifdef PC98 1294 } 1295#endif 1296 printf("\n"); 1297 1298 s = spltty(); 1299 com_addr(unit) = com; 1300 splx(s); 1301 1302 dev = makedev(CDEV_MAJOR, 0); 1303 cdevsw_add(&dev, &sio_cdevsw, NULL); 1304#ifdef DEVFS 1305 com->devfs_token_ttyd = devfs_add_devswf(&sio_cdevsw, 1306 unit, DV_CHR, 1307 UID_ROOT, GID_WHEEL, 0600, "ttyd%n", unit); 1308 com->devfs_token_ttyi = devfs_add_devswf(&sio_cdevsw, 1309 unit | CONTROL_INIT_STATE, DV_CHR, 1310 UID_ROOT, GID_WHEEL, 0600, "ttyid%n", unit); 1311 com->devfs_token_ttyl = devfs_add_devswf(&sio_cdevsw, 1312 unit | CONTROL_LOCK_STATE, DV_CHR, 1313 UID_ROOT, GID_WHEEL, 0600, "ttyld%n", unit); 1314 com->devfs_token_cuaa = devfs_add_devswf(&sio_cdevsw, 1315 unit | CALLOUT_MASK, DV_CHR, 1316 UID_UUCP, GID_DIALER, 0660, "cuaa%n", unit); 1317 com->devfs_token_cuai = devfs_add_devswf(&sio_cdevsw, 1318 unit | CALLOUT_MASK | CONTROL_INIT_STATE, DV_CHR, 1319 UID_UUCP, GID_DIALER, 0660, "cuaia%n", unit); 1320 com->devfs_token_cual = devfs_add_devswf(&sio_cdevsw, 1321 unit | CALLOUT_MASK | CONTROL_LOCK_STATE, DV_CHR, 1322 UID_UUCP, GID_DIALER, 0660, "cuala%n", unit); 1323#endif 1324 return (1); 1325} 1326 1327static int 1328sioopen(dev, flag, mode, p) 1329 dev_t dev; 1330 int flag; 1331 int mode; 1332 struct proc *p; 1333{ 1334 struct com_s *com; 1335 int error; 1336 Port_t iobase; 1337 int mynor; 1338 int s; 1339 struct tty *tp; 1340 int unit; 1341 1342 mynor = minor(dev); 1343 unit = MINOR_TO_UNIT(mynor); 1344 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) 1345 return (ENXIO); 1346 if (com->gone) 1347 return (ENXIO); 1348 if (mynor & CONTROL_MASK) 1349 return (0); 1350#if 0 /* XXX */ 1351 tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]); 1352#else 1353 tp = com->tp = &sio_tty[unit]; 1354#endif 1355 s = spltty(); 1356 /* 1357 * We jump to this label after all non-interrupted sleeps to pick 1358 * up any changes of the device state. 1359 */ 1360open_top: 1361 while (com->state & CS_DTR_OFF) { 1362 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0); 1363 if (com_addr(unit) == NULL) 1364 return (ENXIO); 1365 if (error != 0 || com->gone) 1366 goto out; 1367 } 1368 if (tp->t_state & TS_ISOPEN) { 1369 /* 1370 * The device is open, so everything has been initialized. 1371 * Handle conflicts. 1372 */ 1373 if (mynor & CALLOUT_MASK) { 1374 if (!com->active_out) { 1375 error = EBUSY; 1376 goto out; 1377 } 1378 } else { 1379 if (com->active_out) { 1380 if (flag & O_NONBLOCK) { 1381 error = EBUSY; 1382 goto out; 1383 } 1384 error = tsleep(&com->active_out, 1385 TTIPRI | PCATCH, "siobi", 0); 1386 if (com_addr(unit) == NULL) 1387 return (ENXIO); 1388 if (error != 0 || com->gone) 1389 goto out; 1390 goto open_top; 1391 } 1392 } 1393 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { 1394 error = EBUSY; 1395 goto out; 1396 } 1397 } else { 1398 /* 1399 * The device isn't open, so there are no conflicts. 1400 * Initialize it. Initialization is done twice in many 1401 * cases: to preempt sleeping callin opens if we are 1402 * callout, and to complete a callin open after DCD rises. 1403 */ 1404 tp->t_oproc = comstart; 1405 tp->t_param = comparam; 1406 tp->t_dev = dev; 1407 tp->t_termios = mynor & CALLOUT_MASK 1408 ? com->it_out : com->it_in; 1409#ifdef PC98 1410 if(!IS_8251(com->pc98_if_type)) 1411#endif 1412 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 1413 com->poll = com->no_irq; 1414 com->poll_output = com->loses_outints; 1415 ++com->wopeners; 1416 error = comparam(tp, &tp->t_termios); 1417 --com->wopeners; 1418 if (error != 0) 1419 goto out; 1420#ifdef PC98 1421 if(IS_8251(com->pc98_if_type)){ 1422 com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS); 1423 pc98_msrint_start(dev); 1424 } 1425#endif 1426 /* 1427 * XXX we should goto open_top if comparam() slept. 1428 */ 1429 ttsetwater(tp); 1430 iobase = com->iobase; 1431 if (com->hasfifo) { 1432 /* 1433 * (Re)enable and drain fifos. 1434 * 1435 * Certain SMC chips cause problems if the fifos 1436 * are enabled while input is ready. Turn off the 1437 * fifo if necessary to clear the input. We test 1438 * the input ready bit after enabling the fifos 1439 * since we've already enabled them in comparam() 1440 * and to handle races between enabling and fresh 1441 * input. 1442 */ 1443 while (TRUE) { 1444 outb(iobase + com_fifo, 1445 FIFO_RCV_RST | FIFO_XMT_RST 1446 | com->fifo_image); 1447 /* 1448 * XXX the delays are for superstitious 1449 * historical reasons. It must be less than 1450 * the character time at the maximum 1451 * supported speed (87 usec at 115200 bps 1452 * 8N1). Otherwise we might loop endlessly 1453 * if data is streaming in. We used to use 1454 * delays of 100. That usually worked 1455 * because DELAY(100) used to usually delay 1456 * for about 85 usec instead of 100. 1457 */ 1458 DELAY(50); 1459 if (!(inb(com->line_status_port) & LSR_RXRDY)) 1460 break; 1461 outb(iobase + com_fifo, 0); 1462 DELAY(50); 1463 (void) inb(com->data_port); 1464 } 1465 } 1466 1467 disable_intr(); 1468#ifdef PC98 1469 if(IS_8251(com->pc98_if_type)){ 1470 com_tiocm_bis(com, TIOCM_LE); 1471 com->pc98_prev_modem_status = 1472 pc98_get_modem_status(com); 1473 com_int_Rx_enable(com); 1474 } else { 1475#endif 1476 (void) inb(com->line_status_port); 1477 (void) inb(com->data_port); 1478 com->prev_modem_status = com->last_modem_status 1479 = inb(com->modem_status_port); 1480 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS 1481 | IER_EMSC); 1482#ifdef PC98 1483 } 1484#endif 1485 enable_intr(); 1486 /* 1487 * Handle initial DCD. Callout devices get a fake initial 1488 * DCD (trapdoor DCD). If we are callout, then any sleeping 1489 * callin opens get woken up and resume sleeping on "siobi" 1490 * instead of "siodcd". 1491 */ 1492 /* 1493 * XXX `mynor & CALLOUT_MASK' should be 1494 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 1495 * TRAPDOOR_CARRIER is the default initial state for callout 1496 * devices and SOFT_CARRIER is like CLOCAL except it hides 1497 * the true carrier. 1498 */ 1499#ifdef PC98 1500 if ((IS_8251(com->pc98_if_type) && 1501 (pc98_get_modem_status(com) & TIOCM_CAR)) || 1502 (!IS_8251(com->pc98_if_type) && 1503 (com->prev_modem_status & MSR_DCD)) || 1504 mynor & CALLOUT_MASK) 1505#else 1506 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 1507#endif 1508 (*linesw[tp->t_line].l_modem)(tp, 1); 1509 } 1510 /* 1511 * Wait for DCD if necessary. 1512 */ 1513 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 1514 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 1515 ++com->wopeners; 1516 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0); 1517 if (com_addr(unit) == NULL) 1518 return (ENXIO); 1519 --com->wopeners; 1520 if (error != 0 || com->gone) 1521 goto out; 1522 goto open_top; 1523 } 1524 error = (*linesw[tp->t_line].l_open)(dev, tp); 1525 disc_optim(tp, &tp->t_termios, com); 1526 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 1527 com->active_out = TRUE; 1528 siosettimeout(); 1529out: 1530 splx(s); 1531 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 1532 comhardclose(com); 1533 return (error); 1534} 1535 1536static int 1537sioclose(dev, flag, mode, p) 1538 dev_t dev; 1539 int flag; 1540 int mode; 1541 struct proc *p; 1542{ 1543 struct com_s *com; 1544 int mynor; 1545 int s; 1546 struct tty *tp; 1547 1548 mynor = minor(dev); 1549 if (mynor & CONTROL_MASK) 1550 return (0); 1551 com = com_addr(MINOR_TO_UNIT(mynor)); 1552 tp = com->tp; 1553 s = spltty(); 1554 (*linesw[tp->t_line].l_close)(tp, flag); 1555#ifdef PC98 1556 com->modem_checking = 0; 1557#endif 1558 disc_optim(tp, &tp->t_termios, com); 1559 siostop(tp, FREAD | FWRITE); 1560 comhardclose(com); 1561 ttyclose(tp); 1562 siosettimeout(); 1563 splx(s); 1564 if (com->gone) { 1565 printf("sio%d: gone\n", com->unit); 1566 s = spltty(); 1567 com_addr(com->unit) = 0; 1568 bzero(tp,sizeof *tp); 1569 bzero(com,sizeof *com); 1570 free(com,M_TTYS); 1571 splx(s); 1572 } 1573 return (0); 1574} 1575 1576static void 1577comhardclose(com) 1578 struct com_s *com; 1579{ 1580 Port_t iobase; 1581 int s; 1582 struct tty *tp; 1583 int unit; 1584 1585 unit = com->unit; 1586 iobase = com->iobase; 1587 s = spltty(); 1588 com->poll = FALSE; 1589 com->poll_output = FALSE; 1590 com->do_timestamp = FALSE; 1591 com->do_dcd_timestamp = FALSE; 1592#ifdef PC98 1593 if(IS_8251(com->pc98_if_type)) 1594 com_send_break_off(com); 1595 else 1596#endif 1597 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1598 { 1599#ifdef PC98 1600 int tmp; 1601 if(IS_8251(com->pc98_if_type)) 1602 com_int_TxRx_disable(com); 1603 else 1604#endif 1605 outb(iobase + com_ier, 0); 1606 tp = com->tp; 1607#ifdef PC98 1608 if(IS_8251(com->pc98_if_type)) 1609 tmp = pc98_get_modem_status(com) & TIOCM_CAR; 1610 else 1611 tmp = com->prev_modem_status & MSR_DCD; 1612#endif 1613 if (tp->t_cflag & HUPCL 1614 /* 1615 * XXX we will miss any carrier drop between here and the 1616 * next open. Perhaps we should watch DCD even when the 1617 * port is closed; it is not sufficient to check it at 1618 * the next open because it might go up and down while 1619 * we're not watching. 1620 */ 1621 || !com->active_out 1622#ifdef PC98 1623 && !(tmp) 1624#else 1625 && !(com->prev_modem_status & MSR_DCD) 1626#endif 1627 && !(com->it_in.c_cflag & CLOCAL) 1628 || !(tp->t_state & TS_ISOPEN)) { 1629#ifdef PC98 1630 if(IS_8251(com->pc98_if_type)) 1631 com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE); 1632 else 1633#endif 1634 (void)commctl(com, TIOCM_DTR, DMBIC); 1635 if (com->dtr_wait != 0) { 1636 timeout(siodtrwakeup, com, com->dtr_wait); 1637 com->state |= CS_DTR_OFF; 1638 } 1639 } 1640#ifdef PC98 1641 else { 1642 if(IS_8251(com->pc98_if_type)) 1643 com_tiocm_bic(com, TIOCM_LE ); 1644 } 1645#endif 1646 } 1647 if (com->hasfifo) { 1648 /* 1649 * Disable fifos so that they are off after controlled 1650 * reboots. Some BIOSes fail to detect 16550s when the 1651 * fifos are enabled. 1652 */ 1653 outb(iobase + com_fifo, 0); 1654 } 1655 com->active_out = FALSE; 1656 wakeup(&com->active_out); 1657 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 1658 splx(s); 1659} 1660 1661static int 1662sioread(dev, uio, flag) 1663 dev_t dev; 1664 struct uio *uio; 1665 int flag; 1666{ 1667 int mynor; 1668 int unit; 1669 struct tty *tp; 1670 1671 mynor = minor(dev); 1672 if (mynor & CONTROL_MASK) 1673 return (ENODEV); 1674 unit = MINOR_TO_UNIT(mynor); 1675 if (com_addr(unit)->gone) 1676 return (ENODEV); 1677 tp = com_addr(unit)->tp; 1678 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 1679} 1680 1681static int 1682siowrite(dev, uio, flag) 1683 dev_t dev; 1684 struct uio *uio; 1685 int flag; 1686{ 1687 int mynor; 1688 struct tty *tp; 1689 int unit; 1690 1691 mynor = minor(dev); 1692 if (mynor & CONTROL_MASK) 1693 return (ENODEV); 1694 1695 unit = MINOR_TO_UNIT(mynor); 1696 if (com_addr(unit)->gone) 1697 return (ENODEV); 1698 tp = com_addr(unit)->tp; 1699 /* 1700 * (XXX) We disallow virtual consoles if the physical console is 1701 * a serial port. This is in case there is a display attached that 1702 * is not the console. In that situation we don't need/want the X 1703 * server taking over the console. 1704 */ 1705 if (constty != NULL && unit == comconsole) 1706 constty = NULL; 1707 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1708} 1709 1710static void 1711siobusycheck(chan) 1712 void *chan; 1713{ 1714 struct com_s *com; 1715 int s; 1716 1717 com = (struct com_s *)chan; 1718 1719 /* 1720 * Clear TS_BUSY if low-level output is complete. 1721 * spl locking is sufficient because siointr1() does not set CS_BUSY. 1722 * If siointr() clears CS_BUSY after we look at it, then we'll get 1723 * called again. Reading the line status port outside of siointr1() 1724 * is safe because CS_BUSY is clear so there are no output interrupts 1725 * to lose. 1726 */ 1727 s = spltty(); 1728 if (com->state & CS_BUSY) 1729 ; /* False alarm. */ 1730 else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 1731 == (LSR_TSRE | LSR_TXRDY)) { 1732 com->tp->t_state &= ~TS_BUSY; 1733 ttwwakeup(com->tp); 1734 } else 1735 timeout(siobusycheck, com, hz / 100); 1736 splx(s); 1737} 1738 1739static void 1740siodtrwakeup(chan) 1741 void *chan; 1742{ 1743 struct com_s *com; 1744 1745 com = (struct com_s *)chan; 1746 com->state &= ~CS_DTR_OFF; 1747 wakeup(&com->dtr_wait); 1748} 1749 1750void 1751siointr(unit) 1752 int unit; 1753{ 1754#ifndef COM_MULTIPORT 1755 siointr1(com_addr(unit)); 1756#else /* COM_MULTIPORT */ 1757 struct com_s *com; 1758 bool_t possibly_more_intrs; 1759 1760 /* 1761 * Loop until there is no activity on any port. This is necessary 1762 * to get an interrupt edge more than to avoid another interrupt. 1763 * If the IRQ signal is just an OR of the IRQ signals from several 1764 * devices, then the edge from one may be lost because another is 1765 * on. 1766 */ 1767 do { 1768 possibly_more_intrs = FALSE; 1769 for (unit = 0; unit < NSIO; ++unit) { 1770 com = com_addr(unit); 1771#ifdef PC98 1772 if (com != NULL 1773 && !com->gone 1774 && IS_8251(com->pc98_if_type)){ 1775 siointr1(com); 1776 } else 1777#endif /* PC98 */ 1778 if (com != NULL 1779 && !com->gone 1780 && (inb(com->int_id_port) & IIR_IMASK) 1781 != IIR_NOPEND) { 1782 siointr1(com); 1783 possibly_more_intrs = TRUE; 1784 } 1785 } 1786 } while (possibly_more_intrs); 1787#endif /* COM_MULTIPORT */ 1788} 1789 1790static void 1791siointr1(com) 1792 struct com_s *com; 1793{ 1794 u_char line_status; 1795 u_char modem_status; 1796 u_char *ioptr; 1797 u_char recv_data; 1798#ifdef PC98 1799 u_char tmp=0; 1800recv_data=0; 1801#endif /* PC98 */ 1802 1803 while (TRUE) { 1804#ifdef PC98 1805status_read:; 1806 if (IS_8251(com->pc98_if_type)) { 1807 tmp = inb(com->sts_port); 1808more_intr: 1809 line_status = 0; 1810 if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY; 1811 if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY; 1812 if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE; 1813 if (tmp & STS8251_PE) line_status |= LSR_PE; 1814 if (tmp & STS8251_OE) line_status |= LSR_OE; 1815 if (tmp & STS8251_FE) line_status |= LSR_FE; 1816 if (tmp & STS8251_BD_SD) line_status |= LSR_BI; 1817 } else 1818#endif /* PC98 */ 1819 line_status = inb(com->line_status_port); 1820 1821 /* input event? (check first to help avoid overruns) */ 1822 while (line_status & LSR_RCV_MASK) { 1823 /* break/unnattached error bits or real input? */ 1824#ifdef PC98 1825 if(IS_8251(com->pc98_if_type)){ 1826 recv_data = inb(com->data_port); 1827 if(tmp & 0x78){ 1828 pc98_i8251_or_cmd(com,CMD8251_ER); 1829 recv_data = 0; 1830 } 1831 } else { 1832#endif /* PC98 */ 1833 if (!(line_status & LSR_RXRDY)) 1834 recv_data = 0; 1835 else 1836 recv_data = inb(com->data_port); 1837#ifdef PC98 1838 } 1839#endif 1840 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) { 1841 /* 1842 * Don't store BI if IGNBRK or FE/PE if IGNPAR. 1843 * Otherwise, push the work to a higher level 1844 * (to handle PARMRK) if we're bypassing. 1845 * Otherwise, convert BI/FE and PE+INPCK to 0. 1846 * 1847 * This makes bypassing work right in the 1848 * usual "raw" case (IGNBRK set, and IGNPAR 1849 * and INPCK clear). 1850 * 1851 * Note: BI together with FE/PE means just BI. 1852 */ 1853 if (line_status & LSR_BI) { 1854#if defined(DDB) && defined(BREAK_TO_DEBUGGER) 1855 if (com->unit == comconsole) { 1856 breakpoint(); 1857 goto cont; 1858 } 1859#endif 1860 if (com->tp == NULL 1861 || com->tp->t_iflag & IGNBRK) 1862 goto cont; 1863 } else { 1864 if (com->tp == NULL 1865 || com->tp->t_iflag & IGNPAR) 1866 goto cont; 1867 } 1868 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT 1869 && (line_status & (LSR_BI | LSR_FE) 1870 || com->tp->t_iflag & INPCK)) 1871 recv_data = 0; 1872 } 1873 1874 ++com->bytes_in; 1875 if (com->hotchar != 0 && recv_data == com->hotchar) 1876 setsofttty(); 1877 ioptr = com->iptr; 1878 if (ioptr >= com->ibufend) 1879 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1880 else { 1881 if (com->do_timestamp) 1882 microtime(&com->timestamp); 1883 ++com_events; 1884 schedsofttty(); 1885#if 0 /* for testing input latency vs efficiency */ 1886if (com->iptr - com->ibuf == 8) 1887 setsofttty(); 1888#endif 1889 ioptr[0] = recv_data; 1890 ioptr[CE_INPUT_OFFSET] = line_status; 1891 com->iptr = ++ioptr; 1892 if (ioptr == com->ihighwater 1893 && com->state & CS_RTS_IFLOW) 1894#ifdef PC98 1895 if(IS_8251(com->pc98_if_type)) 1896 com_tiocm_bic(com, TIOCM_RTS); 1897 else 1898#endif 1899 outb(com->modem_ctl_port, 1900 com->mcr_image &= ~MCR_RTS); 1901 if (line_status & LSR_OE) 1902 CE_RECORD(com, CE_OVERRUN); 1903 } 1904cont: 1905 /* 1906 * "& 0x7F" is to avoid the gcc-1.40 generating a slow 1907 * jump from the top of the loop to here 1908 */ 1909#ifdef PC98 1910 if(IS_8251(com->pc98_if_type)) 1911 goto status_read; 1912 else 1913#endif 1914 line_status = inb(com->line_status_port) & 0x7F; 1915 } 1916 1917 /* modem status change? (always check before doing output) */ 1918#ifdef PC98 1919 if(!IS_8251(com->pc98_if_type)){ 1920#endif 1921 modem_status = inb(com->modem_status_port); 1922 if (modem_status != com->last_modem_status) { 1923 if (com->do_dcd_timestamp 1924 && !(com->last_modem_status & MSR_DCD) 1925 && modem_status & MSR_DCD) 1926 microtime(&com->dcd_timestamp); 1927 1928 /* 1929 * Schedule high level to handle DCD changes. Note 1930 * that we don't use the delta bits anywhere. Some 1931 * UARTs mess them up, and it's easy to remember the 1932 * previous bits and calculate the delta. 1933 */ 1934 com->last_modem_status = modem_status; 1935 if (!(com->state & CS_CHECKMSR)) { 1936 com_events += LOTS_OF_EVENTS; 1937 com->state |= CS_CHECKMSR; 1938 setsofttty(); 1939 } 1940 1941 /* handle CTS change immediately for crisp flow ctl */ 1942 if (com->state & CS_CTS_OFLOW) { 1943 if (modem_status & MSR_CTS) 1944 com->state |= CS_ODEVREADY; 1945 else 1946 com->state &= ~CS_ODEVREADY; 1947 } 1948 } 1949#ifdef PC98 1950 } 1951#endif 1952 1953 /* output queued and everything ready? */ 1954 if (line_status & LSR_TXRDY 1955 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1956 ioptr = com->obufq.l_head; 1957 if (com->tx_fifo_size > 1) { 1958 u_int ocount; 1959 1960 ocount = com->obufq.l_tail - ioptr; 1961 if (ocount > com->tx_fifo_size) 1962 ocount = com->tx_fifo_size; 1963 com->bytes_out += ocount; 1964 do 1965 outb(com->data_port, *ioptr++); 1966 while (--ocount != 0); 1967 } else { 1968 outb(com->data_port, *ioptr++); 1969 ++com->bytes_out; 1970 } 1971#ifdef PC98 1972 if(IS_8251(com->pc98_if_type)) 1973 if ( !(pc98_check_i8251_interrupt(com) & IEN_TxFLAG) ) 1974 com_int_Tx_enable(com); 1975#endif 1976 com->obufq.l_head = ioptr; 1977 if (ioptr >= com->obufq.l_tail) { 1978 struct lbq *qp; 1979 1980 qp = com->obufq.l_next; 1981 qp->l_queued = FALSE; 1982 qp = qp->l_next; 1983 if (qp != NULL) { 1984 com->obufq.l_head = qp->l_head; 1985 com->obufq.l_tail = qp->l_tail; 1986 com->obufq.l_next = qp; 1987 } else { 1988 /* output just completed */ 1989 com->state &= ~CS_BUSY; 1990#if defined(PC98) 1991 if(IS_8251(com->pc98_if_type)) 1992 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 1993 com_int_Tx_disable(com); 1994#endif 1995 } 1996 if (!(com->state & CS_ODONE)) { 1997 com_events += LOTS_OF_EVENTS; 1998 com->state |= CS_ODONE; 1999 setsofttty(); /* handle at high level ASAP */ 2000 } 2001 } 2002 } 2003#ifdef PC98 2004 else if (line_status & LSR_TXRDY) { 2005 if(IS_8251(com->pc98_if_type)) 2006 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2007 com_int_Tx_disable(com); 2008 } 2009 if(IS_8251(com->pc98_if_type)) 2010 if ((tmp = inb(com->sts_port)) & STS8251_RxRDY) 2011 goto more_intr; 2012#endif 2013 2014 /* finished? */ 2015#ifndef COM_MULTIPORT 2016#ifdef PC98 2017 if(IS_8251(com->pc98_if_type)) 2018 return; 2019#endif 2020 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) 2021#endif /* COM_MULTIPORT */ 2022 return; 2023 } 2024} 2025 2026static int 2027sioioctl(dev, cmd, data, flag, p) 2028 dev_t dev; 2029 int cmd; 2030 caddr_t data; 2031 int flag; 2032 struct proc *p; 2033{ 2034 struct com_s *com; 2035 int error; 2036 Port_t iobase; 2037 int mynor; 2038 int s; 2039 struct tty *tp; 2040#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2041 int oldcmd; 2042 struct termios term; 2043#endif 2044 2045 mynor = minor(dev); 2046 com = com_addr(MINOR_TO_UNIT(mynor)); 2047 if (com->gone) 2048 return (ENODEV); 2049 iobase = com->iobase; 2050 if (mynor & CONTROL_MASK) { 2051 struct termios *ct; 2052 2053 switch (mynor & CONTROL_MASK) { 2054 case CONTROL_INIT_STATE: 2055 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 2056 break; 2057 case CONTROL_LOCK_STATE: 2058 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 2059 break; 2060 default: 2061 return (ENODEV); /* /dev/nodev */ 2062 } 2063 switch (cmd) { 2064 case TIOCSETA: 2065 error = suser(p->p_ucred, &p->p_acflag); 2066 if (error != 0) 2067 return (error); 2068 *ct = *(struct termios *)data; 2069 return (0); 2070 case TIOCGETA: 2071 *(struct termios *)data = *ct; 2072 return (0); 2073 case TIOCGETD: 2074 *(int *)data = TTYDISC; 2075 return (0); 2076 case TIOCGWINSZ: 2077 bzero(data, sizeof(struct winsize)); 2078 return (0); 2079#ifdef DSI_SOFT_MODEM 2080 /* 2081 * Download micro-code to Digicom modem. 2082 */ 2083 case TIOCDSIMICROCODE: 2084 { 2085 u_long l; 2086 u_char *p,*pi; 2087 2088 pi = (u_char*)(*(caddr_t*)data); 2089 error = copyin(pi,&l,sizeof l); 2090 if(error) 2091 {return error;}; 2092 pi += sizeof l; 2093 2094 p = malloc(l,M_TEMP,M_NOWAIT); 2095 if(!p) 2096 {return ENOBUFS;} 2097 error = copyin(pi,p,l); 2098 if(error) 2099 {free(p,M_TEMP); return error;}; 2100 if(error = LoadSoftModem( 2101 MINOR_TO_UNIT(mynor),iobase,l,p)) 2102 {free(p,M_TEMP); return error;} 2103 free(p,M_TEMP); 2104 return(0); 2105 } 2106#endif /* DSI_SOFT_MODEM */ 2107 default: 2108 return (ENOTTY); 2109 } 2110 } 2111 tp = com->tp; 2112#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2113 term = tp->t_termios; 2114 oldcmd = cmd; 2115 error = ttsetcompat(tp, &cmd, data, &term); 2116 if (error != 0) 2117 return (error); 2118 if (cmd != oldcmd) 2119 data = (caddr_t)&term; 2120#endif 2121 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 2122 int cc; 2123 struct termios *dt = (struct termios *)data; 2124 struct termios *lt = mynor & CALLOUT_MASK 2125 ? &com->lt_out : &com->lt_in; 2126 2127 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 2128 | (dt->c_iflag & ~lt->c_iflag); 2129 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 2130 | (dt->c_oflag & ~lt->c_oflag); 2131 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 2132 | (dt->c_cflag & ~lt->c_cflag); 2133 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 2134 | (dt->c_lflag & ~lt->c_lflag); 2135 for (cc = 0; cc < NCCS; ++cc) 2136 if (lt->c_cc[cc] != 0) 2137 dt->c_cc[cc] = tp->t_cc[cc]; 2138 if (lt->c_ispeed != 0) 2139 dt->c_ispeed = tp->t_ispeed; 2140 if (lt->c_ospeed != 0) 2141 dt->c_ospeed = tp->t_ospeed; 2142 } 2143 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 2144 if (error >= 0) 2145 return (error); 2146 s = spltty(); 2147 error = ttioctl(tp, cmd, data, flag); 2148 disc_optim(tp, &tp->t_termios, com); 2149 if (error >= 0) { 2150 splx(s); 2151 return (error); 2152 } 2153#ifdef PC98 2154 if(IS_8251(com->pc98_if_type)){ 2155 switch (cmd) { 2156 case TIOCSBRK: 2157 com_send_break_on( com ); 2158 break; 2159 case TIOCCBRK: 2160 com_send_break_off( com ); 2161 break; 2162 case TIOCSDTR: 2163 (void)commctl(com, TIOCM_DTR, DMBIS); 2164 break; 2165 case TIOCCDTR: 2166 (void)commctl(com, TIOCM_DTR, DMBIC); 2167 break; 2168 /* 2169 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2170 * changes get undone on the next call to comparam(). 2171 */ 2172 case TIOCMSET: 2173 (void)commctl(com, *(int *)data, DMSET); 2174 break; 2175 case TIOCMBIS: 2176 (void)commctl(com, *(int *)data, DMBIS); 2177 break; 2178 case TIOCMBIC: 2179 (void)commctl(com, *(int *)data, DMBIC); 2180 break; 2181 case TIOCMGET: 2182 *(int *)data = commctl(com, 0, DMGET); 2183 break; 2184 case TIOCMSDTRWAIT: 2185 /* must be root since the wait applies to following logins */ 2186 error = suser(p->p_ucred, &p->p_acflag); 2187 if (error != 0) { 2188 splx(s); 2189 return (error); 2190 } 2191 com->dtr_wait = *(int *)data * hz / 100; 2192 break; 2193 case TIOCMGDTRWAIT: 2194 *(int *)data = com->dtr_wait * 100 / hz; 2195 break; 2196 case TIOCTIMESTAMP: 2197 com->do_timestamp = TRUE; 2198 *(struct timeval *)data = com->timestamp; 2199 break; 2200 case TIOCDCDTIMESTAMP: 2201 com->do_dcd_timestamp = TRUE; 2202 *(struct timeval *)data = com->dcd_timestamp; 2203 break; 2204 default: 2205 splx(s); 2206 return (ENOTTY); 2207 } 2208 } else { 2209#endif 2210 switch (cmd) { 2211 case TIOCSBRK: 2212 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 2213 break; 2214 case TIOCCBRK: 2215 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 2216 break; 2217 case TIOCSDTR: 2218 (void)commctl(com, TIOCM_DTR, DMBIS); 2219 break; 2220 case TIOCCDTR: 2221 (void)commctl(com, TIOCM_DTR, DMBIC); 2222 break; 2223 case TIOCMSET: 2224 (void)commctl(com, *(int *)data, DMSET); 2225 break; 2226 case TIOCMBIS: 2227 (void)commctl(com, *(int *)data, DMBIS); 2228 break; 2229 case TIOCMBIC: 2230 (void)commctl(com, *(int *)data, DMBIC); 2231 break; 2232 case TIOCMGET: 2233 *(int *)data = commctl(com, 0, DMGET); 2234 break; 2235 case TIOCMSDTRWAIT: 2236 /* must be root since the wait applies to following logins */ 2237 error = suser(p->p_ucred, &p->p_acflag); 2238 if (error != 0) { 2239 splx(s); 2240 return (error); 2241 } 2242 com->dtr_wait = *(int *)data * hz / 100; 2243 break; 2244 case TIOCMGDTRWAIT: 2245 *(int *)data = com->dtr_wait * 100 / hz; 2246 break; 2247 case TIOCTIMESTAMP: 2248 com->do_timestamp = TRUE; 2249 *(struct timeval *)data = com->timestamp; 2250 break; 2251 default: 2252 splx(s); 2253 return (ENOTTY); 2254 } 2255#ifdef PC98 2256 } 2257#endif 2258 splx(s); 2259 return (0); 2260} 2261 2262void 2263siopoll() 2264{ 2265 int unit; 2266 2267 if (com_events == 0) 2268 return; 2269repeat: 2270 for (unit = 0; unit < NSIO; ++unit) { 2271 u_char *buf; 2272 struct com_s *com; 2273 u_char *ibuf; 2274 int incc; 2275 struct tty *tp; 2276#ifdef PC98 2277 int tmp; 2278#endif 2279 2280 com = com_addr(unit); 2281 if (com == NULL) 2282 continue; 2283 if (com->gone) 2284 continue; 2285 tp = com->tp; 2286 if (tp == NULL) { 2287 /* 2288 * XXX forget any events related to closed devices 2289 * (actually never opened devices) so that we don't 2290 * loop. 2291 */ 2292 disable_intr(); 2293 incc = com->iptr - com->ibuf; 2294 com->iptr = com->ibuf; 2295 if (com->state & CS_CHECKMSR) { 2296 incc += LOTS_OF_EVENTS; 2297 com->state &= ~CS_CHECKMSR; 2298 } 2299 com_events -= incc; 2300 enable_intr(); 2301 if (incc != 0) 2302 log(LOG_DEBUG, 2303 "sio%d: %d events for device with no tp\n", 2304 unit, incc); 2305 continue; 2306 } 2307 2308 /* switch the role of the low-level input buffers */ 2309 if (com->iptr == (ibuf = com->ibuf)) { 2310 buf = NULL; /* not used, but compiler can't tell */ 2311 incc = 0; 2312 } else { 2313 buf = ibuf; 2314 disable_intr(); 2315 incc = com->iptr - buf; 2316 com_events -= incc; 2317 if (ibuf == com->ibuf1) 2318 ibuf = com->ibuf2; 2319 else 2320 ibuf = com->ibuf1; 2321 com->ibufend = ibuf + RS_IBUFSIZE; 2322 com->ihighwater = ibuf + RS_IHIGHWATER; 2323 com->iptr = ibuf; 2324 2325 /* 2326 * There is now room for another low-level buffer full 2327 * of input, so enable RTS if it is now disabled and 2328 * there is room in the high-level buffer. 2329 */ 2330#ifdef PC98 2331 if(IS_8251(com->pc98_if_type)) 2332 tmp = com_tiocm_get(com) & TIOCM_RTS; 2333 else 2334 tmp = com->mcr_image & MCR_RTS; 2335#endif 2336 if ((com->state & CS_RTS_IFLOW) 2337#ifdef PC98 2338 && !(tmp) 2339#else 2340 && !(com->mcr_image & MCR_RTS) 2341#endif 2342 && !(tp->t_state & TS_TBLOCK)) 2343#ifdef PC98 2344 if(IS_8251(com->pc98_if_type)) 2345 com_tiocm_bis(com, TIOCM_RTS); 2346 else 2347#endif 2348 outb(com->modem_ctl_port, 2349 com->mcr_image |= MCR_RTS); 2350 enable_intr(); 2351 com->ibuf = ibuf; 2352 } 2353 2354 if (com->state & CS_CHECKMSR) { 2355 u_char delta_modem_status; 2356 2357#ifdef PC98 2358 if(!IS_8251(com->pc98_if_type)){ 2359#endif 2360 disable_intr(); 2361 delta_modem_status = com->last_modem_status 2362 ^ com->prev_modem_status; 2363 com->prev_modem_status = com->last_modem_status; 2364 com_events -= LOTS_OF_EVENTS; 2365 com->state &= ~CS_CHECKMSR; 2366 enable_intr(); 2367 if (delta_modem_status & MSR_DCD) 2368 (*linesw[tp->t_line].l_modem) 2369 (tp, com->prev_modem_status & MSR_DCD); 2370#ifdef PC98 2371 } 2372#endif 2373 } 2374 if (com->state & CS_ODONE) { 2375 disable_intr(); 2376 com_events -= LOTS_OF_EVENTS; 2377 com->state &= ~CS_ODONE; 2378 enable_intr(); 2379 if (!(com->state & CS_BUSY)) 2380 timeout(siobusycheck, com, hz / 100); 2381 (*linesw[tp->t_line].l_start)(tp); 2382 } 2383 if (incc <= 0 || !(tp->t_state & TS_ISOPEN) || 2384 !(tp->t_cflag & CREAD)) 2385 continue; 2386 /* 2387 * Avoid the grotesquely inefficient lineswitch routine 2388 * (ttyinput) in "raw" mode. It usually takes about 450 2389 * instructions (that's without canonical processing or echo!). 2390 * slinput is reasonably fast (usually 40 instructions plus 2391 * call overhead). 2392 */ 2393 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 2394 if (tp->t_rawq.c_cc + incc >= RB_I_HIGH_WATER 2395 && (com->state & CS_RTS_IFLOW 2396 || tp->t_iflag & IXOFF) 2397 && !(tp->t_state & TS_TBLOCK)) 2398 ttyblock(tp); 2399 tk_nin += incc; 2400 tk_rawcc += incc; 2401 tp->t_rawcc += incc; 2402 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 2403 += b_to_q((char *)buf, incc, &tp->t_rawq); 2404 ttwakeup(tp); 2405 if (tp->t_state & TS_TTSTOP 2406 && (tp->t_iflag & IXANY 2407 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 2408 tp->t_state &= ~TS_TTSTOP; 2409 tp->t_lflag &= ~FLUSHO; 2410 comstart(tp); 2411 } 2412 } else { 2413 do { 2414 u_char line_status; 2415 int recv_data; 2416 2417 line_status = (u_char) buf[CE_INPUT_OFFSET]; 2418 recv_data = (u_char) *buf++; 2419 if (line_status 2420 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 2421 if (line_status & LSR_BI) 2422 recv_data |= TTY_BI; 2423 if (line_status & LSR_FE) 2424 recv_data |= TTY_FE; 2425 if (line_status & LSR_OE) 2426 recv_data |= TTY_OE; 2427 if (line_status & LSR_PE) 2428 recv_data |= TTY_PE; 2429 } 2430 (*linesw[tp->t_line].l_rint)(recv_data, tp); 2431 } while (--incc > 0); 2432 } 2433 if (com_events == 0) 2434 break; 2435 } 2436 if (com_events >= LOTS_OF_EVENTS) 2437 goto repeat; 2438} 2439 2440static int 2441comparam(tp, t) 2442 struct tty *tp; 2443 struct termios *t; 2444{ 2445 u_int cfcr; 2446 int cflag; 2447 struct com_s *com; 2448 int divisor; 2449 u_char dlbh; 2450 u_char dlbl; 2451 int error; 2452 Port_t iobase; 2453 int s; 2454 int unit; 2455 int txtimeout; 2456#ifdef PC98 2457 Port_t tmp_port; 2458 int tmp_flg; 2459#endif 2460 2461#ifdef PC98 2462 cfcr = 0; 2463 unit = DEV_TO_UNIT(tp->t_dev); 2464 com = com_addr(unit); 2465 iobase = com->iobase; 2466 if(IS_8251(com->pc98_if_type)) { 2467 divisor = pc98_ttspeedtab(com, t->c_ospeed); 2468 } else 2469#endif 2470 /* do historical conversions */ 2471 if (t->c_ispeed == 0) 2472 t->c_ispeed = t->c_ospeed; 2473 2474 /* check requested parameters */ 2475 divisor = ttspeedtab(t->c_ospeed, comspeedtab); 2476 if (divisor < 0 || divisor > 0 && t->c_ispeed != t->c_ospeed) 2477 return (EINVAL); 2478 2479 /* parameters are OK, convert them to the com struct and the device */ 2480#ifndef PC98 2481 unit = DEV_TO_UNIT(tp->t_dev); 2482 com = com_addr(unit); 2483 iobase = com->iobase; 2484#endif 2485 s = spltty(); 2486#ifdef PC98 2487 if(IS_8251(com->pc98_if_type)){ 2488 if(divisor == 0){ 2489 com_int_TxRx_disable( com ); 2490 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 2491 } 2492 } else { 2493#endif 2494 if (divisor == 0) 2495 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 2496 else 2497 (void)commctl(com, TIOCM_DTR, DMBIS); 2498#ifdef PC98 2499 } 2500#endif 2501 cflag = t->c_cflag; 2502#ifdef PC98 2503 if(!IS_8251(com->pc98_if_type)){ 2504#endif 2505 switch (cflag & CSIZE) { 2506 case CS5: 2507 cfcr = CFCR_5BITS; 2508 break; 2509 case CS6: 2510 cfcr = CFCR_6BITS; 2511 break; 2512 case CS7: 2513 cfcr = CFCR_7BITS; 2514 break; 2515 default: 2516 cfcr = CFCR_8BITS; 2517 break; 2518 } 2519 if (cflag & PARENB) { 2520 cfcr |= CFCR_PENAB; 2521 if (!(cflag & PARODD)) 2522 cfcr |= CFCR_PEVEN; 2523 } 2524 if (cflag & CSTOPB) 2525 cfcr |= CFCR_STOPB; 2526 2527 if (com->hasfifo && divisor != 0) { 2528 /* 2529 * Use a fifo trigger level low enough so that the input 2530 * latency from the fifo is less than about 16 msec and 2531 * the total latency is less than about 30 msec. These 2532 * latencies are reasonable for humans. Serial comms 2533 * protocols shouldn't expect anything better since modem 2534 * latencies are larger. 2535 */ 2536 com->fifo_image = t->c_ospeed <= 4800 2537 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; 2538#ifdef COM_ESP 2539 /* 2540 * The Hayes ESP card needs the fifo DMA mode bit set 2541 * in compatibility mode. If not, it will interrupt 2542 * for each character received. 2543 */ 2544 if (com->esp) 2545 com->fifo_image |= FIFO_DMA_MODE; 2546#endif 2547 outb(iobase + com_fifo, com->fifo_image); 2548 } 2549 2550 /* 2551 * Some UARTs lock up if the divisor latch registers are selected 2552 * while the UART is doing output (they refuse to transmit anything 2553 * more until given a hard reset). Fix this by stopping filling 2554 * the device buffers and waiting for them to drain. Reading the 2555 * line status port outside of siointr1() might lose some receiver 2556 * error bits, but that is acceptable here. 2557 */ 2558#ifdef PC98 2559 } 2560#endif 2561 disable_intr(); 2562retry: 2563 com->state &= ~CS_TTGO; 2564 txtimeout = tp->t_timeout; 2565 enable_intr(); 2566#ifdef PC98 2567 if(IS_8251(com->pc98_if_type)){ 2568 tmp_port = com->sts_port; 2569 tmp_flg = (STS8251_TxRDY|STS8251_TxEMP); 2570 } else { 2571 tmp_port = com->line_status_port; 2572 tmp_flg = (LSR_TSRE|LSR_TXRDY); 2573 } 2574 while ((inb(tmp_port) & tmp_flg) != tmp_flg) { 2575#else 2576 while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2577 != (LSR_TSRE | LSR_TXRDY)) { 2578#endif 2579 tp->t_state |= TS_SO_OCOMPLETE; 2580 error = ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI | PCATCH, 2581 "siotx", hz / 100); 2582 if ( txtimeout != 0 2583 && (!error || error == EAGAIN) 2584 && (txtimeout -= hz / 100) <= 0 2585 ) 2586 error = EIO; 2587 if (com->gone) 2588 error = ENODEV; 2589 if (error != 0 && error != EAGAIN) { 2590 if (!(tp->t_state & TS_TTSTOP)) { 2591 disable_intr(); 2592 com->state |= CS_TTGO; 2593 enable_intr(); 2594 } 2595 splx(s); 2596 return (error); 2597 } 2598 } 2599 2600 disable_intr(); /* very important while com_data is hidden */ 2601 2602 /* 2603 * XXX - clearing CS_TTGO is not sufficient to stop further output, 2604 * because siopoll() calls comstart() which usually sets it again 2605 * because TS_TTSTOP is clear. Setting TS_TTSTOP would not be 2606 * sufficient, for similar reasons. 2607 */ 2608#ifdef PC98 2609 if ((inb(tmp_port) & tmp_flg) != tmp_flg) 2610#else 2611 if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2612 != (LSR_TSRE | LSR_TXRDY)) 2613#endif 2614 goto retry; 2615 2616#ifdef PC98 2617 if(!IS_8251(com->pc98_if_type)){ 2618#endif 2619 if (divisor != 0) { 2620 outb(iobase + com_cfcr, cfcr | CFCR_DLAB); 2621 /* 2622 * Only set the divisor registers if they would change, 2623 * since on some 16550 incompatibles (UMC8669F), setting 2624 * them while input is arriving them loses sync until 2625 * data stops arriving. 2626 */ 2627 dlbl = divisor & 0xFF; 2628 if (inb(iobase + com_dlbl) != dlbl) 2629 outb(iobase + com_dlbl, dlbl); 2630 dlbh = (u_int) divisor >> 8; 2631 if (inb(iobase + com_dlbh) != dlbh) 2632 outb(iobase + com_dlbh, dlbh); 2633 } 2634 outb(iobase + com_cfcr, com->cfcr_image = cfcr); 2635#ifdef PC98 2636 } else 2637 com_cflag_and_speed_set(com, cflag, t->c_ospeed); 2638#endif 2639 if (!(tp->t_state & TS_TTSTOP)) 2640 com->state |= CS_TTGO; 2641 if (cflag & CRTS_IFLOW) { 2642 com->state |= CS_RTS_IFLOW; 2643 /* 2644 * If CS_RTS_IFLOW just changed from off to on, the change 2645 * needs to be propagated to MCR_RTS. This isn't urgent, 2646 * so do it later by calling comstart() instead of repeating 2647 * a lot of code from comstart() here. 2648 */ 2649 } else if (com->state & CS_RTS_IFLOW) { 2650 com->state &= ~CS_RTS_IFLOW; 2651 /* 2652 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2653 * on here, since comstart() won't do it later. 2654 */ 2655 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2656 } 2657 2658 /* 2659 * Set up state to handle output flow control. 2660 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2661 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2662 */ 2663 com->state |= CS_ODEVREADY; 2664 com->state &= ~CS_CTS_OFLOW; 2665 if (cflag & CCTS_OFLOW) { 2666 com->state |= CS_CTS_OFLOW; 2667#ifdef PC98 2668 if(IS_8251(com->pc98_if_type)){ 2669 if (!(pc98_get_modem_status(com) & TIOCM_CTS)) 2670 com->state &= ~CS_ODEVREADY; 2671 } else { 2672#endif 2673 if (!(com->last_modem_status & MSR_CTS)) 2674 com->state &= ~CS_ODEVREADY; 2675#ifdef PC98 2676 } 2677#endif 2678 } 2679 /* XXX shouldn't call functions while intrs are disabled. */ 2680 disc_optim(tp, t, com); 2681 /* 2682 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2683 * unconditionally, but that defeated the careful discarding of 2684 * stale input in sioopen(). 2685 */ 2686 if (com->state >= (CS_BUSY | CS_TTGO)) 2687 siointr1(com); 2688 2689 enable_intr(); 2690 splx(s); 2691 comstart(tp); 2692 return (0); 2693} 2694 2695static void 2696comstart(tp) 2697 struct tty *tp; 2698{ 2699 struct com_s *com; 2700 int s; 2701 int unit; 2702#ifdef PC98 2703 int tmp; 2704#endif 2705 2706 unit = DEV_TO_UNIT(tp->t_dev); 2707 com = com_addr(unit); 2708 s = spltty(); 2709 disable_intr(); 2710 if (tp->t_state & TS_TTSTOP) 2711 com->state &= ~CS_TTGO; 2712 else 2713 com->state |= CS_TTGO; 2714 if (tp->t_state & TS_TBLOCK) { 2715#ifdef PC98 2716 if(IS_8251(com->pc98_if_type)) 2717 tmp = com_tiocm_get(com) & TIOCM_RTS; 2718 else 2719 tmp = com->mcr_image & MCR_RTS; 2720 if (tmp && (com->state & CS_RTS_IFLOW)) 2721#else 2722 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 2723#endif 2724#ifdef PC98 2725 if(IS_8251(com->pc98_if_type)) 2726 com_tiocm_bic(com, TIOCM_RTS); 2727 else 2728#endif 2729 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2730 } else { 2731#ifdef PC98 2732 if(IS_8251(com->pc98_if_type)) 2733 tmp = com_tiocm_get(com) & TIOCM_RTS; 2734 else 2735 tmp = com->mcr_image & MCR_RTS; 2736 if (!(tmp) && com->iptr < com->ihighwater 2737 && com->state & CS_RTS_IFLOW) 2738#else 2739 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater 2740 && com->state & CS_RTS_IFLOW) 2741#endif 2742#ifdef PC98 2743 if(IS_8251(com->pc98_if_type)) 2744 com_tiocm_bis(com, TIOCM_RTS); 2745 else 2746#endif 2747 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2748 } 2749 enable_intr(); 2750 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2751#ifdef PC98 2752/* if(IS_8251(com->pc98_if_type)) 2753 com_int_Tx_enable(com); */ 2754#endif 2755 splx(s); 2756 return; 2757 } 2758 if (tp->t_outq.c_cc != 0) { 2759 struct lbq *qp; 2760 struct lbq *next; 2761 2762 if (!com->obufs[0].l_queued) { 2763 com->obufs[0].l_tail 2764 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2765 sizeof com->obuf1); 2766 com->obufs[0].l_next = NULL; 2767 com->obufs[0].l_queued = TRUE; 2768 disable_intr(); 2769 if (com->state & CS_BUSY) { 2770 qp = com->obufq.l_next; 2771 while ((next = qp->l_next) != NULL) 2772 qp = next; 2773 qp->l_next = &com->obufs[0]; 2774 } else { 2775 com->obufq.l_head = com->obufs[0].l_head; 2776 com->obufq.l_tail = com->obufs[0].l_tail; 2777 com->obufq.l_next = &com->obufs[0]; 2778 com->state |= CS_BUSY; 2779 } 2780 enable_intr(); 2781 } 2782 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2783 com->obufs[1].l_tail 2784 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2785 sizeof com->obuf2); 2786 com->obufs[1].l_next = NULL; 2787 com->obufs[1].l_queued = TRUE; 2788 disable_intr(); 2789 if (com->state & CS_BUSY) { 2790 qp = com->obufq.l_next; 2791 while ((next = qp->l_next) != NULL) 2792 qp = next; 2793 qp->l_next = &com->obufs[1]; 2794 } else { 2795 com->obufq.l_head = com->obufs[1].l_head; 2796 com->obufq.l_tail = com->obufs[1].l_tail; 2797 com->obufq.l_next = &com->obufs[1]; 2798 com->state |= CS_BUSY; 2799 } 2800 enable_intr(); 2801 } 2802 tp->t_state |= TS_BUSY; 2803 } 2804 disable_intr(); 2805 if (com->state >= (CS_BUSY | CS_TTGO)) 2806 siointr1(com); /* fake interrupt to start output */ 2807 enable_intr(); 2808#ifdef PC98 2809/* if(IS_8251(com->pc98_if_type)) 2810 com_int_Tx_enable(com); */ 2811#endif 2812 ttwwakeup(tp); 2813 splx(s); 2814} 2815 2816static void 2817siostop(tp, rw) 2818 struct tty *tp; 2819 int rw; 2820{ 2821 struct com_s *com; 2822 2823 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2824 if (com->gone) 2825 return; 2826 disable_intr(); 2827 if (rw & FWRITE) { 2828 if (com->hasfifo) 2829#ifdef COM_ESP 2830 /* XXX avoid h/w bug. */ 2831 if (!com->esp) 2832#endif 2833 /* XXX does this flush everything? */ 2834 outb(com->iobase + com_fifo, 2835 FIFO_XMT_RST | com->fifo_image); 2836 com->obufs[0].l_queued = FALSE; 2837 com->obufs[1].l_queued = FALSE; 2838 if (com->state & CS_ODONE) 2839 com_events -= LOTS_OF_EVENTS; 2840 com->state &= ~(CS_ODONE | CS_BUSY); 2841 com->tp->t_state &= ~TS_BUSY; 2842 } 2843 if (rw & FREAD) { 2844 if (com->hasfifo) 2845#ifdef COM_ESP 2846 /* XXX avoid h/w bug. */ 2847 if (!com->esp) 2848#endif 2849 /* XXX does this flush everything? */ 2850 outb(com->iobase + com_fifo, 2851 FIFO_RCV_RST | com->fifo_image); 2852 com_events -= (com->iptr - com->ibuf); 2853 com->iptr = com->ibuf; 2854 } 2855 enable_intr(); 2856 comstart(tp); 2857} 2858 2859static struct tty * 2860siodevtotty(dev) 2861 dev_t dev; 2862{ 2863 int mynor; 2864 int unit; 2865 2866 mynor = minor(dev); 2867 if (mynor & CONTROL_MASK) 2868 return (NULL); 2869 unit = MINOR_TO_UNIT(mynor); 2870 if ((u_int) unit >= NSIO) 2871 return (NULL); 2872 return (&sio_tty[unit]); 2873} 2874 2875static int 2876commctl(com, bits, how) 2877 struct com_s *com; 2878 int bits; 2879 int how; 2880{ 2881 int mcr; 2882 int msr; 2883 2884 if (how == DMGET) { 2885 bits = TIOCM_LE; /* XXX - always enabled while open */ 2886 mcr = com->mcr_image; 2887 if (mcr & MCR_DTR) 2888 bits |= TIOCM_DTR; 2889 if (mcr & MCR_RTS) 2890 bits |= TIOCM_RTS; 2891 msr = com->prev_modem_status; 2892 if (msr & MSR_CTS) 2893 bits |= TIOCM_CTS; 2894 if (msr & MSR_DCD) 2895 bits |= TIOCM_CD; 2896 if (msr & MSR_DSR) 2897 bits |= TIOCM_DSR; 2898 /* 2899 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI 2900 * more volatile by reading the modem status a lot. Perhaps 2901 * we should latch both bits until the status is read here. 2902 */ 2903 if (msr & (MSR_RI | MSR_TERI)) 2904 bits |= TIOCM_RI; 2905 return (bits); 2906 } 2907 mcr = 0; 2908 if (bits & TIOCM_DTR) 2909 mcr |= MCR_DTR; 2910 if (bits & TIOCM_RTS) 2911 mcr |= MCR_RTS; 2912 if (com->gone) 2913 return(0); 2914 disable_intr(); 2915 switch (how) { 2916 case DMSET: 2917 outb(com->modem_ctl_port, 2918 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); 2919 break; 2920 case DMBIS: 2921 outb(com->modem_ctl_port, com->mcr_image |= mcr); 2922 break; 2923 case DMBIC: 2924 outb(com->modem_ctl_port, com->mcr_image &= ~mcr); 2925 break; 2926 } 2927 enable_intr(); 2928 return (0); 2929} 2930 2931static void 2932siosettimeout() 2933{ 2934 struct com_s *com; 2935 bool_t someopen; 2936 int unit; 2937 2938 /* 2939 * Set our timeout period to 1 second if no polled devices are open. 2940 * Otherwise set it to max(1/200, 1/hz). 2941 * Enable timeouts iff some device is open. 2942 */ 2943 untimeout(comwakeup, (void *)NULL); 2944 sio_timeout = hz; 2945 someopen = FALSE; 2946 for (unit = 0; unit < NSIO; ++unit) { 2947 com = com_addr(unit); 2948 if (com != NULL && com->tp != NULL 2949 && com->tp->t_state & TS_ISOPEN && !com->gone) { 2950 someopen = TRUE; 2951 if (com->poll || com->poll_output) { 2952 sio_timeout = hz > 200 ? hz / 200 : 1; 2953 break; 2954 } 2955 } 2956 } 2957 if (someopen) { 2958 sio_timeouts_until_log = hz / sio_timeout; 2959 timeout(comwakeup, (void *)NULL, sio_timeout); 2960 } else { 2961 /* Flush error messages, if any. */ 2962 sio_timeouts_until_log = 1; 2963 comwakeup((void *)NULL); 2964 untimeout(comwakeup, (void *)NULL); 2965 } 2966} 2967 2968static void 2969comwakeup(chan) 2970 void *chan; 2971{ 2972 struct com_s *com; 2973 int unit; 2974 2975 timeout(comwakeup, (void *)NULL, sio_timeout); 2976 2977 /* 2978 * Recover from lost output interrupts. 2979 * Poll any lines that don't use interrupts. 2980 */ 2981 for (unit = 0; unit < NSIO; ++unit) { 2982 com = com_addr(unit); 2983 if (com != NULL && !com->gone 2984 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2985 disable_intr(); 2986 siointr1(com); 2987 enable_intr(); 2988 } 2989 } 2990 2991 /* 2992 * Check for and log errors, but not too often. 2993 */ 2994 if (--sio_timeouts_until_log > 0) 2995 return; 2996 sio_timeouts_until_log = hz / sio_timeout; 2997 for (unit = 0; unit < NSIO; ++unit) { 2998 int errnum; 2999 3000 com = com_addr(unit); 3001 if (com == NULL) 3002 continue; 3003 if (com->gone) 3004 continue; 3005 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 3006 u_int delta; 3007 u_long total; 3008 3009 disable_intr(); 3010 delta = com->delta_error_counts[errnum]; 3011 com->delta_error_counts[errnum] = 0; 3012 enable_intr(); 3013 if (delta == 0) 3014 continue; 3015 total = com->error_counts[errnum] += delta; 3016 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", 3017 unit, delta, error_desc[errnum], 3018 delta == 1 ? "" : "s", total); 3019 } 3020 } 3021} 3022 3023#ifdef PC98 3024/* commint is called when modem control line changes */ 3025static void 3026commint(dev_t dev) 3027{ 3028 register struct tty *tp; 3029 int stat,delta; 3030 struct com_s *com; 3031 int mynor,unit; 3032 3033 mynor = minor(dev); 3034 unit = MINOR_TO_UNIT(mynor); 3035 com = com_addr(unit); 3036 tp = com->tp; 3037 3038 stat = com_tiocm_get(com); 3039 delta = com_tiocm_get_delta(com); 3040 3041 if (com->state & CS_CTS_OFLOW) { 3042 if (stat & TIOCM_CTS) 3043 com->state |= CS_ODEVREADY; 3044 else 3045 com->state &= ~CS_ODEVREADY; 3046 } 3047 if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) { 3048 if (stat & TIOCM_CAR ) 3049 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 3050 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 3051 /* negate DTR, RTS */ 3052 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ? 3053 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE ); 3054 /* disable IENABLE */ 3055 com_int_TxRx_disable( com ); 3056 } 3057 } 3058} 3059#endif 3060 3061static void 3062disc_optim(tp, t, com) 3063 struct tty *tp; 3064 struct termios *t; 3065 struct com_s *com; 3066{ 3067 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 3068 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 3069 && (!(t->c_iflag & PARMRK) 3070 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 3071 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 3072 && linesw[tp->t_line].l_rint == ttyinput) 3073 tp->t_state |= TS_CAN_BYPASS_L_RINT; 3074 else 3075 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 3076 /* 3077 * Prepare to reduce input latency for packet 3078 * discplines with a end of packet character. 3079 */ 3080 if (tp->t_line == SLIPDISC) 3081 com->hotchar = 0xc0; 3082 else if (tp->t_line == PPPDISC) 3083 com->hotchar = 0x7e; 3084 else 3085 com->hotchar = 0; 3086} 3087 3088/* 3089 * Following are all routines needed for SIO to act as console 3090 */ 3091#include <machine/cons.h> 3092 3093struct siocnstate { 3094 u_char dlbl; 3095 u_char dlbh; 3096 u_char ier; 3097 u_char cfcr; 3098 u_char mcr; 3099}; 3100 3101static Port_t siocniobase; 3102 3103static void siocnclose __P((struct siocnstate *sp)); 3104static void siocnopen __P((struct siocnstate *sp)); 3105static void siocntxwait __P((void)); 3106 3107static void 3108siocntxwait() 3109{ 3110 int timo; 3111 3112 /* 3113 * Wait for any pending transmission to finish. Required to avoid 3114 * the UART lockup bug when the speed is changed, and for normal 3115 * transmits. 3116 */ 3117 timo = 100000; 3118 while ((inb(siocniobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) 3119 != (LSR_TSRE | LSR_TXRDY) && --timo != 0) 3120 ; 3121} 3122 3123static void 3124siocnopen(sp) 3125 struct siocnstate *sp; 3126{ 3127 int divisor; 3128 u_char dlbh; 3129 u_char dlbl; 3130 Port_t iobase; 3131 3132 /* 3133 * Save all the device control registers except the fifo register 3134 * and set our default ones (cs8 -parenb speed=comdefaultrate). 3135 * We can't save the fifo register since it is read-only. 3136 */ 3137 iobase = siocniobase; 3138 sp->ier = inb(iobase + com_ier); 3139 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ 3140 siocntxwait(); 3141 sp->cfcr = inb(iobase + com_cfcr); 3142 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3143 sp->dlbl = inb(iobase + com_dlbl); 3144 sp->dlbh = inb(iobase + com_dlbh); 3145 /* 3146 * Only set the divisor registers if they would change, since on 3147 * some 16550 incompatibles (Startech), setting them clears the 3148 * data input register. This also reduces the effects of the 3149 * UMC8669F bug. 3150 */ 3151 divisor = ttspeedtab(comdefaultrate, comspeedtab); 3152 dlbl = divisor & 0xFF; 3153 if (sp->dlbl != dlbl) 3154 outb(iobase + com_dlbl, dlbl); 3155 dlbh = (u_int) divisor >> 8; 3156 if (sp->dlbh != dlbh) 3157 outb(iobase + com_dlbh, dlbh); 3158 outb(iobase + com_cfcr, CFCR_8BITS); 3159 sp->mcr = inb(iobase + com_mcr); 3160 /* 3161 * We don't want interrupts, but must be careful not to "disable" 3162 * them by clearing the MCR_IENABLE bit, since that might cause 3163 * an interrupt by floating the IRQ line. 3164 */ 3165 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); 3166} 3167 3168static void 3169siocnclose(sp) 3170 struct siocnstate *sp; 3171{ 3172 Port_t iobase; 3173 3174 /* 3175 * Restore the device control registers. 3176 */ 3177 siocntxwait(); 3178 iobase = siocniobase; 3179 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3180 if (sp->dlbl != inb(iobase + com_dlbl)) 3181 outb(iobase + com_dlbl, sp->dlbl); 3182 if (sp->dlbh != inb(iobase + com_dlbh)) 3183 outb(iobase + com_dlbh, sp->dlbh); 3184 outb(iobase + com_cfcr, sp->cfcr); 3185 /* 3186 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. 3187 */ 3188 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); 3189 outb(iobase + com_ier, sp->ier); 3190} 3191 3192void 3193siocnprobe(cp) 3194 struct consdev *cp; 3195{ 3196 int unit; 3197 3198 /* XXX: ick */ 3199 unit = DEV_TO_UNIT(CONUNIT); 3200 siocniobase = CONADDR; 3201 3202 /* make sure hardware exists? XXX */ 3203 3204 /* initialize required fields */ 3205 cp->cn_dev = makedev(CDEV_MAJOR, unit); 3206#ifdef COMCONSOLE 3207 cp->cn_pri = CN_REMOTE; /* Force a serial port console */ 3208#else 3209 cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL; 3210#endif 3211} 3212 3213void 3214siocninit(cp) 3215 struct consdev *cp; 3216{ 3217 comconsole = DEV_TO_UNIT(cp->cn_dev); 3218} 3219 3220int 3221siocncheckc(dev) 3222 dev_t dev; 3223{ 3224 int c; 3225 Port_t iobase; 3226 int s; 3227 struct siocnstate sp; 3228 3229 iobase = siocniobase; 3230 s = spltty(); 3231 siocnopen(&sp); 3232 if (inb(iobase + com_lsr) & LSR_RXRDY) 3233 c = inb(iobase + com_data); 3234 else 3235 c = -1; 3236 siocnclose(&sp); 3237 splx(s); 3238 return (c); 3239} 3240 3241 3242int 3243siocngetc(dev) 3244 dev_t dev; 3245{ 3246 int c; 3247 Port_t iobase; 3248 int s; 3249 struct siocnstate sp; 3250 3251 iobase = siocniobase; 3252 s = spltty(); 3253 siocnopen(&sp); 3254 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 3255 ; 3256 c = inb(iobase + com_data); 3257 siocnclose(&sp); 3258 splx(s); 3259 return (c); 3260} 3261 3262void 3263siocnputc(dev, c) 3264 dev_t dev; 3265 int c; 3266{ 3267 int s; 3268 struct siocnstate sp; 3269 3270 s = spltty(); 3271 siocnopen(&sp); 3272 siocntxwait(); 3273 outb(siocniobase + com_data, c); 3274 siocnclose(&sp); 3275 splx(s); 3276} 3277 3278#ifdef DSI_SOFT_MODEM 3279/* 3280 * The magic code to download microcode to a "Connection 14.4+Fax" 3281 * modem from Digicom Systems Inc. Very magic. 3282 */ 3283 3284#define DSI_ERROR(str) { ptr = str; goto error; } 3285static int 3286LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr) 3287{ 3288 int int_c,int_k; 3289 int data_0188, data_0187; 3290 3291 /* 3292 * First see if it is a DSI SoftModem 3293 */ 3294 if(!((inb(base_io+7) ^ inb(base_io+7) & 0x80))) 3295 return ENODEV; 3296 3297 data_0188 = inb(base_io+4); 3298 data_0187 = inb(base_io+3); 3299 outb(base_io+3,0x80); 3300 outb(base_io+4,0x0C); 3301 outb(base_io+0,0x31); 3302 outb(base_io+1,0x8C); 3303 outb(base_io+7,0x10); 3304 outb(base_io+7,0x19); 3305 3306 if(0x18 != (inb(base_io+7) & 0x1A)) 3307 DSI_ERROR("dsp bus not granted"); 3308 3309 if(0x01 != (inb(base_io+7) & 0x01)) { 3310 outb(base_io+7,0x18); 3311 outb(base_io+7,0x19); 3312 if(0x01 != (inb(base_io+7) & 0x01)) 3313 DSI_ERROR("program mem not granted"); 3314 } 3315 3316 int_c = 0; 3317 3318 while(1) { 3319 if(int_c >= 7 || size <= 0x1800) 3320 break; 3321 3322 for(int_k = 0 ; int_k < 0x800; int_k++) { 3323 outb(base_io+0,*ptr++); 3324 outb(base_io+1,*ptr++); 3325 outb(base_io+2,*ptr++); 3326 } 3327 3328 size -= 0x1800; 3329 int_c++; 3330 } 3331 3332 if(size > 0x1800) { 3333 outb(base_io+7,0x18); 3334 outb(base_io+7,0x19); 3335 if(0x00 != (inb(base_io+7) & 0x01)) 3336 DSI_ERROR("program data not granted"); 3337 3338 for(int_k = 0 ; int_k < 0x800; int_k++) { 3339 outb(base_io+1,*ptr++); 3340 outb(base_io+2,0); 3341 outb(base_io+1,*ptr++); 3342 outb(base_io+2,*ptr++); 3343 } 3344 3345 size -= 0x1800; 3346 3347 while(size > 0x1800) { 3348 for(int_k = 0 ; int_k < 0xC00; int_k++) { 3349 outb(base_io+1,*ptr++); 3350 outb(base_io+2,*ptr++); 3351 } 3352 size -= 0x1800; 3353 } 3354 3355 if(size < 0x1800) { 3356 for(int_k=0;int_k<size/2;int_k++) { 3357 outb(base_io+1,*ptr++); 3358 outb(base_io+2,*ptr++); 3359 } 3360 } 3361 3362 } else if (size > 0) { 3363 if(int_c == 7) { 3364 outb(base_io+7,0x18); 3365 outb(base_io+7,0x19); 3366 if(0x00 != (inb(base_io+7) & 0x01)) 3367 DSI_ERROR("program data not granted"); 3368 for(int_k = 0 ; int_k < size/3; int_k++) { 3369 outb(base_io+1,*ptr++); 3370 outb(base_io+2,0); 3371 outb(base_io+1,*ptr++); 3372 outb(base_io+2,*ptr++); 3373 } 3374 } else { 3375 for(int_k = 0 ; int_k < size/3; int_k++) { 3376 outb(base_io+0,*ptr++); 3377 outb(base_io+1,*ptr++); 3378 outb(base_io+2,*ptr++); 3379 } 3380 } 3381 } 3382 outb(base_io+7,0x11); 3383 outb(base_io+7,3); 3384 3385 outb(base_io+4,data_0188 & 0xfb); 3386 3387 outb(base_io+3,data_0187); 3388 3389 return 0; 3390error: 3391 printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",unit,ptr); 3392 outb(base_io+7,0x00); \ 3393 outb(base_io+3,data_0187); \ 3394 outb(base_io+4,data_0188); \ 3395 return EIO; 3396} 3397#endif /* DSI_SOFT_MODEM */ 3398#ifdef PC98 3399/* 3400 * pc98 local function 3401 */ 3402 3403static void 3404com_tiocm_set(struct com_s *com, int msr) 3405{ 3406 int s; 3407 int tmp = 0; 3408 int mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS; 3409 3410 s=spltty(); 3411 com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ) 3412 | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3413 tmp |= (CMD8251_TxEN|CMD8251_RxEN); 3414 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3415 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3416 pc98_i8251_clear_or_cmd( com, mask, tmp ); 3417 splx(s); 3418} 3419 3420static void 3421com_tiocm_bis(struct com_s *com, int msr) 3422{ 3423 int s; 3424 int tmp = 0; 3425 3426 s=spltty(); 3427 com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3428 tmp |= CMD8251_TxEN|CMD8251_RxEN; 3429 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3430 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3431 3432 pc98_i8251_or_cmd( com, tmp ); 3433 splx(s); 3434} 3435 3436static void 3437com_tiocm_bic(struct com_s *com, int msr) 3438{ 3439 int s; 3440 int tmp = msr; 3441 3442 s=spltty(); 3443 com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3444 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3445 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3446 3447 pc98_i8251_clear_cmd( com, tmp ); 3448 splx(s); 3449} 3450 3451static int 3452com_tiocm_get(struct com_s *com) 3453{ 3454 return( com->pc98_prev_modem_status ); 3455} 3456 3457static int 3458com_tiocm_get_delta(struct com_s *com) 3459{ 3460 int tmp; 3461 3462 tmp = com->pc98_modem_delta; 3463 com->pc98_modem_delta = 0; 3464 return( tmp ); 3465} 3466 3467/* convert to TIOCM_?? ( ioctl.h ) */ 3468static int 3469pc98_get_modem_status(struct com_s *com) 3470{ 3471 int stat, stat2; 3472 register int msr; 3473 3474 stat = inb(com->sts_port); 3475 stat2 = inb(com->in_modem_port); 3476 msr = com->pc98_prev_modem_status 3477 & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3478 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR; 3479 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI; 3480 if ( stat & STS8251_DSR ) msr |= TIOCM_DSR; 3481 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS; 3482#if COM_CARRIER_DETECT_EMULATE 3483 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { 3484 msr |= TIOCM_CAR; 3485 } 3486#endif 3487 return(msr); 3488} 3489 3490static void 3491pc98_check_msr(void* chan) 3492{ 3493 int msr, delta; 3494 int s; 3495 register struct tty *tp; 3496 struct com_s *com; 3497 int mynor; 3498 int unit; 3499 dev_t dev; 3500 3501 dev=(dev_t)chan; 3502 mynor = minor(dev); 3503 unit = MINOR_TO_UNIT(mynor); 3504 com = com_addr(unit); 3505 tp = com->tp; 3506 3507 s = spltty(); 3508 msr = pc98_get_modem_status(com); 3509 /* make change flag */ 3510 delta = msr ^ com->pc98_prev_modem_status; 3511 if ( delta & TIOCM_CAR ) { 3512 if ( com->modem_car_chg_timer ) { 3513 if ( -- com->modem_car_chg_timer ) 3514 msr ^= TIOCM_CAR; 3515 } else { 3516 if ( com->modem_car_chg_timer = ( msr & TIOCM_CAR ) ? 3517 DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE ) 3518 msr ^= TIOCM_CAR; 3519 } 3520 } else 3521 com->modem_car_chg_timer = 0; 3522 delta = ( msr ^ com->pc98_prev_modem_status ) & 3523 (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3524 com->pc98_prev_modem_status = msr; 3525 delta = ( com->pc98_modem_delta |= delta ); 3526 splx(s); 3527 if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) { 3528 if ( delta ) { 3529 commint(dev); 3530 } 3531 timeout(pc98_check_msr, (caddr_t)dev, 3532 PC98_CHECK_MODEM_INTERVAL); 3533 } else { 3534 com->modem_checking = 0; 3535 } 3536} 3537 3538static void 3539pc98_msrint_start(dev_t dev) 3540{ 3541 struct com_s *com; 3542 int mynor; 3543 int unit; 3544 int s = spltty(); 3545 3546 mynor = minor(dev); 3547 unit = MINOR_TO_UNIT(mynor); 3548 com = com_addr(unit); 3549 /* modem control line check routine envoke interval is 1/10 sec */ 3550 if ( com->modem_checking == 0 ) { 3551 com->pc98_prev_modem_status = pc98_get_modem_status(com); 3552 com->pc98_modem_delta = 0; 3553 timeout(pc98_check_msr, (caddr_t)dev, 3554 PC98_CHECK_MODEM_INTERVAL); 3555 com->modem_checking = 1; 3556 } 3557 splx(s); 3558} 3559 3560static void 3561pc98_disable_i8251_interrupt(struct com_s *com, int mod) 3562{ 3563 /* disable interrupt */ 3564 register int tmp; 3565 3566 mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3567 COM_INT_DISABLE 3568 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3569 outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp ); 3570 COM_INT_ENABLE 3571} 3572 3573static void 3574pc98_enable_i8251_interrupt(struct com_s *com, int mod) 3575{ 3576 register int tmp; 3577 3578 COM_INT_DISABLE 3579 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3580 outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp ); 3581 COM_INT_ENABLE 3582} 3583 3584static int 3585pc98_check_i8251_interrupt(struct com_s *com) 3586{ 3587 return ( com->intr_enable & 0x07 ); 3588} 3589 3590static void 3591pc98_i8251_clear_cmd(struct com_s *com, int x) 3592{ 3593 int tmp; 3594 3595 COM_INT_DISABLE 3596 tmp = com->pc98_prev_siocmd & ~(x); 3597 outb(com->cmd_port, tmp); 3598 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3599 COM_INT_ENABLE 3600} 3601 3602static void 3603pc98_i8251_or_cmd(struct com_s *com, int x) 3604{ 3605 int tmp; 3606 3607 COM_INT_DISABLE 3608 tmp = com->pc98_prev_siocmd | (x); 3609 outb(com->cmd_port, tmp); 3610 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3611 COM_INT_ENABLE 3612} 3613 3614static void 3615pc98_i8251_set_cmd(struct com_s *com, int x) 3616{ 3617 int tmp; 3618 3619 COM_INT_DISABLE 3620 tmp = (x); 3621 outb(com->cmd_port, tmp); 3622 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3623 COM_INT_ENABLE 3624} 3625 3626static void 3627pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x) 3628{ 3629 int tmp; 3630 COM_INT_DISABLE 3631 tmp = com->pc98_prev_siocmd & ~(clr); 3632 tmp |= (x); 3633 outb(com->cmd_port, tmp); 3634 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3635 COM_INT_ENABLE 3636} 3637 3638static int 3639pc98_i8251_get_cmd(struct com_s *com) 3640{ 3641 return com->pc98_prev_siocmd; 3642} 3643 3644static int 3645pc98_i8251_get_mod(struct com_s *com) 3646{ 3647 return com->pc98_prev_siomod; 3648} 3649 3650static void 3651pc98_i8251_reset(struct com_s *com, int mode, int command) 3652{ 3653 outb(com->cmd_port, 0); /* dummy */ 3654 DELAY(2); 3655 outb(com->cmd_port, 0); /* dummy */ 3656 DELAY(2); 3657 outb(com->cmd_port, 0); /* dummy */ 3658 DELAY(2); 3659 outb(com->cmd_port, CMD8251_RESET); /* internal reset */ 3660 DELAY(2); 3661 outb(com->cmd_port, mode ); /* mode register */ 3662 com->pc98_prev_siomod = mode; 3663 DELAY(2); 3664 pc98_i8251_set_cmd( com, (command|CMD8251_ER) ); 3665} 3666 3667static void 3668pc98_check_sysclock(void) 3669{ 3670 /* get system clock from port */ 3671 if ( pc98_machine_type & M_8M ) { 3672 /* 8 MHz system & H98 */ 3673 sysclock = 8; 3674 } else { 3675 /* 5 MHz system */ 3676 sysclock = 5; 3677 } 3678} 3679 3680static void 3681com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) 3682{ 3683 int cfcr=0, count; 3684 int previnterrupt; 3685 3686 count = pc98_ttspeedtab( com, speed ); 3687 if ( count < 0 ) return; 3688 3689 previnterrupt = pc98_check_i8251_interrupt(com); 3690 pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx ); 3691 3692 switch ( cflag&CSIZE ) { 3693 case CS5: 3694 cfcr = MOD8251_5BITS; break; 3695 case CS6: 3696 cfcr = MOD8251_6BITS; break; 3697 case CS7: 3698 cfcr = MOD8251_7BITS; break; 3699 case CS8: 3700 cfcr = MOD8251_8BITS; break; 3701 } 3702 if ( cflag&PARENB ) { 3703 if ( cflag&PARODD ) 3704 cfcr |= MOD8251_PODD; 3705 else 3706 cfcr |= MOD8251_PEVEN; 3707 } else 3708 cfcr |= MOD8251_PDISAB; 3709 3710 if ( cflag&CSTOPB ) 3711 cfcr |= MOD8251_STOP2; 3712 else 3713 cfcr |= MOD8251_STOP1; 3714 3715 if ( count & 0x10000 ) 3716 cfcr |= MOD8251_CLKX1; 3717 else 3718 cfcr |= MOD8251_CLKX16; 3719 3720 if (epson_machine_id != 0x20) { /* XXX */ 3721 { 3722 int tmp; 3723 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP)) 3724 ; 3725 } 3726 } 3727 /* set baud rate from ospeed */ 3728 pc98_set_baud_rate( com, count ); 3729 3730 if ( cfcr != pc98_i8251_get_mod(com) ) 3731 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) ); 3732 3733 pc98_enable_i8251_interrupt( com, previnterrupt ); 3734} 3735 3736static int 3737pc98_ttspeedtab(struct com_s *com, int speed) 3738{ 3739 int effect_sp, count=-1, mod; 3740 3741 switch ( com->pc98_if_type ) { 3742 case COM_IF_INTERNAL: 3743 /* for *1CLK asynchronous! mode , TEFUTEFU */ 3744 effect_sp = ttspeedtab( speed, pc98speedtab ); 3745 if ( effect_sp < 0 ) 3746 effect_sp = ttspeedtab( (speed-1), pc98speedtab ); 3747 if ( effect_sp <= 0 ) 3748 return effect_sp; 3749 mod = (sysclock == 5 ? 2457600 : 1996800); 3750 if ( effect_sp == speed ) 3751 mod /= 16; 3752 count = mod / effect_sp; 3753 if ( count > 65535 ) 3754 return(-1); 3755 if ( effect_sp >= 2400 ) 3756 if ( !(sysclock != 5 && 3757 (effect_sp == 19200 || effect_sp == 38400)) ) 3758 if ( ( mod % effect_sp ) != 0 ) 3759 return(-1); 3760 if ( effect_sp != speed ) 3761 count |= 0x10000; 3762 break; 3763#ifdef COM_IF_PC9861K 3764 case COM_IF_PC9861K: 3765 effect_sp = speed; 3766 count = 1; 3767 break; 3768#endif 3769#ifdef COM_IF_PIO9032B 3770 case COM_IF_PIO9032B: 3771 if ( speed == 0 ) return 0; 3772 count = ttspeedtab( speed, comspeedtab_pio9032b ); 3773 if ( count < 0 ) return count; 3774 effect_sp = speed; 3775 break; 3776#endif 3777#ifdef COM_IF_B98_01 3778 case COM_IF_B98_01: 3779 effect_sp=speed; 3780 count = ttspeedtab( speed, comspeedtab_b98_01 ); 3781 if ( count <= 3 ) 3782 return -1; /* invalid speed/count */ 3783 if ( count <= 5 ) 3784 count |= 0x10000; /* x1 mode for 76800 and 153600 */ 3785 else 3786 count -= 4; /* x16 mode for slower */ 3787 break; 3788#endif 3789 } 3790 return count; 3791} 3792 3793static void 3794pc98_set_baud_rate( struct com_s *com, int count) 3795{ 3796 int s; 3797 3798 switch ( com->pc98_if_type ) { 3799 case COM_IF_INTERNAL: 3800 if ( count < 0 ) { 3801 printf( "[ Illegal count : %d ]", count ); 3802 return; 3803 } else if ( count == 0) 3804 return; 3805 /* set i8253 */ 3806 s = splclock(); 3807 outb( 0x77, 0xb6 ); 3808 outb( 0x5f, 0); 3809 outb( 0x75, count & 0xff ); 3810 outb( 0x5f, 0); 3811 outb( 0x75, (count >> 8) & 0xff ); 3812 splx(s); 3813 break; 3814#if 0 3815#ifdef COM_IF_PC9861K 3816 case COM_IF_PC9861K: 3817 break; 3818 /* ext. RS232C board: speed is determined by DIP switch */ 3819#endif 3820#endif /* 0 */ 3821#ifdef COM_IF_PIO9032B 3822 case COM_IF_PIO9032B: 3823 outb( com_addr[unit], count & 0x07 ); 3824 break; 3825#endif 3826#ifdef COM_IF_B98_01 3827 case COM_IF_B98_01: 3828 outb( com->iobase, count & 0x0f ); 3829#ifdef B98_01_OLD 3830 /* some old board should be controlled in different way, 3831 but this hasn't been tested yet.*/ 3832 outb( com->iobase+2, ( count & 0x10000 ) ? 0xf0 : 0xf2 ); 3833#endif 3834 break; 3835#endif 3836 } 3837} 3838static int 3839pc98_check_if_type( int iobase, struct siodev *iod) 3840{ 3841 int irr = 0, tmp = 0; 3842 int ret = 0; 3843 static short irq_tab[2][8] = { 3844 { 3, 5, 6, 9, 10, 12, 13, -1}, 3845 { 3, 10, 12, 13, 5, 6, 9, -1} 3846 }; 3847 iod->irq = 0; 3848 switch ( iobase & 0xff ) { 3849 case IO_COM1: 3850 iod->if_type = COM_IF_INTERNAL; 3851 ret = 0; iod->irq = 4; break; 3852#ifdef COM_IF_PC9861K 3853 case IO_COM2: 3854 iod->if_type = COM_IF_PC9861K; 3855 ret = 1; irr = 0; tmp = 3; break; 3856 case IO_COM3: 3857 iod->if_type = COM_IF_PC9861K; 3858 ret = 2; irr = 1; tmp = 3; break; 3859#endif 3860#ifdef COM_IF_PIO9032B 3861 case IO_COM_PIO9032B_2: 3862 iod->if_type = COM_IF_PIO9032B; 3863 ret = 1; irr = 0; tmp = 7; break; 3864 case IO_COM_PIO9032B_3: 3865 iod->if_type = COM_IF_PIO9032B; 3866 ret = 2; irr = 1; tmp = 7; break; 3867#endif 3868#ifdef COM_IF_B98_01 3869 case IO_COM_B98_01_2: 3870 iod->if_type = COM_IF_B98_01; 3871 ret = 1; irr = 0; tmp = 7; 3872 outb(iobase + 2, 0xf2); 3873 outb(iobase, 4); 3874 break; 3875 case IO_COM_B98_01_3: 3876 iod->if_type = COM_IF_B98_01; 3877 ret = 2; irr = 1; tmp = 7; 3878 outb(iobase + 2, 0xf2); 3879 outb(iobase , 4); 3880 break; 3881#endif 3882 default: 3883 if((iobase & 0x0f0) == 0xd0){ 3884 iod->if_type = MC16550; 3885 return 0; 3886 } 3887 return -1; 3888 } 3889 3890 iod->cmd = ( iobase & 0xff00 )|PC98SIO_cmd_port(ret); 3891 iod->sts = ( iobase & 0xff00 )|PC98SIO_sts_port(ret); 3892 iod->mod = ( iobase & 0xff00 )|PC98SIO_in_modem_port(ret); 3893 iod->ctrl = ( iobase & 0xff00 )|PC98SIO_intr_ctrl_port(ret); 3894 3895 if ( iod->irq == 0 ) { 3896 tmp &= inb( iod->mod ); 3897 iod->irq = irq_tab[irr][tmp]; 3898 if ( iod->irq == -1 ) return -1; 3899 } 3900 return 0; 3901} 3902static int 3903pc98_set_ioport( struct com_s *com, int io_base ) 3904{ 3905 int a, io, type; 3906 3907 switch ( io_base & 0xff ) { 3908 case IO_COM1: a = 0; io = 0; type = COM_IF_INTERNAL; 3909 pc98_check_sysclock(); break; 3910#ifdef COM_IF_PC9861K 3911 case IO_COM2: a = 1; io = 0; type = COM_IF_PC9861K; break; 3912 case IO_COM3: a = 2; io = 0; type = COM_IF_PC9861K; break; 3913#endif /* COM_IF_PC9861K */ 3914#ifdef COM_IF_PIO9032B 3915 /* PIO9032B : I/O address is changeable */ 3916 case IO_COM_PIO9032B_2: 3917 a = 1; io = io_base & 0xff00; 3918 type = COM_IF_PIO9032B; break; 3919 case IO_COM_PIO9032B_3: 3920 a = 2; io = io_base & 0xff00; 3921 type = COM_IF_PIO9032B; break; 3922#endif /* COM_IF_PIO9032B */ 3923#ifdef COM_IF_B98_01 3924 case IO_COM_B98_01_2: 3925 a = 1; io = 0; type = COM_IF_B98_01; break; 3926 case IO_COM_B98_01_3: 3927 a = 2; io = 0; type = COM_IF_B98_01; break; 3928#endif /* COM_IF_B98_01*/ 3929 default: /* i/o address not match */ 3930 return -1; 3931 } 3932 3933 com->pc98_if_type = type; 3934 com->data_port = io | PC98SIO_data_port(a); 3935 com->cmd_port = io | PC98SIO_cmd_port(a); 3936 com->sts_port = io | PC98SIO_sts_port(a); 3937 com->in_modem_port = io | PC98SIO_in_modem_port(a); 3938 com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(a); 3939 return 0; 3940} 3941#endif /* PC98 defined */ 3942