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