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