sio.c revision 52585
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 * $FreeBSD: head/sys/dev/sio/sio.c 52585 1999-10-28 05:06:14Z imp $ 34 * from: @(#)com.c 7.5 (Berkeley) 5/16/91 35 * from: i386/isa sio.c,v 1.234 36 */ 37 38#include "opt_comconsole.h" 39#include "opt_compat.h" 40#include "opt_ddb.h" 41#include "opt_sio.h" 42#include "sio.h" 43 44/* 45 * Serial driver, based on 386BSD-0.1 com driver. 46 * Mostly rewritten to use pseudo-DMA. 47 * Works for National Semiconductor NS8250-NS16550AF UARTs. 48 * COM driver, based on HP dca driver. 49 * 50 * Changes for PC-Card integration: 51 * - Added PC-Card driver table and handlers 52 */ 53#include <sys/param.h> 54#include <sys/systm.h> 55#include <sys/reboot.h> 56#include <sys/malloc.h> 57#include <sys/tty.h> 58#include <sys/proc.h> 59#include <sys/module.h> 60#include <sys/conf.h> 61#include <sys/dkstat.h> 62#include <sys/fcntl.h> 63#include <sys/interrupt.h> 64#include <sys/kernel.h> 65#include <sys/syslog.h> 66#include <sys/sysctl.h> 67#include <sys/bus.h> 68#include <machine/bus.h> 69#include <sys/rman.h> 70#include <sys/timepps.h> 71 72#include <isa/isareg.h> 73#include <isa/isavar.h> 74#include <machine/lock.h> 75 76#include <machine/clock.h> 77#include <machine/ipl.h> 78#ifndef SMP 79#include <machine/lock.h> 80#endif 81#include <machine/resource.h> 82 83#include <isa/sioreg.h> 84 85#ifdef COM_ESP 86#include <isa/ic/esp.h> 87#endif 88#include <isa/ic/ns16550.h> 89 90#include "card.h" 91#if NCARD > 0 92/* XXX should die XXX */ 93#include <sys/select.h> 94#include <sys/module.h> 95#include <pccard/cardinfo.h> 96#include <pccard/slot.h> 97#endif 98 99#ifndef __i386__ 100#define disable_intr() 101#define enable_intr() 102#endif 103 104#ifdef SMP 105#define disable_intr() COM_DISABLE_INTR() 106#define enable_intr() COM_ENABLE_INTR() 107#endif /* SMP */ 108 109#ifndef EXTRA_SIO 110#define EXTRA_SIO 4 /* XXX shouldn't need NSIO */ 111#endif 112 113#define NSIOTOT (NSIO + EXTRA_SIO) 114 115#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 116 117#define CALLOUT_MASK 0x80 118#define CONTROL_MASK 0x60 119#define CONTROL_INIT_STATE 0x20 120#define CONTROL_LOCK_STATE 0x40 121#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 122#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 123#define MINOR_TO_UNIT(mynor) ((mynor) & ~MINOR_MAGIC_MASK) 124 125#ifdef COM_MULTIPORT 126/* checks in flags for multiport and which is multiport "master chip" 127 * for a given card 128 */ 129#define COM_ISMULTIPORT(flags) ((flags) & 0x01) 130#define COM_MPMASTER(flags) (((flags) >> 8) & 0x0ff) 131#define COM_NOTAST4(flags) ((flags) & 0x04) 132#endif /* COM_MULTIPORT */ 133 134#define COM_CONSOLE(flags) ((flags) & 0x10) 135#define COM_FORCECONSOLE(flags) ((flags) & 0x20) 136#define COM_LLCONSOLE(flags) ((flags) & 0x40) 137#define COM_DEBUGGER(flags) ((flags) & 0x80) 138#define COM_LOSESOUTINTS(flags) ((flags) & 0x08) 139#define COM_NOFIFO(flags) ((flags) & 0x02) 140#define COM_ST16650A(flags) ((flags) & 0x20000) 141#define COM_C_NOPROBE (0x40000) 142#define COM_NOPROBE(flags) ((flags) & COM_C_NOPROBE) 143#define COM_C_IIR_TXRDYBUG (0x80000) 144#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG) 145#define COM_FIFOSIZE(flags) (((flags) & 0xff000000) >> 24) 146 147#define com_scr 7 /* scratch register for 16450-16550 (R/W) */ 148 149/* 150 * com state bits. 151 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 152 * than the other bits so that they can be tested as a group without masking 153 * off the low bits. 154 * 155 * The following com and tty flags correspond closely: 156 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and 157 * siostop()) 158 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) 159 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 160 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 161 * TS_FLUSH is not used. 162 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 163 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 164 */ 165#define CS_BUSY 0x80 /* output in progress */ 166#define CS_TTGO 0x40 /* output not stopped by XOFF */ 167#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 168#define CS_CHECKMSR 1 /* check of MSR scheduled */ 169#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 170#define CS_DTR_OFF 0x10 /* DTR held off */ 171#define CS_ODONE 4 /* output completed */ 172#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 173#define CSE_BUSYCHECK 1 /* siobusycheck() scheduled */ 174 175static char const * const error_desc[] = { 176#define CE_OVERRUN 0 177 "silo overflow", 178#define CE_INTERRUPT_BUF_OVERFLOW 1 179 "interrupt-level buffer overflow", 180#define CE_TTY_BUF_OVERFLOW 2 181 "tty-level buffer overflow", 182}; 183 184#define CE_NTYPES 3 185#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 186 187/* types. XXX - should be elsewhere */ 188typedef u_int Port_t; /* hardware port */ 189typedef u_char bool_t; /* boolean */ 190 191/* queue of linear buffers */ 192struct lbq { 193 u_char *l_head; /* next char to process */ 194 u_char *l_tail; /* one past the last char to process */ 195 struct lbq *l_next; /* next in queue */ 196 bool_t l_queued; /* nonzero if queued */ 197}; 198 199/* com device structure */ 200struct com_s { 201 u_int flags; /* Copy isa device flags */ 202 u_char state; /* miscellaneous flag bits */ 203 bool_t active_out; /* nonzero if the callout device is open */ 204 u_char cfcr_image; /* copy of value written to CFCR */ 205#ifdef COM_ESP 206 bool_t esp; /* is this unit a hayes esp board? */ 207#endif 208 u_char extra_state; /* more flag bits, separate for order trick */ 209 u_char fifo_image; /* copy of value written to FIFO */ 210 bool_t hasfifo; /* nonzero for 16550 UARTs */ 211 bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */ 212 bool_t loses_outints; /* nonzero if device loses output interrupts */ 213 u_char mcr_image; /* copy of value written to MCR */ 214#ifdef COM_MULTIPORT 215 bool_t multiport; /* is this unit part of a multiport device? */ 216#endif /* COM_MULTIPORT */ 217 bool_t no_irq; /* nonzero if irq is not attached */ 218 bool_t gone; /* hardware disappeared */ 219 bool_t poll; /* nonzero if polling is required */ 220 bool_t poll_output; /* nonzero if polling for output is required */ 221 int unit; /* unit number */ 222 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 223 u_int tx_fifo_size; 224 u_int wopeners; /* # processes waiting for DCD in open() */ 225 226 /* 227 * The high level of the driver never reads status registers directly 228 * because there would be too many side effects to handle conveniently. 229 * Instead, it reads copies of the registers stored here by the 230 * interrupt handler. 231 */ 232 u_char last_modem_status; /* last MSR read by intr handler */ 233 u_char prev_modem_status; /* last MSR handled by high level */ 234 235 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 236 u_char *ibuf; /* start of input buffer */ 237 u_char *ibufend; /* end of input buffer */ 238 u_char *ibufold; /* old input buffer, to be freed */ 239 u_char *ihighwater; /* threshold in input buffer */ 240 u_char *iptr; /* next free spot in input buffer */ 241 int ibufsize; /* size of ibuf (not include error bytes) */ 242 int ierroff; /* offset of error bytes in ibuf */ 243 244 struct lbq obufq; /* head of queue of output buffers */ 245 struct lbq obufs[2]; /* output buffers */ 246 247 Port_t data_port; /* i/o ports */ 248#ifdef COM_ESP 249 Port_t esp_port; 250#endif 251 Port_t int_id_port; 252 Port_t iobase; 253 Port_t modem_ctl_port; 254 Port_t line_status_port; 255 Port_t modem_status_port; 256 Port_t intr_ctl_port; /* Ports of IIR register */ 257 258 struct tty *tp; /* cross reference */ 259 260 /* Initial state. */ 261 struct termios it_in; /* should be in struct tty */ 262 struct termios it_out; 263 264 /* Lock state. */ 265 struct termios lt_in; /* should be in struct tty */ 266 struct termios lt_out; 267 268 bool_t do_timestamp; 269 bool_t do_dcd_timestamp; 270 struct timeval timestamp; 271 struct timeval dcd_timestamp; 272 struct pps_state pps; 273 274 u_long bytes_in; /* statistics */ 275 u_long bytes_out; 276 u_int delta_error_counts[CE_NTYPES]; 277 u_long error_counts[CE_NTYPES]; 278 279 struct resource *irqres; 280 struct resource *ioportres; 281 282 /* 283 * Data area for output buffers. Someday we should build the output 284 * buffer queue without copying data. 285 */ 286 u_char obuf1[256]; 287 u_char obuf2[256]; 288}; 289 290#ifdef COM_ESP 291static int espattach __P((struct com_s *com, Port_t esp_port)); 292#endif 293static int sioattach __P((device_t dev)); 294static int sio_isa_attach __P((device_t dev)); 295 296static timeout_t siobusycheck; 297static timeout_t siodtrwakeup; 298static void comhardclose __P((struct com_s *com)); 299static void sioinput __P((struct com_s *com)); 300static void siointr1 __P((struct com_s *com)); 301static void siointr __P((void *arg)); 302static int commctl __P((struct com_s *com, int bits, int how)); 303static int comparam __P((struct tty *tp, struct termios *t)); 304static swihand_t siopoll; 305static int sioprobe __P((device_t dev)); 306static int sio_isa_probe __P((device_t dev)); 307static void siosettimeout __P((void)); 308static int siosetwater __P((struct com_s *com, speed_t speed)); 309static void comstart __P((struct tty *tp)); 310static void comstop __P((struct tty *tp, int rw)); 311static timeout_t comwakeup; 312static void disc_optim __P((struct tty *tp, struct termios *t, 313 struct com_s *com)); 314 315#if NCARD > 0 316static int sio_pccard_attach __P((device_t dev)); 317static void sio_pccard_detach __P((device_t dev)); 318static int sio_pccard_probe __P((device_t dev)); 319#endif /* NCARD > 0 */ 320 321static char driver_name[] = "sio"; 322 323/* table and macro for fast conversion from a unit number to its com struct */ 324static devclass_t sio_devclass; 325#define com_addr(unit) ((struct com_s *) \ 326 devclass_get_softc(sio_devclass, unit)) 327 328static device_method_t sio_isa_methods[] = { 329 /* Device interface */ 330 DEVMETHOD(device_probe, sio_isa_probe), 331 DEVMETHOD(device_attach, sio_isa_attach), 332 333 { 0, 0 } 334}; 335 336static driver_t sio_isa_driver = { 337 driver_name, 338 sio_isa_methods, 339 sizeof(struct com_s), 340}; 341 342#if NCARD > 0 343static device_method_t sio_pccard_methods[] = { 344 /* Device interface */ 345 DEVMETHOD(device_probe, sio_pccard_probe), 346 DEVMETHOD(device_attach, sio_pccard_attach), 347 DEVMETHOD(device_detach, sio_pccard_detach), 348 349 { 0, 0 } 350}; 351 352static driver_t sio_pccard_driver = { 353 driver_name, 354 sio_pccard_methods, 355 sizeof(struct com_s), 356}; 357#endif (NCARD > 0) 358 359static d_open_t sioopen; 360static d_close_t sioclose; 361static d_read_t sioread; 362static d_write_t siowrite; 363static d_ioctl_t sioioctl; 364 365#define CDEV_MAJOR 28 366static struct cdevsw sio_cdevsw = { 367 /* open */ sioopen, 368 /* close */ sioclose, 369 /* read */ sioread, 370 /* write */ siowrite, 371 /* ioctl */ sioioctl, 372 /* poll */ ttypoll, 373 /* mmap */ nommap, 374 /* strategy */ nostrategy, 375 /* name */ driver_name, 376 /* maj */ CDEV_MAJOR, 377 /* dump */ nodump, 378 /* psize */ nopsize, 379 /* flags */ D_TTY, 380 /* bmaj */ -1 381}; 382 383int comconsole = -1; 384static volatile speed_t comdefaultrate = CONSPEED; 385#ifdef __alpha__ 386static volatile speed_t gdbdefaultrate = CONSPEED; 387#endif 388static u_int com_events; /* input chars + weighted output completions */ 389static Port_t siocniobase; 390static int siocnunit; 391static Port_t siogdbiobase; 392static int siogdbunit = -1; 393static bool_t sio_registered; 394static int sio_timeout; 395static int sio_timeouts_until_log; 396static struct callout_handle sio_timeout_handle 397 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 398 399static struct speedtab comspeedtab[] = { 400 { 0, 0 }, 401 { 50, COMBRD(50) }, 402 { 75, COMBRD(75) }, 403 { 110, COMBRD(110) }, 404 { 134, COMBRD(134) }, 405 { 150, COMBRD(150) }, 406 { 200, COMBRD(200) }, 407 { 300, COMBRD(300) }, 408 { 600, COMBRD(600) }, 409 { 1200, COMBRD(1200) }, 410 { 1800, COMBRD(1800) }, 411 { 2400, COMBRD(2400) }, 412 { 4800, COMBRD(4800) }, 413 { 9600, COMBRD(9600) }, 414 { 19200, COMBRD(19200) }, 415 { 38400, COMBRD(38400) }, 416 { 57600, COMBRD(57600) }, 417 { 115200, COMBRD(115200) }, 418 { -1, -1 } 419}; 420 421#ifdef COM_ESP 422/* XXX configure this properly. */ 423static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, }; 424static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 }; 425#endif 426 427/* 428 * handle sysctl read/write requests for console speed 429 * 430 * In addition to setting comdefaultrate for I/O through /dev/console, 431 * also set the initial and lock values for the /dev/ttyXX device 432 * if there is one associated with the console. Finally, if the /dev/tty 433 * device has already been open, change the speed on the open running port 434 * itself. 435 */ 436 437static int 438sysctl_machdep_comdefaultrate SYSCTL_HANDLER_ARGS 439{ 440 int error, s; 441 speed_t newspeed; 442 struct com_s *com; 443 struct tty *tp; 444 445 newspeed = comdefaultrate; 446 447 error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req); 448 if (error || !req->newptr) 449 return (error); 450 451 comdefaultrate = newspeed; 452 453 if (comconsole < 0) /* serial console not selected? */ 454 return (0); 455 456 com = com_addr(comconsole); 457 if (!com) 458 return (ENXIO); 459 460 /* 461 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX 462 * (note, the lock rates really are boolean -- if non-zero, disallow 463 * speed changes) 464 */ 465 com->it_in.c_ispeed = com->it_in.c_ospeed = 466 com->lt_in.c_ispeed = com->lt_in.c_ospeed = 467 com->it_out.c_ispeed = com->it_out.c_ospeed = 468 com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate; 469 470 /* 471 * if we're open, change the running rate too 472 */ 473 tp = com->tp; 474 if (tp && (tp->t_state & TS_ISOPEN)) { 475 tp->t_termios.c_ispeed = 476 tp->t_termios.c_ospeed = comdefaultrate; 477 s = spltty(); 478 error = comparam(tp, &tp->t_termios); 479 splx(s); 480 } 481 return error; 482} 483 484SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW, 485 0, 0, sysctl_machdep_comdefaultrate, "I", ""); 486 487#if NCARD > 0 488static int 489sio_pccard_probe(dev) 490 device_t dev; 491{ 492 return (sioprobe(dev)); 493} 494 495static int 496sio_pccard_attach(dev) 497 device_t dev; 498{ 499 return (sioattach(dev)); 500} 501 502/* 503 * sio_detach - unload the driver and clear the table. 504 * XXX TODO: 505 * This is usually called when the card is ejected, but 506 * can be caused by a modunload of a controller driver. 507 * The idea is to reset the driver's view of the device 508 * and ensure that any driver entry points such as 509 * read and write do not hang. 510 */ 511static void 512sio_pccard_detach(dev) 513 device_t dev; 514{ 515 struct com_s *com; 516 517 com = (struct com_s *) device_get_softc(dev); 518 if (!com) { 519 device_printf(dev, "NULL com in siounload\n"); 520 return; 521 } 522 if (!com->iobase) { 523 device_printf(dev, "already unloaded!\n"); 524 return; 525 } 526 if (com->tp && (com->tp->t_state & TS_ISOPEN)) { 527 com->gone = 1; 528 device_printf(dev, "unload\n"); 529 com->tp->t_gen++; 530 ttyclose(com->tp); 531 ttwakeup(com->tp); 532 ttwwakeup(com->tp); 533 } else { 534 if (com->ibuf != NULL) 535 free(com->ibuf, M_DEVBUF); 536 free(com, M_DEVBUF); 537 device_printf(dev, "unload,gone\n"); 538 } 539} 540#endif /* NCARD > 0 */ 541 542#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit)) 543#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit)) 544 545static struct isa_pnp_id sio_ids[] = { 546 {0x0005d041, "Standard PC COM port"}, /* PNP0500 */ 547 {0x0105d041, "16550A-compatible COM port"}, /* PNP0501 */ 548 {0x0205d041, "Multiport serial device (non-intelligent 16550)"}, /* PNP0502 */ 549 {0x1005d041, "Generic IRDA-compatible device"}, /* PNP0510 */ 550 {0x1105d041, "Generic IRDA-compatible device"}, /* PNP0511 */ 551 {0x01017256, NULL}, /* USR0101 */ 552 {0x30207256, NULL}, /* USR2030 */ 553 {0x31307256, NULL}, /* USR3031 */ 554 {0x8020b04e, NULL}, /* SUP2080 */ 555 {0x8024b04e, NULL}, /* SUP2480 */ 556 {0} 557}; 558 559static int 560sio_isa_probe(dev) 561 device_t dev; 562{ 563 /* Check isapnp ids */ 564 if (ISA_PNP_PROBE(device_get_parent(dev), dev, sio_ids) == ENXIO) 565 return (ENXIO); 566 return (sioprobe(dev)); 567} 568 569static int 570sioprobe(dev) 571 device_t dev; 572{ 573 static bool_t already_init; 574 bool_t failures[10]; 575 int fn; 576 device_t idev; 577 Port_t iobase; 578 intrmask_t irqmap[4]; 579 intrmask_t irqs; 580 u_char mcr_image; 581 int result; 582 device_t xdev; 583 u_int flags = device_get_flags(dev); 584 int rid; 585 struct resource *port; 586 587 rid = 0; 588 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 589 0, ~0, IO_COMSIZE, RF_ACTIVE); 590 if (!port) 591 return ENXIO; 592 593 if (!already_init) { 594 /* 595 * Turn off MCR_IENABLE for all likely serial ports. An unused 596 * port with its MCR_IENABLE gate open will inhibit interrupts 597 * from any used port that shares the interrupt vector. 598 * XXX the gate enable is elsewhere for some multiports. 599 */ 600 device_t *devs; 601 int count, i; 602 603 devclass_get_devices(sio_devclass, &devs, &count); 604 for (i = 0; i < count; i++) { 605 xdev = devs[i]; 606 if (device_is_enabled(xdev)) 607 outb(isa_get_port(xdev) + com_mcr, 0); 608 } 609 free(devs, M_TEMP); 610 already_init = TRUE; 611 } 612 613 if (COM_LLCONSOLE(flags)) { 614 printf("sio%d: reserved for low-level i/o\n", 615 device_get_unit(dev)); 616 return (ENXIO); 617 } 618 619 /* 620 * If the device is on a multiport card and has an AST/4 621 * compatible interrupt control register, initialize this 622 * register and prepare to leave MCR_IENABLE clear in the mcr. 623 * Otherwise, prepare to set MCR_IENABLE in the mcr. 624 * Point idev to the device struct giving the correct id_irq. 625 * This is the struct for the master device if there is one. 626 */ 627 idev = dev; 628 mcr_image = MCR_IENABLE; 629#ifdef COM_MULTIPORT 630 if (COM_ISMULTIPORT(flags)) { 631 idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags)); 632 if (idev == NULL) { 633 printf("sio%d: master device %d not configured\n", 634 device_get_unit(dev), COM_MPMASTER(flags)); 635 idev = dev; 636 } 637 if (!COM_NOTAST4(flags)) { 638 outb(isa_get_port(idev) + com_scr, 639 isa_get_irq(idev) >= 0 ? 0x80 : 0); 640 mcr_image = 0; 641 } 642 } 643#endif /* COM_MULTIPORT */ 644 if (isa_get_irq(idev) < 0) 645 mcr_image = 0; 646 647 bzero(failures, sizeof failures); 648 iobase = rman_get_start(port); 649 650 /* 651 * We don't want to get actual interrupts, just masked ones. 652 * Interrupts from this line should already be masked in the ICU, 653 * but mask them in the processor as well in case there are some 654 * (misconfigured) shared interrupts. 655 */ 656 disable_intr(); 657/* EXTRA DELAY? */ 658 659 /* 660 * Initialize the speed and the word size and wait long enough to 661 * drain the maximum of 16 bytes of junk in device output queues. 662 * The speed is undefined after a master reset and must be set 663 * before relying on anything related to output. There may be 664 * junk after a (very fast) soft reboot and (apparently) after 665 * master reset. 666 * XXX what about the UART bug avoided by waiting in comparam()? 667 * We don't want to to wait long enough to drain at 2 bps. 668 */ 669 if (iobase == siocniobase) 670 DELAY((16 + 1) * 1000000 / (comdefaultrate / 10)); 671 else { 672 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 673 outb(iobase + com_dlbl, COMBRD(SIO_TEST_SPEED) & 0xff); 674 outb(iobase + com_dlbh, (u_int) COMBRD(SIO_TEST_SPEED) >> 8); 675 outb(iobase + com_cfcr, CFCR_8BITS); 676 DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10)); 677 } 678 679 /* 680 * Enable the interrupt gate and disable device interupts. This 681 * should leave the device driving the interrupt line low and 682 * guarantee an edge trigger if an interrupt can be generated. 683 */ 684/* EXTRA DELAY? */ 685 outb(iobase + com_mcr, mcr_image); 686 outb(iobase + com_ier, 0); 687 DELAY(1000); /* XXX */ 688 irqmap[0] = isa_irq_pending(); 689 690 /* 691 * Attempt to set loopback mode so that we can send a null byte 692 * without annoying any external device. 693 */ 694/* EXTRA DELAY? */ 695 outb(iobase + com_mcr, mcr_image | MCR_LOOPBACK); 696 697 /* 698 * Attempt to generate an output interrupt. On 8250's, setting 699 * IER_ETXRDY generates an interrupt independent of the current 700 * setting and independent of whether the THR is empty. On 16450's, 701 * setting IER_ETXRDY generates an interrupt independent of the 702 * current setting. On 16550A's, setting IER_ETXRDY only 703 * generates an interrupt when IER_ETXRDY is not already set. 704 */ 705 outb(iobase + com_ier, IER_ETXRDY); 706 707 /* 708 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate 709 * an interrupt. They'd better generate one for actually doing 710 * output. Loopback may be broken on the same incompatibles but 711 * it's unlikely to do more than allow the null byte out. 712 */ 713 outb(iobase + com_data, 0); 714 DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10)); 715 716 /* 717 * Turn off loopback mode so that the interrupt gate works again 718 * (MCR_IENABLE was hidden). This should leave the device driving 719 * an interrupt line high. It doesn't matter if the interrupt 720 * line oscillates while we are not looking at it, since interrupts 721 * are disabled. 722 */ 723/* EXTRA DELAY? */ 724 outb(iobase + com_mcr, mcr_image); 725 726 /* 727 * Some pcmcia cards have the "TXRDY bug", so we check everyone 728 * for IIR_TXRDY implementation ( Palido 321s, DC-1S... ) 729 * XXX Bruce, is this OK? XXX 730 */ 731#if 0 732 /* Reading IIR register twice */ 733 for ( fn = 0; fn < 2; fn ++ ) { 734 DELAY(10000); 735 failures[6] = inb(iobase + com_iir); 736 } 737 /* Check IIR_TXRDY clear ? */ 738 result = 0; 739 if ( failures[6] & IIR_TXRDY ) { 740 /* Nop, Double check with clearing IER */ 741 outb(iobase + com_ier, 0); 742 if ( inb(iobase + com_iir) & IIR_NOPEND ) { 743 /* Ok. we're familia this gang */ 744 SET_FLAG(dev, COM_C_IIR_TXRDYBUG); /* Set IIR_TXRDYBUG */ 745 } else { 746 /* Unknown, Just omit this chip.. XXX */ 747 result = ENXIO; 748 } 749 } else { 750 /* OK. this is well-known guys */ 751 CLR_FLAG(dev, COM_C_IIR_TXRDYBUG); /*Clear IIR_TXRDYBUG*/ 752 } 753#endif 754 /* 755 * Check that 756 * o the CFCR, IER and MCR in UART hold the values written to them 757 * (the values happen to be all distinct - this is good for 758 * avoiding false positive tests from bus echoes). 759 * o an output interrupt is generated and its vector is correct. 760 * o the interrupt goes away when the IIR in the UART is read. 761 */ 762/* EXTRA DELAY? */ 763 failures[0] = inb(iobase + com_cfcr) - CFCR_8BITS; 764 failures[1] = inb(iobase + com_ier) - IER_ETXRDY; 765 failures[2] = inb(iobase + com_mcr) - mcr_image; 766 DELAY(10000); /* Some internal modems need this time */ 767 irqmap[1] = isa_irq_pending(); 768 failures[4] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_TXRDY; 769 DELAY(1000); /* XXX */ 770 irqmap[2] = isa_irq_pending(); 771 failures[6] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; 772 773 /* 774 * Turn off all device interrupts and check that they go off properly. 775 * Leave MCR_IENABLE alone. For ports without a master port, it gates 776 * the OUT2 output of the UART to 777 * the ICU input. Closing the gate would give a floating ICU input 778 * (unless there is another device driving it) and spurious interrupts. 779 * (On the system that this was first tested on, the input floats high 780 * and gives a (masked) interrupt as soon as the gate is closed.) 781 */ 782 outb(iobase + com_ier, 0); 783 outb(iobase + com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */ 784 failures[7] = inb(iobase + com_ier); 785 DELAY(1000); /* XXX */ 786 irqmap[3] = isa_irq_pending(); 787 failures[9] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; 788 789 enable_intr(); 790 791 irqs = irqmap[1] & ~irqmap[0]; 792 if (isa_get_irq(idev) >= 0 && ((1 << isa_get_irq(idev)) & irqs) == 0) 793 printf( 794 "sio%d: configured irq %d not in bitmap of probed irqs %#x\n", 795 device_get_unit(dev), isa_get_irq(idev), irqs); 796 if (bootverbose) 797 printf("sio%d: irq maps: %#x %#x %#x %#x\n", 798 device_get_unit(dev), 799 irqmap[0], irqmap[1], irqmap[2], irqmap[3]); 800 801 result = 0; 802 for (fn = 0; fn < sizeof failures; ++fn) 803 if (failures[fn]) { 804 outb(iobase + com_mcr, 0); 805 result = ENXIO; 806 if (bootverbose) { 807 printf("sio%d: probe failed test(s):", 808 device_get_unit(dev)); 809 for (fn = 0; fn < sizeof failures; ++fn) 810 if (failures[fn]) 811 printf(" %d", fn); 812 printf("\n"); 813 } 814 break; 815 } 816 bus_release_resource(dev, SYS_RES_IOPORT, rid, port); 817 return (iobase == siocniobase ? 0 : result); 818} 819 820#ifdef COM_ESP 821static int 822espattach(com, esp_port) 823 struct com_s *com; 824 Port_t esp_port; 825{ 826 u_char dips; 827 u_char val; 828 829 /* 830 * Check the ESP-specific I/O port to see if we're an ESP 831 * card. If not, return failure immediately. 832 */ 833 if ((inb(esp_port) & 0xf3) == 0) { 834 printf(" port 0x%x is not an ESP board?\n", esp_port); 835 return (0); 836 } 837 838 /* 839 * We've got something that claims to be a Hayes ESP card. 840 * Let's hope so. 841 */ 842 843 /* Get the dip-switch configuration */ 844 outb(esp_port + ESP_CMD1, ESP_GETDIPS); 845 dips = inb(esp_port + ESP_STATUS1); 846 847 /* 848 * Bits 0,1 of dips say which COM port we are. 849 */ 850 if (com->iobase == likely_com_ports[dips & 0x03]) 851 printf(" : ESP"); 852 else { 853 printf(" esp_port has com %d\n", dips & 0x03); 854 return (0); 855 } 856 857 /* 858 * Check for ESP version 2.0 or later: bits 4,5,6 = 010. 859 */ 860 outb(esp_port + ESP_CMD1, ESP_GETTEST); 861 val = inb(esp_port + ESP_STATUS1); /* clear reg 1 */ 862 val = inb(esp_port + ESP_STATUS2); 863 if ((val & 0x70) < 0x20) { 864 printf("-old (%o)", val & 0x70); 865 return (0); 866 } 867 868 /* 869 * Check for ability to emulate 16550: bit 7 == 1 870 */ 871 if ((dips & 0x80) == 0) { 872 printf(" slave"); 873 return (0); 874 } 875 876 /* 877 * Okay, we seem to be a Hayes ESP card. Whee. 878 */ 879 com->esp = TRUE; 880 com->esp_port = esp_port; 881 return (1); 882} 883#endif /* COM_ESP */ 884 885static int 886sio_isa_attach(dev) 887 device_t dev; 888{ 889 return (sioattach(dev)); 890} 891 892static int 893sioattach(dev) 894 device_t dev; 895{ 896 struct com_s *com; 897#ifdef COM_ESP 898 Port_t *espp; 899#endif 900 Port_t iobase; 901 int unit; 902 void *ih; 903 u_int flags = device_get_flags(dev); 904 int rid; 905 struct resource *port; 906 907 rid = 0; 908 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 909 0, ~0, IO_COMSIZE, RF_ACTIVE); 910 if (!port) 911 return ENXIO; 912 913 iobase = rman_get_start(port); 914 unit = device_get_unit(dev); 915 com = device_get_softc(dev); 916 917 /* 918 * sioprobe() has initialized the device registers as follows: 919 * o cfcr = CFCR_8BITS. 920 * It is most important that CFCR_DLAB is off, so that the 921 * data port is not hidden when we enable interrupts. 922 * o ier = 0. 923 * Interrupts are only enabled when the line is open. 924 * o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible 925 * interrupt control register or the config specifies no irq. 926 * Keeping MCR_DTR and MCR_RTS off might stop the external 927 * device from sending before we are ready. 928 */ 929 bzero(com, sizeof *com); 930 com->unit = unit; 931 com->ioportres = port; 932 com->cfcr_image = CFCR_8BITS; 933 com->dtr_wait = 3 * hz; 934 com->loses_outints = COM_LOSESOUTINTS(flags) != 0; 935 com->no_irq = isa_get_irq(dev) < 0; 936 com->tx_fifo_size = 1; 937 com->obufs[0].l_head = com->obuf1; 938 com->obufs[1].l_head = com->obuf2; 939 940 com->iobase = iobase; 941 com->data_port = iobase + com_data; 942 com->int_id_port = iobase + com_iir; 943 com->modem_ctl_port = iobase + com_mcr; 944 com->mcr_image = inb(com->modem_ctl_port); 945 com->line_status_port = iobase + com_lsr; 946 com->modem_status_port = iobase + com_msr; 947 com->intr_ctl_port = iobase + com_ier; 948 949 /* 950 * We don't use all the flags from <sys/ttydefaults.h> since they 951 * are only relevant for logins. It's important to have echo off 952 * initially so that the line doesn't start blathering before the 953 * echo flag can be turned off. 954 */ 955 com->it_in.c_iflag = 0; 956 com->it_in.c_oflag = 0; 957 com->it_in.c_cflag = TTYDEF_CFLAG; 958 com->it_in.c_lflag = 0; 959 if (unit == comconsole) { 960 com->it_in.c_iflag = TTYDEF_IFLAG; 961 com->it_in.c_oflag = TTYDEF_OFLAG; 962 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 963 com->it_in.c_lflag = TTYDEF_LFLAG; 964 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 965 com->lt_out.c_ispeed = com->lt_out.c_ospeed = 966 com->lt_in.c_ispeed = com->lt_in.c_ospeed = 967 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 968 } else 969 com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED; 970 if (siosetwater(com, com->it_in.c_ispeed) != 0) { 971 enable_intr(); 972 free(com, M_DEVBUF); 973 return (0); 974 } 975 enable_intr(); 976 termioschars(&com->it_in); 977 com->it_out = com->it_in; 978 979 /* attempt to determine UART type */ 980 printf("sio%d: type", unit); 981 982 983#ifdef COM_MULTIPORT 984 if (!COM_ISMULTIPORT(flags) && !COM_IIR_TXRDYBUG(flags)) 985#else 986 if (!COM_IIR_TXRDYBUG(flags)) 987#endif 988 { 989 u_char scr; 990 u_char scr1; 991 u_char scr2; 992 993 scr = inb(iobase + com_scr); 994 outb(iobase + com_scr, 0xa5); 995 scr1 = inb(iobase + com_scr); 996 outb(iobase + com_scr, 0x5a); 997 scr2 = inb(iobase + com_scr); 998 outb(iobase + com_scr, scr); 999 if (scr1 != 0xa5 || scr2 != 0x5a) { 1000 printf(" 8250"); 1001 goto determined_type; 1002 } 1003 } 1004 outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RX_HIGH); 1005 DELAY(100); 1006 com->st16650a = 0; 1007 switch (inb(com->int_id_port) & IIR_FIFO_MASK) { 1008 case FIFO_RX_LOW: 1009 printf(" 16450"); 1010 break; 1011 case FIFO_RX_MEDL: 1012 printf(" 16450?"); 1013 break; 1014 case FIFO_RX_MEDH: 1015 printf(" 16550?"); 1016 break; 1017 case FIFO_RX_HIGH: 1018 if (COM_NOFIFO(flags)) { 1019 printf(" 16550A fifo disabled"); 1020 } else { 1021 com->hasfifo = TRUE; 1022 if (COM_ST16650A(flags)) { 1023 com->st16650a = 1; 1024 com->tx_fifo_size = 32; 1025 printf(" ST16650A"); 1026 } else { 1027 com->tx_fifo_size = COM_FIFOSIZE(flags); 1028 printf(" 16550A"); 1029 } 1030 } 1031#ifdef COM_ESP 1032 for (espp = likely_esp_ports; *espp != 0; espp++) 1033 if (espattach(com, *espp)) { 1034 com->tx_fifo_size = 1024; 1035 break; 1036 } 1037#endif 1038 if (!com->st16650a) { 1039 if (!com->tx_fifo_size) 1040 com->tx_fifo_size = 16; 1041 else 1042 printf(" lookalike with %d bytes FIFO", 1043 com->tx_fifo_size); 1044 } 1045 1046 break; 1047 } 1048 1049#ifdef COM_ESP 1050 if (com->esp) { 1051 /* 1052 * Set 16550 compatibility mode. 1053 * We don't use the ESP_MODE_SCALE bit to increase the 1054 * fifo trigger levels because we can't handle large 1055 * bursts of input. 1056 * XXX flow control should be set in comparam(), not here. 1057 */ 1058 outb(com->esp_port + ESP_CMD1, ESP_SETMODE); 1059 outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); 1060 1061 /* Set RTS/CTS flow control. */ 1062 outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE); 1063 outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS); 1064 outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS); 1065 1066 /* Set flow-control levels. */ 1067 outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW); 1068 outb(com->esp_port + ESP_CMD2, HIBYTE(768)); 1069 outb(com->esp_port + ESP_CMD2, LOBYTE(768)); 1070 outb(com->esp_port + ESP_CMD2, HIBYTE(512)); 1071 outb(com->esp_port + ESP_CMD2, LOBYTE(512)); 1072 } 1073#endif /* COM_ESP */ 1074 outb(iobase + com_fifo, 0); 1075determined_type: ; 1076 1077#ifdef COM_MULTIPORT 1078 if (COM_ISMULTIPORT(flags)) { 1079 com->multiport = TRUE; 1080 printf(" (multiport"); 1081 if (unit == COM_MPMASTER(flags)) 1082 printf(" master"); 1083 printf(")"); 1084 com->no_irq = 1085 isa_get_irq(devclass_get_device 1086 (sio_devclass, COM_MPMASTER(flags))) < 0; 1087 } 1088#endif /* COM_MULTIPORT */ 1089 if (unit == comconsole) 1090 printf(", console"); 1091 if ( COM_IIR_TXRDYBUG(flags) ) 1092 printf(" with a bogus IIR_TXRDY register"); 1093 printf("\n"); 1094 1095 if (!sio_registered) { 1096 register_swi(SWI_TTY, siopoll); 1097 sio_registered = TRUE; 1098 } 1099 make_dev(&sio_cdevsw, unit, 1100 UID_ROOT, GID_WHEEL, 0600, "ttyd%r", unit); 1101 make_dev(&sio_cdevsw, unit | CONTROL_INIT_STATE, 1102 UID_ROOT, GID_WHEEL, 0600, "ttyid%r", unit); 1103 make_dev(&sio_cdevsw, unit | CONTROL_LOCK_STATE, 1104 UID_ROOT, GID_WHEEL, 0600, "ttyld%r", unit); 1105 make_dev(&sio_cdevsw, unit | CALLOUT_MASK, 1106 UID_UUCP, GID_DIALER, 0660, "cuaa%r", unit); 1107 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_INIT_STATE, 1108 UID_UUCP, GID_DIALER, 0660, "cuaia%r", unit); 1109 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_LOCK_STATE, 1110 UID_UUCP, GID_DIALER, 0660, "cuala%r", unit); 1111 com->flags = flags; 1112 com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; 1113 pps_init(&com->pps); 1114 1115 rid = 0; 1116 com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, 1117 RF_SHAREABLE | RF_ACTIVE); 1118 BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres, 1119 INTR_TYPE_TTY | INTR_TYPE_FAST, 1120 siointr, com, &ih); 1121 1122 return (0); 1123} 1124 1125static int 1126sioopen(dev, flag, mode, p) 1127 dev_t dev; 1128 int flag; 1129 int mode; 1130 struct proc *p; 1131{ 1132 struct com_s *com; 1133 int error; 1134 Port_t iobase; 1135 int mynor; 1136 int s; 1137 struct tty *tp; 1138 int unit; 1139 1140 mynor = minor(dev); 1141 unit = MINOR_TO_UNIT(mynor); 1142 if ((u_int) unit >= NSIOTOT || (com = com_addr(unit)) == NULL) 1143 return (ENXIO); 1144 if (com->gone) 1145 return (ENXIO); 1146 if (mynor & CONTROL_MASK) 1147 return (0); 1148 tp = dev->si_tty = com->tp = ttymalloc(com->tp); 1149 s = spltty(); 1150 /* 1151 * We jump to this label after all non-interrupted sleeps to pick 1152 * up any changes of the device state. 1153 */ 1154open_top: 1155 while (com->state & CS_DTR_OFF) { 1156 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0); 1157 if (com_addr(unit) == NULL) 1158 return (ENXIO); 1159 if (error != 0 || com->gone) 1160 goto out; 1161 } 1162 if (tp->t_state & TS_ISOPEN) { 1163 /* 1164 * The device is open, so everything has been initialized. 1165 * Handle conflicts. 1166 */ 1167 if (mynor & CALLOUT_MASK) { 1168 if (!com->active_out) { 1169 error = EBUSY; 1170 goto out; 1171 } 1172 } else { 1173 if (com->active_out) { 1174 if (flag & O_NONBLOCK) { 1175 error = EBUSY; 1176 goto out; 1177 } 1178 error = tsleep(&com->active_out, 1179 TTIPRI | PCATCH, "siobi", 0); 1180 if (com_addr(unit) == NULL) 1181 return (ENXIO); 1182 if (error != 0 || com->gone) 1183 goto out; 1184 goto open_top; 1185 } 1186 } 1187 if (tp->t_state & TS_XCLUDE && 1188 suser(p)) { 1189 error = EBUSY; 1190 goto out; 1191 } 1192 } else { 1193 /* 1194 * The device isn't open, so there are no conflicts. 1195 * Initialize it. Initialization is done twice in many 1196 * cases: to preempt sleeping callin opens if we are 1197 * callout, and to complete a callin open after DCD rises. 1198 */ 1199 tp->t_oproc = comstart; 1200 tp->t_param = comparam; 1201 tp->t_stop = comstop; 1202 tp->t_dev = dev; 1203 tp->t_termios = mynor & CALLOUT_MASK 1204 ? com->it_out : com->it_in; 1205 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 1206 com->poll = com->no_irq; 1207 com->poll_output = com->loses_outints; 1208 ++com->wopeners; 1209 error = comparam(tp, &tp->t_termios); 1210 --com->wopeners; 1211 if (error != 0) 1212 goto out; 1213 /* 1214 * XXX we should goto open_top if comparam() slept. 1215 */ 1216 iobase = com->iobase; 1217 if (com->hasfifo) { 1218 /* 1219 * (Re)enable and drain fifos. 1220 * 1221 * Certain SMC chips cause problems if the fifos 1222 * are enabled while input is ready. Turn off the 1223 * fifo if necessary to clear the input. We test 1224 * the input ready bit after enabling the fifos 1225 * since we've already enabled them in comparam() 1226 * and to handle races between enabling and fresh 1227 * input. 1228 */ 1229 while (TRUE) { 1230 outb(iobase + com_fifo, 1231 FIFO_RCV_RST | FIFO_XMT_RST 1232 | com->fifo_image); 1233 /* 1234 * XXX the delays are for superstitious 1235 * historical reasons. It must be less than 1236 * the character time at the maximum 1237 * supported speed (87 usec at 115200 bps 1238 * 8N1). Otherwise we might loop endlessly 1239 * if data is streaming in. We used to use 1240 * delays of 100. That usually worked 1241 * because DELAY(100) used to usually delay 1242 * for about 85 usec instead of 100. 1243 */ 1244 DELAY(50); 1245 if (!(inb(com->line_status_port) & LSR_RXRDY)) 1246 break; 1247 outb(iobase + com_fifo, 0); 1248 DELAY(50); 1249 (void) inb(com->data_port); 1250 } 1251 } 1252 1253 disable_intr(); 1254 (void) inb(com->line_status_port); 1255 (void) inb(com->data_port); 1256 com->prev_modem_status = com->last_modem_status 1257 = inb(com->modem_status_port); 1258 if (COM_IIR_TXRDYBUG(com->flags)) { 1259 outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS 1260 | IER_EMSC); 1261 } else { 1262 outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY 1263 | IER_ERLS | IER_EMSC); 1264 } 1265 enable_intr(); 1266 /* 1267 * Handle initial DCD. Callout devices get a fake initial 1268 * DCD (trapdoor DCD). If we are callout, then any sleeping 1269 * callin opens get woken up and resume sleeping on "siobi" 1270 * instead of "siodcd". 1271 */ 1272 /* 1273 * XXX `mynor & CALLOUT_MASK' should be 1274 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 1275 * TRAPDOOR_CARRIER is the default initial state for callout 1276 * devices and SOFT_CARRIER is like CLOCAL except it hides 1277 * the true carrier. 1278 */ 1279 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 1280 (*linesw[tp->t_line].l_modem)(tp, 1); 1281 } 1282 /* 1283 * Wait for DCD if necessary. 1284 */ 1285 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 1286 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 1287 ++com->wopeners; 1288 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0); 1289 if (com_addr(unit) == NULL) 1290 return (ENXIO); 1291 --com->wopeners; 1292 if (error != 0 || com->gone) 1293 goto out; 1294 goto open_top; 1295 } 1296 error = (*linesw[tp->t_line].l_open)(dev, tp); 1297 disc_optim(tp, &tp->t_termios, com); 1298 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 1299 com->active_out = TRUE; 1300 siosettimeout(); 1301out: 1302 splx(s); 1303 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 1304 comhardclose(com); 1305 return (error); 1306} 1307 1308static int 1309sioclose(dev, flag, mode, p) 1310 dev_t dev; 1311 int flag; 1312 int mode; 1313 struct proc *p; 1314{ 1315 struct com_s *com; 1316 int mynor; 1317 int s; 1318 struct tty *tp; 1319 1320 mynor = minor(dev); 1321 if (mynor & CONTROL_MASK) 1322 return (0); 1323 com = com_addr(MINOR_TO_UNIT(mynor)); 1324 tp = com->tp; 1325 s = spltty(); 1326 (*linesw[tp->t_line].l_close)(tp, flag); 1327 disc_optim(tp, &tp->t_termios, com); 1328 comstop(tp, FREAD | FWRITE); 1329 comhardclose(com); 1330 ttyclose(tp); 1331 siosettimeout(); 1332 splx(s); 1333 if (com->gone) { 1334 printf("sio%d: gone\n", com->unit); 1335 s = spltty(); 1336 if (com->ibuf != NULL) 1337 free(com->ibuf, M_DEVBUF); 1338 bzero(tp, sizeof *tp); 1339 free(com, M_DEVBUF); 1340 splx(s); 1341 } 1342 return (0); 1343} 1344 1345static void 1346comhardclose(com) 1347 struct com_s *com; 1348{ 1349 Port_t iobase; 1350 int s; 1351 struct tty *tp; 1352 int unit; 1353 1354 unit = com->unit; 1355 iobase = com->iobase; 1356 s = spltty(); 1357 com->poll = FALSE; 1358 com->poll_output = FALSE; 1359 com->do_timestamp = FALSE; 1360 com->do_dcd_timestamp = FALSE; 1361 com->pps.ppsparam.mode = 0; 1362 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1363 { 1364 outb(iobase + com_ier, 0); 1365 tp = com->tp; 1366 if (tp->t_cflag & HUPCL 1367 /* 1368 * XXX we will miss any carrier drop between here and the 1369 * next open. Perhaps we should watch DCD even when the 1370 * port is closed; it is not sufficient to check it at 1371 * the next open because it might go up and down while 1372 * we're not watching. 1373 */ 1374 || (!com->active_out 1375 && !(com->prev_modem_status & MSR_DCD) 1376 && !(com->it_in.c_cflag & CLOCAL)) 1377 || !(tp->t_state & TS_ISOPEN)) { 1378 (void)commctl(com, TIOCM_DTR, DMBIC); 1379 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 1380 timeout(siodtrwakeup, com, com->dtr_wait); 1381 com->state |= CS_DTR_OFF; 1382 } 1383 } 1384 } 1385 if (com->hasfifo) { 1386 /* 1387 * Disable fifos so that they are off after controlled 1388 * reboots. Some BIOSes fail to detect 16550s when the 1389 * fifos are enabled. 1390 */ 1391 outb(iobase + com_fifo, 0); 1392 } 1393 com->active_out = FALSE; 1394 wakeup(&com->active_out); 1395 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 1396 splx(s); 1397} 1398 1399static int 1400sioread(dev, uio, flag) 1401 dev_t dev; 1402 struct uio *uio; 1403 int flag; 1404{ 1405 int mynor; 1406 struct com_s *com; 1407 1408 mynor = minor(dev); 1409 if (mynor & CONTROL_MASK) 1410 return (ENODEV); 1411 com = com_addr(MINOR_TO_UNIT(mynor)); 1412 if (com->gone) 1413 return (ENODEV); 1414 return ((*linesw[com->tp->t_line].l_read)(com->tp, uio, flag)); 1415} 1416 1417static int 1418siowrite(dev, uio, flag) 1419 dev_t dev; 1420 struct uio *uio; 1421 int flag; 1422{ 1423 int mynor; 1424 struct com_s *com; 1425 int unit; 1426 1427 mynor = minor(dev); 1428 if (mynor & CONTROL_MASK) 1429 return (ENODEV); 1430 1431 unit = MINOR_TO_UNIT(mynor); 1432 com = com_addr(unit); 1433 if (com->gone) 1434 return (ENODEV); 1435 /* 1436 * (XXX) We disallow virtual consoles if the physical console is 1437 * a serial port. This is in case there is a display attached that 1438 * is not the console. In that situation we don't need/want the X 1439 * server taking over the console. 1440 */ 1441 if (constty != NULL && unit == comconsole) 1442 constty = NULL; 1443 return ((*linesw[com->tp->t_line].l_write)(com->tp, uio, flag)); 1444} 1445 1446static void 1447siobusycheck(chan) 1448 void *chan; 1449{ 1450 struct com_s *com; 1451 int s; 1452 1453 com = (struct com_s *)chan; 1454 1455 /* 1456 * Clear TS_BUSY if low-level output is complete. 1457 * spl locking is sufficient because siointr1() does not set CS_BUSY. 1458 * If siointr1() clears CS_BUSY after we look at it, then we'll get 1459 * called again. Reading the line status port outside of siointr1() 1460 * is safe because CS_BUSY is clear so there are no output interrupts 1461 * to lose. 1462 */ 1463 s = spltty(); 1464 if (com->state & CS_BUSY) 1465 com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */ 1466 else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 1467 == (LSR_TSRE | LSR_TXRDY)) { 1468 com->tp->t_state &= ~TS_BUSY; 1469 ttwwakeup(com->tp); 1470 com->extra_state &= ~CSE_BUSYCHECK; 1471 } else 1472 timeout(siobusycheck, com, hz / 100); 1473 splx(s); 1474} 1475 1476static void 1477siodtrwakeup(chan) 1478 void *chan; 1479{ 1480 struct com_s *com; 1481 1482 com = (struct com_s *)chan; 1483 com->state &= ~CS_DTR_OFF; 1484 wakeup(&com->dtr_wait); 1485} 1486 1487static void 1488sioinput(com) 1489 struct com_s *com; 1490{ 1491 u_char *buf; 1492 int incc; 1493 u_char line_status; 1494 int recv_data; 1495 struct tty *tp; 1496 1497 buf = com->ibuf; 1498 tp = com->tp; 1499 if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) { 1500 com_events -= (com->iptr - com->ibuf); 1501 com->iptr = com->ibuf; 1502 return; 1503 } 1504 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 1505 /* 1506 * Avoid the grotesquely inefficient lineswitch routine 1507 * (ttyinput) in "raw" mode. It usually takes about 450 1508 * instructions (that's without canonical processing or echo!). 1509 * slinput is reasonably fast (usually 40 instructions plus 1510 * call overhead). 1511 */ 1512 do { 1513 enable_intr(); 1514 incc = com->iptr - buf; 1515 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 1516 && (com->state & CS_RTS_IFLOW 1517 || tp->t_iflag & IXOFF) 1518 && !(tp->t_state & TS_TBLOCK)) 1519 ttyblock(tp); 1520 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 1521 += b_to_q((char *)buf, incc, &tp->t_rawq); 1522 buf += incc; 1523 tk_nin += incc; 1524 tk_rawcc += incc; 1525 tp->t_rawcc += incc; 1526 ttwakeup(tp); 1527 if (tp->t_state & TS_TTSTOP 1528 && (tp->t_iflag & IXANY 1529 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 1530 tp->t_state &= ~TS_TTSTOP; 1531 tp->t_lflag &= ~FLUSHO; 1532 comstart(tp); 1533 } 1534 disable_intr(); 1535 } while (buf < com->iptr); 1536 } else { 1537 do { 1538 enable_intr(); 1539 line_status = buf[com->ierroff]; 1540 recv_data = *buf++; 1541 if (line_status 1542 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 1543 if (line_status & LSR_BI) 1544 recv_data |= TTY_BI; 1545 if (line_status & LSR_FE) 1546 recv_data |= TTY_FE; 1547 if (line_status & LSR_OE) 1548 recv_data |= TTY_OE; 1549 if (line_status & LSR_PE) 1550 recv_data |= TTY_PE; 1551 } 1552 (*linesw[tp->t_line].l_rint)(recv_data, tp); 1553 disable_intr(); 1554 } while (buf < com->iptr); 1555 } 1556 com_events -= (com->iptr - com->ibuf); 1557 com->iptr = com->ibuf; 1558 1559 /* 1560 * There is now room for another low-level buffer full of input, 1561 * so enable RTS if it is now disabled and there is room in the 1562 * high-level buffer. 1563 */ 1564 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) && 1565 !(tp->t_state & TS_TBLOCK)) 1566 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 1567} 1568 1569void 1570siointr(arg) 1571 void *arg; 1572{ 1573#ifndef COM_MULTIPORT 1574 COM_LOCK(); 1575 siointr1((struct com_s *) arg); 1576 COM_UNLOCK(); 1577#else /* COM_MULTIPORT */ 1578 bool_t possibly_more_intrs; 1579 int unit; 1580 struct com_s *com; 1581 1582 /* 1583 * Loop until there is no activity on any port. This is necessary 1584 * to get an interrupt edge more than to avoid another interrupt. 1585 * If the IRQ signal is just an OR of the IRQ signals from several 1586 * devices, then the edge from one may be lost because another is 1587 * on. 1588 */ 1589 COM_LOCK(); 1590 do { 1591 possibly_more_intrs = FALSE; 1592 for (unit = 0; unit < NSIOTOT; ++unit) { 1593 com = com_addr(unit); 1594 /* 1595 * XXX COM_LOCK(); 1596 * would it work here, or be counter-productive? 1597 */ 1598 if (com != NULL 1599 && !com->gone 1600 && (inb(com->int_id_port) & IIR_IMASK) 1601 != IIR_NOPEND) { 1602 siointr1(com); 1603 possibly_more_intrs = TRUE; 1604 } 1605 /* XXX COM_UNLOCK(); */ 1606 } 1607 } while (possibly_more_intrs); 1608 COM_UNLOCK(); 1609#endif /* COM_MULTIPORT */ 1610} 1611 1612static void 1613siointr1(com) 1614 struct com_s *com; 1615{ 1616 u_char line_status; 1617 u_char modem_status; 1618 u_char *ioptr; 1619 u_char recv_data; 1620 u_char int_ctl; 1621 u_char int_ctl_new; 1622 struct timecounter *tc; 1623 u_int count; 1624 1625 int_ctl = inb(com->intr_ctl_port); 1626 int_ctl_new = int_ctl; 1627 1628 while (!com->gone) { 1629 if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) { 1630 modem_status = inb(com->modem_status_port); 1631 if ((modem_status ^ com->last_modem_status) & MSR_DCD) { 1632 tc = timecounter; 1633 count = tc->tc_get_timecount(tc); 1634 pps_event(&com->pps, tc, count, 1635 (modem_status & MSR_DCD) ? 1636 PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); 1637 } 1638 } 1639 line_status = inb(com->line_status_port); 1640 1641 /* input event? (check first to help avoid overruns) */ 1642 while (line_status & LSR_RCV_MASK) { 1643 /* break/unnattached error bits or real input? */ 1644 if (!(line_status & LSR_RXRDY)) 1645 recv_data = 0; 1646 else 1647 recv_data = inb(com->data_port); 1648 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) { 1649 /* 1650 * Don't store BI if IGNBRK or FE/PE if IGNPAR. 1651 * Otherwise, push the work to a higher level 1652 * (to handle PARMRK) if we're bypassing. 1653 * Otherwise, convert BI/FE and PE+INPCK to 0. 1654 * 1655 * This makes bypassing work right in the 1656 * usual "raw" case (IGNBRK set, and IGNPAR 1657 * and INPCK clear). 1658 * 1659 * Note: BI together with FE/PE means just BI. 1660 */ 1661 if (line_status & LSR_BI) { 1662#if defined(DDB) && defined(BREAK_TO_DEBUGGER) 1663 if (com->unit == comconsole) { 1664 breakpoint(); 1665 goto cont; 1666 } 1667#endif 1668 if (com->tp == NULL 1669 || com->tp->t_iflag & IGNBRK) 1670 goto cont; 1671 } else { 1672 if (com->tp == NULL 1673 || com->tp->t_iflag & IGNPAR) 1674 goto cont; 1675 } 1676 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT 1677 && (line_status & (LSR_BI | LSR_FE) 1678 || com->tp->t_iflag & INPCK)) 1679 recv_data = 0; 1680 } 1681 ++com->bytes_in; 1682 if (com->hotchar != 0 && recv_data == com->hotchar) 1683 setsofttty(); 1684 ioptr = com->iptr; 1685 if (ioptr >= com->ibufend) 1686 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1687 else { 1688 if (com->do_timestamp) 1689 microtime(&com->timestamp); 1690 ++com_events; 1691 schedsofttty(); 1692#if 0 /* for testing input latency vs efficiency */ 1693if (com->iptr - com->ibuf == 8) 1694 setsofttty(); 1695#endif 1696 ioptr[0] = recv_data; 1697 ioptr[com->ierroff] = line_status; 1698 com->iptr = ++ioptr; 1699 if (ioptr == com->ihighwater 1700 && com->state & CS_RTS_IFLOW) 1701 outb(com->modem_ctl_port, 1702 com->mcr_image &= ~MCR_RTS); 1703 if (line_status & LSR_OE) 1704 CE_RECORD(com, CE_OVERRUN); 1705 } 1706cont: 1707 /* 1708 * "& 0x7F" is to avoid the gcc-1.40 generating a slow 1709 * jump from the top of the loop to here 1710 */ 1711 line_status = inb(com->line_status_port) & 0x7F; 1712 } 1713 1714 /* modem status change? (always check before doing output) */ 1715 modem_status = inb(com->modem_status_port); 1716 if (modem_status != com->last_modem_status) { 1717 if (com->do_dcd_timestamp 1718 && !(com->last_modem_status & MSR_DCD) 1719 && modem_status & MSR_DCD) 1720 microtime(&com->dcd_timestamp); 1721 1722 /* 1723 * Schedule high level to handle DCD changes. Note 1724 * that we don't use the delta bits anywhere. Some 1725 * UARTs mess them up, and it's easy to remember the 1726 * previous bits and calculate the delta. 1727 */ 1728 com->last_modem_status = modem_status; 1729 if (!(com->state & CS_CHECKMSR)) { 1730 com_events += LOTS_OF_EVENTS; 1731 com->state |= CS_CHECKMSR; 1732 setsofttty(); 1733 } 1734 1735 /* handle CTS change immediately for crisp flow ctl */ 1736 if (com->state & CS_CTS_OFLOW) { 1737 if (modem_status & MSR_CTS) 1738 com->state |= CS_ODEVREADY; 1739 else 1740 com->state &= ~CS_ODEVREADY; 1741 } 1742 } 1743 1744 /* output queued and everything ready? */ 1745 if (line_status & LSR_TXRDY 1746 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1747 ioptr = com->obufq.l_head; 1748 if (com->tx_fifo_size > 1) { 1749 u_int ocount; 1750 1751 ocount = com->obufq.l_tail - ioptr; 1752 if (ocount > com->tx_fifo_size) 1753 ocount = com->tx_fifo_size; 1754 com->bytes_out += ocount; 1755 do 1756 outb(com->data_port, *ioptr++); 1757 while (--ocount != 0); 1758 } else { 1759 outb(com->data_port, *ioptr++); 1760 ++com->bytes_out; 1761 } 1762 com->obufq.l_head = ioptr; 1763 if (COM_IIR_TXRDYBUG(com->flags)) { 1764 int_ctl_new = int_ctl | IER_ETXRDY; 1765 } 1766 if (ioptr >= com->obufq.l_tail) { 1767 struct lbq *qp; 1768 1769 qp = com->obufq.l_next; 1770 qp->l_queued = FALSE; 1771 qp = qp->l_next; 1772 if (qp != NULL) { 1773 com->obufq.l_head = qp->l_head; 1774 com->obufq.l_tail = qp->l_tail; 1775 com->obufq.l_next = qp; 1776 } else { 1777 /* output just completed */ 1778 if ( COM_IIR_TXRDYBUG(com->flags) ) { 1779 int_ctl_new = int_ctl & ~IER_ETXRDY; 1780 } 1781 com->state &= ~CS_BUSY; 1782 } 1783 if (!(com->state & CS_ODONE)) { 1784 com_events += LOTS_OF_EVENTS; 1785 com->state |= CS_ODONE; 1786 setsofttty(); /* handle at high level ASAP */ 1787 } 1788 } 1789 if ( COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) { 1790 outb(com->intr_ctl_port, int_ctl_new); 1791 } 1792 } 1793 1794 /* finished? */ 1795#ifndef COM_MULTIPORT 1796 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) 1797#endif /* COM_MULTIPORT */ 1798 return; 1799 } 1800} 1801 1802static int 1803sioioctl(dev, cmd, data, flag, p) 1804 dev_t dev; 1805 u_long cmd; 1806 caddr_t data; 1807 int flag; 1808 struct proc *p; 1809{ 1810 struct com_s *com; 1811 int error; 1812 Port_t iobase; 1813 int mynor; 1814 int s; 1815 struct tty *tp; 1816#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1817 u_long oldcmd; 1818 struct termios term; 1819#endif 1820 1821 mynor = minor(dev); 1822 com = com_addr(MINOR_TO_UNIT(mynor)); 1823 if (com->gone) 1824 return (ENODEV); 1825 iobase = com->iobase; 1826 if (mynor & CONTROL_MASK) { 1827 struct termios *ct; 1828 1829 switch (mynor & CONTROL_MASK) { 1830 case CONTROL_INIT_STATE: 1831 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 1832 break; 1833 case CONTROL_LOCK_STATE: 1834 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 1835 break; 1836 default: 1837 return (ENODEV); /* /dev/nodev */ 1838 } 1839 switch (cmd) { 1840 case TIOCSETA: 1841 error = suser(p); 1842 if (error != 0) 1843 return (error); 1844 *ct = *(struct termios *)data; 1845 return (0); 1846 case TIOCGETA: 1847 *(struct termios *)data = *ct; 1848 return (0); 1849 case TIOCGETD: 1850 *(int *)data = TTYDISC; 1851 return (0); 1852 case TIOCGWINSZ: 1853 bzero(data, sizeof(struct winsize)); 1854 return (0); 1855 default: 1856 return (ENOTTY); 1857 } 1858 } 1859 tp = com->tp; 1860#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1861 term = tp->t_termios; 1862 oldcmd = cmd; 1863 error = ttsetcompat(tp, &cmd, data, &term); 1864 if (error != 0) 1865 return (error); 1866 if (cmd != oldcmd) 1867 data = (caddr_t)&term; 1868#endif 1869 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1870 int cc; 1871 struct termios *dt = (struct termios *)data; 1872 struct termios *lt = mynor & CALLOUT_MASK 1873 ? &com->lt_out : &com->lt_in; 1874 1875 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1876 | (dt->c_iflag & ~lt->c_iflag); 1877 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1878 | (dt->c_oflag & ~lt->c_oflag); 1879 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1880 | (dt->c_cflag & ~lt->c_cflag); 1881 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1882 | (dt->c_lflag & ~lt->c_lflag); 1883 for (cc = 0; cc < NCCS; ++cc) 1884 if (lt->c_cc[cc] != 0) 1885 dt->c_cc[cc] = tp->t_cc[cc]; 1886 if (lt->c_ispeed != 0) 1887 dt->c_ispeed = tp->t_ispeed; 1888 if (lt->c_ospeed != 0) 1889 dt->c_ospeed = tp->t_ospeed; 1890 } 1891 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1892 if (error != ENOIOCTL) 1893 return (error); 1894 s = spltty(); 1895 error = ttioctl(tp, cmd, data, flag); 1896 disc_optim(tp, &tp->t_termios, com); 1897 if (error != ENOIOCTL) { 1898 splx(s); 1899 return (error); 1900 } 1901 switch (cmd) { 1902 case TIOCSBRK: 1903 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 1904 break; 1905 case TIOCCBRK: 1906 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1907 break; 1908 case TIOCSDTR: 1909 (void)commctl(com, TIOCM_DTR, DMBIS); 1910 break; 1911 case TIOCCDTR: 1912 (void)commctl(com, TIOCM_DTR, DMBIC); 1913 break; 1914 /* 1915 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 1916 * changes get undone on the next call to comparam(). 1917 */ 1918 case TIOCMSET: 1919 (void)commctl(com, *(int *)data, DMSET); 1920 break; 1921 case TIOCMBIS: 1922 (void)commctl(com, *(int *)data, DMBIS); 1923 break; 1924 case TIOCMBIC: 1925 (void)commctl(com, *(int *)data, DMBIC); 1926 break; 1927 case TIOCMGET: 1928 *(int *)data = commctl(com, 0, DMGET); 1929 break; 1930 case TIOCMSDTRWAIT: 1931 /* must be root since the wait applies to following logins */ 1932 error = suser(p); 1933 if (error != 0) { 1934 splx(s); 1935 return (error); 1936 } 1937 com->dtr_wait = *(int *)data * hz / 100; 1938 break; 1939 case TIOCMGDTRWAIT: 1940 *(int *)data = com->dtr_wait * 100 / hz; 1941 break; 1942 case TIOCTIMESTAMP: 1943 com->do_timestamp = TRUE; 1944 *(struct timeval *)data = com->timestamp; 1945 break; 1946 case TIOCDCDTIMESTAMP: 1947 com->do_dcd_timestamp = TRUE; 1948 *(struct timeval *)data = com->dcd_timestamp; 1949 break; 1950 default: 1951 splx(s); 1952 error = pps_ioctl(cmd, data, &com->pps); 1953 if (error == ENODEV) 1954 error = ENOTTY; 1955 return (error); 1956 } 1957 splx(s); 1958 return (0); 1959} 1960 1961static void 1962siopoll() 1963{ 1964 int unit; 1965 1966 if (com_events == 0) 1967 return; 1968repeat: 1969 for (unit = 0; unit < NSIOTOT; ++unit) { 1970 struct com_s *com; 1971 int incc; 1972 struct tty *tp; 1973 1974 com = com_addr(unit); 1975 if (com == NULL) 1976 continue; 1977 tp = com->tp; 1978 if (tp == NULL || com->gone) { 1979 /* 1980 * Discard any events related to never-opened or 1981 * going-away devices. 1982 */ 1983 disable_intr(); 1984 incc = com->iptr - com->ibuf; 1985 com->iptr = com->ibuf; 1986 if (com->state & CS_CHECKMSR) { 1987 incc += LOTS_OF_EVENTS; 1988 com->state &= ~CS_CHECKMSR; 1989 } 1990 com_events -= incc; 1991 enable_intr(); 1992 continue; 1993 } 1994 if (com->iptr != com->ibuf) { 1995 disable_intr(); 1996 sioinput(com); 1997 enable_intr(); 1998 } 1999 if (com->state & CS_CHECKMSR) { 2000 u_char delta_modem_status; 2001 2002 disable_intr(); 2003 delta_modem_status = com->last_modem_status 2004 ^ com->prev_modem_status; 2005 com->prev_modem_status = com->last_modem_status; 2006 com_events -= LOTS_OF_EVENTS; 2007 com->state &= ~CS_CHECKMSR; 2008 enable_intr(); 2009 if (delta_modem_status & MSR_DCD) 2010 (*linesw[tp->t_line].l_modem) 2011 (tp, com->prev_modem_status & MSR_DCD); 2012 } 2013 if (com->state & CS_ODONE) { 2014 disable_intr(); 2015 com_events -= LOTS_OF_EVENTS; 2016 com->state &= ~CS_ODONE; 2017 enable_intr(); 2018 if (!(com->state & CS_BUSY) 2019 && !(com->extra_state & CSE_BUSYCHECK)) { 2020 timeout(siobusycheck, com, hz / 100); 2021 com->extra_state |= CSE_BUSYCHECK; 2022 } 2023 (*linesw[tp->t_line].l_start)(tp); 2024 } 2025 if (com_events == 0) 2026 break; 2027 } 2028 if (com_events >= LOTS_OF_EVENTS) 2029 goto repeat; 2030} 2031 2032static int 2033comparam(tp, t) 2034 struct tty *tp; 2035 struct termios *t; 2036{ 2037 u_int cfcr; 2038 int cflag; 2039 struct com_s *com; 2040 int divisor; 2041 u_char dlbh; 2042 u_char dlbl; 2043 Port_t iobase; 2044 int s; 2045 int unit; 2046 2047 /* do historical conversions */ 2048 if (t->c_ispeed == 0) 2049 t->c_ispeed = t->c_ospeed; 2050 2051 /* check requested parameters */ 2052 divisor = ttspeedtab(t->c_ospeed, comspeedtab); 2053 if (divisor < 0 || (divisor > 0 && t->c_ispeed != t->c_ospeed)) 2054 return (EINVAL); 2055 2056 /* parameters are OK, convert them to the com struct and the device */ 2057 unit = DEV_TO_UNIT(tp->t_dev); 2058 com = com_addr(unit); 2059 iobase = com->iobase; 2060 s = spltty(); 2061 if (divisor == 0) 2062 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 2063 else 2064 (void)commctl(com, TIOCM_DTR, DMBIS); 2065 cflag = t->c_cflag; 2066 switch (cflag & CSIZE) { 2067 case CS5: 2068 cfcr = CFCR_5BITS; 2069 break; 2070 case CS6: 2071 cfcr = CFCR_6BITS; 2072 break; 2073 case CS7: 2074 cfcr = CFCR_7BITS; 2075 break; 2076 default: 2077 cfcr = CFCR_8BITS; 2078 break; 2079 } 2080 if (cflag & PARENB) { 2081 cfcr |= CFCR_PENAB; 2082 if (!(cflag & PARODD)) 2083 cfcr |= CFCR_PEVEN; 2084 } 2085 if (cflag & CSTOPB) 2086 cfcr |= CFCR_STOPB; 2087 2088 if (com->hasfifo && divisor != 0) { 2089 /* 2090 * Use a fifo trigger level low enough so that the input 2091 * latency from the fifo is less than about 16 msec and 2092 * the total latency is less than about 30 msec. These 2093 * latencies are reasonable for humans. Serial comms 2094 * protocols shouldn't expect anything better since modem 2095 * latencies are larger. 2096 */ 2097 com->fifo_image = t->c_ospeed <= 4800 2098 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; 2099#ifdef COM_ESP 2100 /* 2101 * The Hayes ESP card needs the fifo DMA mode bit set 2102 * in compatibility mode. If not, it will interrupt 2103 * for each character received. 2104 */ 2105 if (com->esp) 2106 com->fifo_image |= FIFO_DMA_MODE; 2107#endif 2108 outb(iobase + com_fifo, com->fifo_image); 2109 } 2110 2111 /* 2112 * This returns with interrupts disabled so that we can complete 2113 * the speed change atomically. Keeping interrupts disabled is 2114 * especially important while com_data is hidden. 2115 */ 2116 (void) siosetwater(com, t->c_ispeed); 2117 2118 if (divisor != 0) { 2119 outb(iobase + com_cfcr, cfcr | CFCR_DLAB); 2120 /* 2121 * Only set the divisor registers if they would change, 2122 * since on some 16550 incompatibles (UMC8669F), setting 2123 * them while input is arriving them loses sync until 2124 * data stops arriving. 2125 */ 2126 dlbl = divisor & 0xFF; 2127 if (inb(iobase + com_dlbl) != dlbl) 2128 outb(iobase + com_dlbl, dlbl); 2129 dlbh = (u_int) divisor >> 8; 2130 if (inb(iobase + com_dlbh) != dlbh) 2131 outb(iobase + com_dlbh, dlbh); 2132 } 2133 2134 2135 outb(iobase + com_cfcr, com->cfcr_image = cfcr); 2136 2137 if (!(tp->t_state & TS_TTSTOP)) 2138 com->state |= CS_TTGO; 2139 2140 if (cflag & CRTS_IFLOW) { 2141 if (com->st16650a) { 2142 outb(iobase + com_cfcr, 0xbf); 2143 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40); 2144 } 2145 com->state |= CS_RTS_IFLOW; 2146 /* 2147 * If CS_RTS_IFLOW just changed from off to on, the change 2148 * needs to be propagated to MCR_RTS. This isn't urgent, 2149 * so do it later by calling comstart() instead of repeating 2150 * a lot of code from comstart() here. 2151 */ 2152 } else if (com->state & CS_RTS_IFLOW) { 2153 com->state &= ~CS_RTS_IFLOW; 2154 /* 2155 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2156 * on here, since comstart() won't do it later. 2157 */ 2158 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2159 if (com->st16650a) { 2160 outb(iobase + com_cfcr, 0xbf); 2161 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40); 2162 } 2163 } 2164 2165 2166 /* 2167 * Set up state to handle output flow control. 2168 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2169 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2170 */ 2171 com->state |= CS_ODEVREADY; 2172 com->state &= ~CS_CTS_OFLOW; 2173 if (cflag & CCTS_OFLOW) { 2174 com->state |= CS_CTS_OFLOW; 2175 if (!(com->last_modem_status & MSR_CTS)) 2176 com->state &= ~CS_ODEVREADY; 2177 if (com->st16650a) { 2178 outb(iobase + com_cfcr, 0xbf); 2179 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80); 2180 } 2181 } else { 2182 if (com->st16650a) { 2183 outb(iobase + com_cfcr, 0xbf); 2184 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80); 2185 } 2186 } 2187 2188 2189 outb(iobase + com_cfcr, com->cfcr_image); 2190 2191 2192 /* XXX shouldn't call functions while intrs are disabled. */ 2193 disc_optim(tp, t, com); 2194 /* 2195 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2196 * unconditionally, but that defeated the careful discarding of 2197 * stale input in sioopen(). 2198 */ 2199 if (com->state >= (CS_BUSY | CS_TTGO)) 2200 siointr1(com); 2201 2202 enable_intr(); 2203 splx(s); 2204 comstart(tp); 2205 if (com->ibufold != NULL) { 2206 free(com->ibufold, M_DEVBUF); 2207 com->ibufold = NULL; 2208 } 2209 return (0); 2210} 2211 2212static int 2213siosetwater(com, speed) 2214 struct com_s *com; 2215 speed_t speed; 2216{ 2217 int cp4ticks; 2218 u_char *ibuf; 2219 int ibufsize; 2220 struct tty *tp; 2221 2222 /* 2223 * Make the buffer size large enough to handle a softtty interrupt 2224 * latency of about 2 ticks without loss of throughput or data 2225 * (about 3 ticks if input flow control is not used or not honoured, 2226 * but a bit less for CS5-CS7 modes). 2227 */ 2228 cp4ticks = speed / 10 / hz * 4; 2229 for (ibufsize = 128; ibufsize < cp4ticks;) 2230 ibufsize <<= 1; 2231 if (ibufsize == com->ibufsize) { 2232 disable_intr(); 2233 return (0); 2234 } 2235 2236 /* 2237 * Allocate input buffer. The extra factor of 2 in the size is 2238 * to allow for an error byte for each input byte. 2239 */ 2240 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 2241 if (ibuf == NULL) { 2242 disable_intr(); 2243 return (ENOMEM); 2244 } 2245 2246 /* Initialize non-critical variables. */ 2247 com->ibufold = com->ibuf; 2248 com->ibufsize = ibufsize; 2249 tp = com->tp; 2250 if (tp != NULL) { 2251 tp->t_ififosize = 2 * ibufsize; 2252 tp->t_ispeedwat = (speed_t)-1; 2253 tp->t_ospeedwat = (speed_t)-1; 2254 } 2255 2256 /* 2257 * Read current input buffer, if any. Continue with interrupts 2258 * disabled. 2259 */ 2260 disable_intr(); 2261 if (com->iptr != com->ibuf) 2262 sioinput(com); 2263 2264 /*- 2265 * Initialize critical variables, including input buffer watermarks. 2266 * The external device is asked to stop sending when the buffer 2267 * exactly reaches high water, or when the high level requests it. 2268 * The high level is notified immediately (rather than at a later 2269 * clock tick) when this watermark is reached. 2270 * The buffer size is chosen so the watermark should almost never 2271 * be reached. 2272 * The low watermark is invisibly 0 since the buffer is always 2273 * emptied all at once. 2274 */ 2275 com->iptr = com->ibuf = ibuf; 2276 com->ibufend = ibuf + ibufsize; 2277 com->ierroff = ibufsize; 2278 com->ihighwater = ibuf + 3 * ibufsize / 4; 2279 return (0); 2280} 2281 2282static void 2283comstart(tp) 2284 struct tty *tp; 2285{ 2286 struct com_s *com; 2287 int s; 2288 int unit; 2289 2290 unit = DEV_TO_UNIT(tp->t_dev); 2291 com = com_addr(unit); 2292 s = spltty(); 2293 disable_intr(); 2294 if (tp->t_state & TS_TTSTOP) 2295 com->state &= ~CS_TTGO; 2296 else 2297 com->state |= CS_TTGO; 2298 if (tp->t_state & TS_TBLOCK) { 2299 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 2300 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2301 } else { 2302 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater 2303 && com->state & CS_RTS_IFLOW) 2304 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2305 } 2306 enable_intr(); 2307 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2308 ttwwakeup(tp); 2309 splx(s); 2310 return; 2311 } 2312 if (tp->t_outq.c_cc != 0) { 2313 struct lbq *qp; 2314 struct lbq *next; 2315 2316 if (!com->obufs[0].l_queued) { 2317 com->obufs[0].l_tail 2318 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2319 sizeof com->obuf1); 2320 com->obufs[0].l_next = NULL; 2321 com->obufs[0].l_queued = TRUE; 2322 disable_intr(); 2323 if (com->state & CS_BUSY) { 2324 qp = com->obufq.l_next; 2325 while ((next = qp->l_next) != NULL) 2326 qp = next; 2327 qp->l_next = &com->obufs[0]; 2328 } else { 2329 com->obufq.l_head = com->obufs[0].l_head; 2330 com->obufq.l_tail = com->obufs[0].l_tail; 2331 com->obufq.l_next = &com->obufs[0]; 2332 com->state |= CS_BUSY; 2333 } 2334 enable_intr(); 2335 } 2336 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2337 com->obufs[1].l_tail 2338 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2339 sizeof com->obuf2); 2340 com->obufs[1].l_next = NULL; 2341 com->obufs[1].l_queued = TRUE; 2342 disable_intr(); 2343 if (com->state & CS_BUSY) { 2344 qp = com->obufq.l_next; 2345 while ((next = qp->l_next) != NULL) 2346 qp = next; 2347 qp->l_next = &com->obufs[1]; 2348 } else { 2349 com->obufq.l_head = com->obufs[1].l_head; 2350 com->obufq.l_tail = com->obufs[1].l_tail; 2351 com->obufq.l_next = &com->obufs[1]; 2352 com->state |= CS_BUSY; 2353 } 2354 enable_intr(); 2355 } 2356 tp->t_state |= TS_BUSY; 2357 } 2358 disable_intr(); 2359 if (com->state >= (CS_BUSY | CS_TTGO)) 2360 siointr1(com); /* fake interrupt to start output */ 2361 enable_intr(); 2362 ttwwakeup(tp); 2363 splx(s); 2364} 2365 2366static void 2367comstop(tp, rw) 2368 struct tty *tp; 2369 int rw; 2370{ 2371 struct com_s *com; 2372 2373 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2374 if (com->gone) 2375 return; 2376 disable_intr(); 2377 if (rw & FWRITE) { 2378 if (com->hasfifo) 2379#ifdef COM_ESP 2380 /* XXX avoid h/w bug. */ 2381 if (!com->esp) 2382#endif 2383 outb(com->iobase + com_fifo, 2384 FIFO_XMT_RST | com->fifo_image); 2385 com->obufs[0].l_queued = FALSE; 2386 com->obufs[1].l_queued = FALSE; 2387 if (com->state & CS_ODONE) 2388 com_events -= LOTS_OF_EVENTS; 2389 com->state &= ~(CS_ODONE | CS_BUSY); 2390 com->tp->t_state &= ~TS_BUSY; 2391 } 2392 if (rw & FREAD) { 2393 if (com->hasfifo) 2394#ifdef COM_ESP 2395 /* XXX avoid h/w bug. */ 2396 if (!com->esp) 2397#endif 2398 outb(com->iobase + com_fifo, 2399 FIFO_RCV_RST | com->fifo_image); 2400 com_events -= (com->iptr - com->ibuf); 2401 com->iptr = com->ibuf; 2402 } 2403 enable_intr(); 2404 comstart(tp); 2405} 2406 2407static int 2408commctl(com, bits, how) 2409 struct com_s *com; 2410 int bits; 2411 int how; 2412{ 2413 int mcr; 2414 int msr; 2415 2416 if (how == DMGET) { 2417 bits = TIOCM_LE; /* XXX - always enabled while open */ 2418 mcr = com->mcr_image; 2419 if (mcr & MCR_DTR) 2420 bits |= TIOCM_DTR; 2421 if (mcr & MCR_RTS) 2422 bits |= TIOCM_RTS; 2423 msr = com->prev_modem_status; 2424 if (msr & MSR_CTS) 2425 bits |= TIOCM_CTS; 2426 if (msr & MSR_DCD) 2427 bits |= TIOCM_CD; 2428 if (msr & MSR_DSR) 2429 bits |= TIOCM_DSR; 2430 /* 2431 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI 2432 * more volatile by reading the modem status a lot. Perhaps 2433 * we should latch both bits until the status is read here. 2434 */ 2435 if (msr & (MSR_RI | MSR_TERI)) 2436 bits |= TIOCM_RI; 2437 return (bits); 2438 } 2439 mcr = 0; 2440 if (bits & TIOCM_DTR) 2441 mcr |= MCR_DTR; 2442 if (bits & TIOCM_RTS) 2443 mcr |= MCR_RTS; 2444 if (com->gone) 2445 return(0); 2446 disable_intr(); 2447 switch (how) { 2448 case DMSET: 2449 outb(com->modem_ctl_port, 2450 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); 2451 break; 2452 case DMBIS: 2453 outb(com->modem_ctl_port, com->mcr_image |= mcr); 2454 break; 2455 case DMBIC: 2456 outb(com->modem_ctl_port, com->mcr_image &= ~mcr); 2457 break; 2458 } 2459 enable_intr(); 2460 return (0); 2461} 2462 2463static void 2464siosettimeout() 2465{ 2466 struct com_s *com; 2467 bool_t someopen; 2468 int unit; 2469 2470 /* 2471 * Set our timeout period to 1 second if no polled devices are open. 2472 * Otherwise set it to max(1/200, 1/hz). 2473 * Enable timeouts iff some device is open. 2474 */ 2475 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2476 sio_timeout = hz; 2477 someopen = FALSE; 2478 for (unit = 0; unit < NSIOTOT; ++unit) { 2479 com = com_addr(unit); 2480 if (com != NULL && com->tp != NULL 2481 && com->tp->t_state & TS_ISOPEN && !com->gone) { 2482 someopen = TRUE; 2483 if (com->poll || com->poll_output) { 2484 sio_timeout = hz > 200 ? hz / 200 : 1; 2485 break; 2486 } 2487 } 2488 } 2489 if (someopen) { 2490 sio_timeouts_until_log = hz / sio_timeout; 2491 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 2492 sio_timeout); 2493 } else { 2494 /* Flush error messages, if any. */ 2495 sio_timeouts_until_log = 1; 2496 comwakeup((void *)NULL); 2497 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2498 } 2499} 2500 2501static void 2502comwakeup(chan) 2503 void *chan; 2504{ 2505 struct com_s *com; 2506 int unit; 2507 2508 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 2509 2510 /* 2511 * Recover from lost output interrupts. 2512 * Poll any lines that don't use interrupts. 2513 */ 2514 for (unit = 0; unit < NSIOTOT; ++unit) { 2515 com = com_addr(unit); 2516 if (com != NULL && !com->gone 2517 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2518 disable_intr(); 2519 siointr1(com); 2520 enable_intr(); 2521 } 2522 } 2523 2524 /* 2525 * Check for and log errors, but not too often. 2526 */ 2527 if (--sio_timeouts_until_log > 0) 2528 return; 2529 sio_timeouts_until_log = hz / sio_timeout; 2530 for (unit = 0; unit < NSIOTOT; ++unit) { 2531 int errnum; 2532 2533 com = com_addr(unit); 2534 if (com == NULL) 2535 continue; 2536 if (com->gone) 2537 continue; 2538 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2539 u_int delta; 2540 u_long total; 2541 2542 disable_intr(); 2543 delta = com->delta_error_counts[errnum]; 2544 com->delta_error_counts[errnum] = 0; 2545 enable_intr(); 2546 if (delta == 0) 2547 continue; 2548 total = com->error_counts[errnum] += delta; 2549 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", 2550 unit, delta, error_desc[errnum], 2551 delta == 1 ? "" : "s", total); 2552 } 2553 } 2554} 2555 2556static void 2557disc_optim(tp, t, com) 2558 struct tty *tp; 2559 struct termios *t; 2560 struct com_s *com; 2561{ 2562 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 2563 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2564 && (!(t->c_iflag & PARMRK) 2565 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 2566 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 2567 && linesw[tp->t_line].l_rint == ttyinput) 2568 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2569 else 2570 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2571 com->hotchar = linesw[tp->t_line].l_hotchar; 2572} 2573 2574/* 2575 * Following are all routines needed for SIO to act as console 2576 */ 2577#include <sys/cons.h> 2578 2579struct siocnstate { 2580 u_char dlbl; 2581 u_char dlbh; 2582 u_char ier; 2583 u_char cfcr; 2584 u_char mcr; 2585}; 2586 2587static speed_t siocngetspeed __P((Port_t, struct speedtab *)); 2588static void siocnclose __P((struct siocnstate *sp, Port_t iobase)); 2589static void siocnopen __P((struct siocnstate *sp, Port_t iobase, int speed)); 2590static void siocntxwait __P((Port_t iobase)); 2591 2592static cn_probe_t siocnprobe; 2593static cn_init_t siocninit; 2594static cn_checkc_t siocncheckc; 2595static cn_getc_t siocngetc; 2596static cn_putc_t siocnputc; 2597 2598#ifdef __i386__ 2599CONS_DRIVER(sio, siocnprobe, siocninit, NULL, siocngetc, siocncheckc, siocnputc); 2600 2601#endif 2602 2603/* To get the GDB related variables */ 2604#if DDB > 0 2605#include <ddb/ddb.h> 2606#endif 2607 2608static void 2609siocntxwait(iobase) 2610 Port_t iobase; 2611{ 2612 int timo; 2613 2614 /* 2615 * Wait for any pending transmission to finish. Required to avoid 2616 * the UART lockup bug when the speed is changed, and for normal 2617 * transmits. 2618 */ 2619 timo = 100000; 2620 while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) 2621 != (LSR_TSRE | LSR_TXRDY) && --timo != 0) 2622 ; 2623} 2624 2625/* 2626 * Read the serial port specified and try to figure out what speed 2627 * it's currently running at. We're assuming the serial port has 2628 * been initialized and is basicly idle. This routine is only intended 2629 * to be run at system startup. 2630 * 2631 * If the value read from the serial port doesn't make sense, return 0. 2632 */ 2633 2634static speed_t 2635siocngetspeed(iobase, table) 2636 Port_t iobase; 2637 struct speedtab *table; 2638{ 2639 int code; 2640 u_char dlbh; 2641 u_char dlbl; 2642 u_char cfcr; 2643 2644 cfcr = inb(iobase + com_cfcr); 2645 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 2646 2647 dlbl = inb(iobase + com_dlbl); 2648 dlbh = inb(iobase + com_dlbh); 2649 2650 outb(iobase + com_cfcr, cfcr); 2651 2652 code = dlbh << 8 | dlbl; 2653 2654 for ( ; table->sp_speed != -1; table++) 2655 if (table->sp_code == code) 2656 return (table->sp_speed); 2657 2658 return 0; /* didn't match anything sane */ 2659} 2660 2661static void 2662siocnopen(sp, iobase, speed) 2663 struct siocnstate *sp; 2664 Port_t iobase; 2665 int speed; 2666{ 2667 int divisor; 2668 u_char dlbh; 2669 u_char dlbl; 2670 2671 /* 2672 * Save all the device control registers except the fifo register 2673 * and set our default ones (cs8 -parenb speed=comdefaultrate). 2674 * We can't save the fifo register since it is read-only. 2675 */ 2676 sp->ier = inb(iobase + com_ier); 2677 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ 2678 siocntxwait(iobase); 2679 sp->cfcr = inb(iobase + com_cfcr); 2680 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 2681 sp->dlbl = inb(iobase + com_dlbl); 2682 sp->dlbh = inb(iobase + com_dlbh); 2683 /* 2684 * Only set the divisor registers if they would change, since on 2685 * some 16550 incompatibles (Startech), setting them clears the 2686 * data input register. This also reduces the effects of the 2687 * UMC8669F bug. 2688 */ 2689 divisor = ttspeedtab(speed, comspeedtab); 2690 dlbl = divisor & 0xFF; 2691 if (sp->dlbl != dlbl) 2692 outb(iobase + com_dlbl, dlbl); 2693 dlbh = (u_int) divisor >> 8; 2694 if (sp->dlbh != dlbh) 2695 outb(iobase + com_dlbh, dlbh); 2696 outb(iobase + com_cfcr, CFCR_8BITS); 2697 sp->mcr = inb(iobase + com_mcr); 2698 /* 2699 * We don't want interrupts, but must be careful not to "disable" 2700 * them by clearing the MCR_IENABLE bit, since that might cause 2701 * an interrupt by floating the IRQ line. 2702 */ 2703 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); 2704} 2705 2706static void 2707siocnclose(sp, iobase) 2708 struct siocnstate *sp; 2709 Port_t iobase; 2710{ 2711 /* 2712 * Restore the device control registers. 2713 */ 2714 siocntxwait(iobase); 2715 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 2716 if (sp->dlbl != inb(iobase + com_dlbl)) 2717 outb(iobase + com_dlbl, sp->dlbl); 2718 if (sp->dlbh != inb(iobase + com_dlbh)) 2719 outb(iobase + com_dlbh, sp->dlbh); 2720 outb(iobase + com_cfcr, sp->cfcr); 2721 /* 2722 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. 2723 */ 2724 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); 2725 outb(iobase + com_ier, sp->ier); 2726} 2727 2728static void 2729siocnprobe(cp) 2730 struct consdev *cp; 2731{ 2732 speed_t boot_speed; 2733 u_char cfcr; 2734 int s, unit; 2735 struct siocnstate sp; 2736 2737 /* 2738 * Find our first enabled console, if any. If it is a high-level 2739 * console device, then initialize it and return successfully. 2740 * If it is a low-level console device, then initialize it and 2741 * return unsuccessfully. It must be initialized in both cases 2742 * for early use by console drivers and debuggers. Initializing 2743 * the hardware is not necessary in all cases, since the i/o 2744 * routines initialize it on the fly, but it is necessary if 2745 * input might arrive while the hardware is switched back to an 2746 * uninitialized state. We can't handle multiple console devices 2747 * yet because our low-level routines don't take a device arg. 2748 * We trust the user to set the console flags properly so that we 2749 * don't need to probe. 2750 */ 2751 cp->cn_pri = CN_DEAD; 2752 2753 for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */ 2754 int flags; 2755 int disabled; 2756 if (resource_int_value("sio", unit, "disabled", &disabled) == 0) { 2757 if (disabled) 2758 continue; 2759 } 2760 if (resource_int_value("sio", unit, "flags", &flags)) 2761 continue; 2762 if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) { 2763 int port; 2764 Port_t iobase; 2765 2766 if (resource_int_value("sio", unit, "port", &port)) 2767 continue; 2768 iobase = port; 2769 s = spltty(); 2770 if (boothowto & RB_SERIAL) { 2771 boot_speed = siocngetspeed(iobase, comspeedtab); 2772 if (boot_speed) 2773 comdefaultrate = boot_speed; 2774 } 2775 2776 /* 2777 * Initialize the divisor latch. We can't rely on 2778 * siocnopen() to do this the first time, since it 2779 * avoids writing to the latch if the latch appears 2780 * to have the correct value. Also, if we didn't 2781 * just read the speed from the hardware, then we 2782 * need to set the speed in hardware so that 2783 * switching it later is null. 2784 */ 2785 cfcr = inb(iobase + com_cfcr); 2786 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 2787 outb(iobase + com_dlbl, 2788 COMBRD(comdefaultrate) & 0xff); 2789 outb(iobase + com_dlbh, 2790 (u_int) COMBRD(comdefaultrate) >> 8); 2791 outb(iobase + com_cfcr, cfcr); 2792 2793 siocnopen(&sp, iobase, comdefaultrate); 2794 2795 splx(s); 2796 if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) { 2797 cp->cn_dev = makedev(CDEV_MAJOR, unit); 2798 cp->cn_pri = COM_FORCECONSOLE(flags) 2799 || boothowto & RB_SERIAL 2800 ? CN_REMOTE : CN_NORMAL; 2801 siocniobase = iobase; 2802 siocnunit = unit; 2803 } 2804 if (COM_DEBUGGER(flags)) { 2805 printf("sio%d: gdb debugging port\n", unit); 2806 siogdbiobase = iobase; 2807 siogdbunit = unit; 2808#if DDB > 0 2809 gdbdev = makedev(CDEV_MAJOR, unit); 2810 gdb_getc = siocngetc; 2811 gdb_putc = siocnputc; 2812#endif 2813 } 2814 } 2815 } 2816#ifdef __i386__ 2817#if DDB > 0 2818 /* 2819 * XXX Ugly Compatability. 2820 * If no gdb port has been specified, set it to be the console 2821 * as some configuration files don't specify the gdb port. 2822 */ 2823 if (gdbdev == NODEV && (boothowto & RB_GDB)) { 2824 printf("Warning: no GDB port specified. Defaulting to sio%d.\n", 2825 siocnunit); 2826 printf("Set flag 0x80 on desired GDB port in your\n"); 2827 printf("configuration file (currently sio only).\n"); 2828 siogdbiobase = siocniobase; 2829 siogdbunit = siocnunit; 2830 gdbdev = makedev(CDEV_MAJOR, siocnunit); 2831 gdb_getc = siocngetc; 2832 gdb_putc = siocnputc; 2833 } 2834#endif 2835#endif 2836} 2837 2838#ifdef __alpha__ 2839 2840CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc); 2841 2842int 2843siocnattach(port, speed) 2844 int port; 2845 int speed; 2846{ 2847 int s; 2848 u_char cfcr; 2849 struct siocnstate sp; 2850 2851 siocniobase = port; 2852 comdefaultrate = speed; 2853 sio_consdev.cn_pri = CN_NORMAL; 2854 sio_consdev.cn_dev = makedev(CDEV_MAJOR, 0); 2855 2856 s = spltty(); 2857 2858 /* 2859 * Initialize the divisor latch. We can't rely on 2860 * siocnopen() to do this the first time, since it 2861 * avoids writing to the latch if the latch appears 2862 * to have the correct value. Also, if we didn't 2863 * just read the speed from the hardware, then we 2864 * need to set the speed in hardware so that 2865 * switching it later is null. 2866 */ 2867 cfcr = inb(siocniobase + com_cfcr); 2868 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr); 2869 outb(siocniobase + com_dlbl, 2870 COMBRD(comdefaultrate) & 0xff); 2871 outb(siocniobase + com_dlbh, 2872 (u_int) COMBRD(comdefaultrate) >> 8); 2873 outb(siocniobase + com_cfcr, cfcr); 2874 2875 siocnopen(&sp, siocniobase, comdefaultrate); 2876 splx(s); 2877 2878 cn_tab = &sio_consdev; 2879 return 0; 2880} 2881 2882int 2883siogdbattach(port, speed) 2884 int port; 2885 int speed; 2886{ 2887 int s; 2888 u_char cfcr; 2889 struct siocnstate sp; 2890 2891 siogdbiobase = port; 2892 gdbdefaultrate = speed; 2893 2894 s = spltty(); 2895 2896 /* 2897 * Initialize the divisor latch. We can't rely on 2898 * siocnopen() to do this the first time, since it 2899 * avoids writing to the latch if the latch appears 2900 * to have the correct value. Also, if we didn't 2901 * just read the speed from the hardware, then we 2902 * need to set the speed in hardware so that 2903 * switching it later is null. 2904 */ 2905 cfcr = inb(siogdbiobase + com_cfcr); 2906 outb(siogdbiobase + com_cfcr, CFCR_DLAB | cfcr); 2907 outb(siogdbiobase + com_dlbl, 2908 COMBRD(gdbdefaultrate) & 0xff); 2909 outb(siogdbiobase + com_dlbh, 2910 (u_int) COMBRD(gdbdefaultrate) >> 8); 2911 outb(siogdbiobase + com_cfcr, cfcr); 2912 2913 siocnopen(&sp, siogdbiobase, gdbdefaultrate); 2914 splx(s); 2915 2916 return 0; 2917} 2918 2919#endif 2920 2921static void 2922siocninit(cp) 2923 struct consdev *cp; 2924{ 2925 comconsole = DEV_TO_UNIT(cp->cn_dev); 2926} 2927 2928static int 2929siocncheckc(dev) 2930 dev_t dev; 2931{ 2932 int c; 2933 Port_t iobase; 2934 int s; 2935 struct siocnstate sp; 2936 2937 if (minor(dev) == siogdbunit) 2938 iobase = siogdbiobase; 2939 else 2940 iobase = siocniobase; 2941 s = spltty(); 2942 siocnopen(&sp, iobase, comdefaultrate); 2943 if (inb(iobase + com_lsr) & LSR_RXRDY) 2944 c = inb(iobase + com_data); 2945 else 2946 c = -1; 2947 siocnclose(&sp, iobase); 2948 splx(s); 2949 return (c); 2950} 2951 2952 2953int 2954siocngetc(dev) 2955 dev_t dev; 2956{ 2957 int c; 2958 Port_t iobase; 2959 int s; 2960 struct siocnstate sp; 2961 2962 if (minor(dev) == siogdbunit) 2963 iobase = siogdbiobase; 2964 else 2965 iobase = siocniobase; 2966 s = spltty(); 2967 siocnopen(&sp, iobase, comdefaultrate); 2968 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 2969 ; 2970 c = inb(iobase + com_data); 2971 siocnclose(&sp, iobase); 2972 splx(s); 2973 return (c); 2974} 2975 2976void 2977siocnputc(dev, c) 2978 dev_t dev; 2979 int c; 2980{ 2981 int s; 2982 struct siocnstate sp; 2983 Port_t iobase; 2984 2985 if (minor(dev) == siogdbunit) 2986 iobase = siogdbiobase; 2987 else 2988 iobase = siocniobase; 2989 s = spltty(); 2990 siocnopen(&sp, iobase, comdefaultrate); 2991 siocntxwait(iobase); 2992 outb(iobase + com_data, c); 2993 siocnclose(&sp, iobase); 2994 splx(s); 2995} 2996 2997#ifdef __alpha__ 2998int 2999siogdbgetc() 3000{ 3001 int c; 3002 Port_t iobase; 3003 int s; 3004 struct siocnstate sp; 3005 3006 iobase = siogdbiobase; 3007 s = spltty(); 3008 siocnopen(&sp, iobase, gdbdefaultrate); 3009 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 3010 ; 3011 c = inb(iobase + com_data); 3012 siocnclose(&sp, iobase); 3013 splx(s); 3014 return (c); 3015} 3016 3017void 3018siogdbputc(c) 3019 int c; 3020{ 3021 int s; 3022 struct siocnstate sp; 3023 3024 s = spltty(); 3025 siocnopen(&sp, siogdbiobase, gdbdefaultrate); 3026 siocntxwait(siogdbiobase); 3027 outb(siogdbiobase + com_data, c); 3028 siocnclose(&sp, siogdbiobase); 3029 splx(s); 3030} 3031#endif 3032 3033DRIVER_MODULE(sio, isa, sio_isa_driver, sio_devclass, 0, 0); 3034#if NCARD > 0 3035DRIVER_MODULE(sio, pccard, sio_pccard_driver, sio_devclass, 0, 0); 3036#endif 3037