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