Deleted Added
full compact
sio.c (67551) sio.c (70174)
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

--- 16 unchanged lines hidden (view full) ---

25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
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

--- 16 unchanged lines hidden (view full) ---

25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * $FreeBSD: head/sys/dev/sio/sio.c 67551 2000-10-25 05:19:40Z jhb $
33 * $FreeBSD: head/sys/dev/sio/sio.c 70174 2000-12-18 23:56:16Z jhb $
34 * from: @(#)com.c 7.5 (Berkeley) 5/16/91
35 * from: i386/isa sio.c,v 1.234
36 */
37
38#include "opt_comconsole.h"
39#include "opt_compat.h"
40#include "opt_ddb.h"
41#include "opt_sio.h"

--- 49 unchanged lines hidden (view full) ---

91
92#include <isa/sioreg.h>
93
94#ifdef COM_ESP
95#include <isa/ic/esp.h>
96#endif
97#include <isa/ic/ns16550.h>
98
34 * from: @(#)com.c 7.5 (Berkeley) 5/16/91
35 * from: i386/isa sio.c,v 1.234
36 */
37
38#include "opt_comconsole.h"
39#include "opt_compat.h"
40#include "opt_ddb.h"
41#include "opt_sio.h"

--- 49 unchanged lines hidden (view full) ---

91
92#include <isa/sioreg.h>
93
94#ifdef COM_ESP
95#include <isa/ic/esp.h>
96#endif
97#include <isa/ic/ns16550.h>
98
99/* XXX - this is ok because we only do sio fast interrupts on i386 */
100#ifndef __i386__
101#define disable_intr()
102#define enable_intr()
103#endif
104
105#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
106
107#define CALLOUT_MASK 0x80
108#define CONTROL_MASK 0x60
109#define CONTROL_INIT_STATE 0x20
110#define CONTROL_LOCK_STATE 0x40
111#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
112#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)

--- 205 unchanged lines hidden (view full) ---

318#endif /* NCARD > 0 */
319
320#if NPCI > 0
321static int sio_pci_attach __P((device_t dev));
322static void sio_pci_kludge_unit __P((device_t dev));
323static int sio_pci_probe __P((device_t dev));
324#endif /* NPCI > 0 */
325
99#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
100
101#define CALLOUT_MASK 0x80
102#define CONTROL_MASK 0x60
103#define CONTROL_INIT_STATE 0x20
104#define CONTROL_LOCK_STATE 0x40
105#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
106#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)

--- 205 unchanged lines hidden (view full) ---

312#endif /* NCARD > 0 */
313
314#if NPCI > 0
315static int sio_pci_attach __P((device_t dev));
316static void sio_pci_kludge_unit __P((device_t dev));
317static int sio_pci_probe __P((device_t dev));
318#endif /* NPCI > 0 */
319
326static char driver_name[] = "sio";
320static char driver_name[] = "sio";
321static struct mtx sio_lock;
322static int sio_inited;
327
328/* table and macro for fast conversion from a unit number to its com struct */
329static devclass_t sio_devclass;
330#define com_addr(unit) ((struct com_s *) \
331 devclass_get_softc(sio_devclass, unit))
332
333static device_method_t sio_isa_methods[] = {
334 /* Device interface */

--- 421 unchanged lines hidden (view full) ---

756 intrmask_t irqmap[4];
757 intrmask_t irqs;
758 u_char mcr_image;
759 int result;
760 u_long xirq;
761 u_int flags = device_get_flags(dev);
762 int rid;
763 struct resource *port;
323
324/* table and macro for fast conversion from a unit number to its com struct */
325static devclass_t sio_devclass;
326#define com_addr(unit) ((struct com_s *) \
327 devclass_get_softc(sio_devclass, unit))
328
329static device_method_t sio_isa_methods[] = {
330 /* Device interface */

--- 421 unchanged lines hidden (view full) ---

752 intrmask_t irqmap[4];
753 intrmask_t irqs;
754 u_char mcr_image;
755 int result;
756 u_long xirq;
757 u_int flags = device_get_flags(dev);
758 int rid;
759 struct resource *port;
764 int intrsave;
765
766 rid = xrid;
767 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
768 0, ~0, IO_COMSIZE, RF_ACTIVE);
769 if (!port)
770 return (ENXIO);
771
772 com = device_get_softc(dev);
773 com->bst = rman_get_bustag(port);
774 com->bsh = rman_get_bushandle(port);
775
760
761 rid = xrid;
762 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
763 0, ~0, IO_COMSIZE, RF_ACTIVE);
764 if (!port)
765 return (ENXIO);
766
767 com = device_get_softc(dev);
768 com->bst = rman_get_bustag(port);
769 com->bsh = rman_get_bushandle(port);
770
771 if (atomic_cmpset_int(&sio_inited, 0, 1))
772 mtx_init(&sio_lock, "sio", MTX_SPIN);
773
776#if 0
777 /*
778 * XXX this is broken - when we are first called, there are no
779 * previously configured IO ports. We could hard code
780 * 0x3f8, 0x2f8, 0x3e8, 0x2e8 etc but that's probably worse.
781 * This code has been doing nothing since the conversion since
782 * "count" is zero the first time around.
783 */

--- 69 unchanged lines hidden (view full) ---

853 iobase = rman_get_start(port);
854
855 /*
856 * We don't want to get actual interrupts, just masked ones.
857 * Interrupts from this line should already be masked in the ICU,
858 * but mask them in the processor as well in case there are some
859 * (misconfigured) shared interrupts.
860 */
774#if 0
775 /*
776 * XXX this is broken - when we are first called, there are no
777 * previously configured IO ports. We could hard code
778 * 0x3f8, 0x2f8, 0x3e8, 0x2e8 etc but that's probably worse.
779 * This code has been doing nothing since the conversion since
780 * "count" is zero the first time around.
781 */

--- 69 unchanged lines hidden (view full) ---

851 iobase = rman_get_start(port);
852
853 /*
854 * We don't want to get actual interrupts, just masked ones.
855 * Interrupts from this line should already be masked in the ICU,
856 * but mask them in the processor as well in case there are some
857 * (misconfigured) shared interrupts.
858 */
861 intrsave = save_intr();
862 disable_intr();
863 COM_LOCK();
859 mtx_enter(&sio_lock, MTX_SPIN);
864/* EXTRA DELAY? */
865
866 /*
867 * Initialize the speed and the word size and wait long enough to
868 * drain the maximum of 16 bytes of junk in device output queues.
869 * The speed is undefined after a master reset and must be set
870 * before relying on anything related to output. There may be
871 * junk after a (very fast) soft reboot and (apparently) after

--- 80 unchanged lines hidden (view full) ---

952 /* Unknown, Just omit this chip.. XXX */
953 result = ENXIO;
954 }
955 } else {
956 /* OK. this is well-known guys */
957 CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
958 }
959 sio_setreg(com, com_cfcr, CFCR_8BITS);
860/* EXTRA DELAY? */
861
862 /*
863 * Initialize the speed and the word size and wait long enough to
864 * drain the maximum of 16 bytes of junk in device output queues.
865 * The speed is undefined after a master reset and must be set
866 * before relying on anything related to output. There may be
867 * junk after a (very fast) soft reboot and (apparently) after

--- 80 unchanged lines hidden (view full) ---

948 /* Unknown, Just omit this chip.. XXX */
949 result = ENXIO;
950 }
951 } else {
952 /* OK. this is well-known guys */
953 CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
954 }
955 sio_setreg(com, com_cfcr, CFCR_8BITS);
960 COM_UNLOCK();
961 restore_intr(intrsave);
956 mtx_exit(&sio_lock, MTX_SPIN);
962 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
963 return (iobase == siocniobase ? 0 : result);
964 }
965
966 /*
967 * Check that
968 * o the CFCR, IER and MCR in UART hold the values written to them
969 * (the values happen to be all distinct - this is good for

--- 23 unchanged lines hidden (view full) ---

993 */
994 sio_setreg(com, com_ier, 0);
995 sio_setreg(com, com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */
996 failures[7] = sio_getreg(com, com_ier);
997 DELAY(1000); /* XXX */
998 irqmap[3] = isa_irq_pending();
999 failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
1000
957 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
958 return (iobase == siocniobase ? 0 : result);
959 }
960
961 /*
962 * Check that
963 * o the CFCR, IER and MCR in UART hold the values written to them
964 * (the values happen to be all distinct - this is good for

--- 23 unchanged lines hidden (view full) ---

988 */
989 sio_setreg(com, com_ier, 0);
990 sio_setreg(com, com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */
991 failures[7] = sio_getreg(com, com_ier);
992 DELAY(1000); /* XXX */
993 irqmap[3] = isa_irq_pending();
994 failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
995
1001 COM_UNLOCK();
1002 restore_intr(intrsave);
996 mtx_exit(&sio_lock, MTX_SPIN);
1003
1004 irqs = irqmap[1] & ~irqmap[0];
1005 if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 &&
1006 ((1 << xirq) & irqs) == 0)
1007 printf(
1008 "sio%d: configured irq %ld not in bitmap of probed irqs %#x\n",
1009 device_get_unit(dev), xirq, irqs);
1010 if (bootverbose)

--- 102 unchanged lines hidden (view full) ---

1113 Port_t *espp;
1114#endif
1115 Port_t iobase;
1116 int unit;
1117 u_int flags;
1118 int rid;
1119 struct resource *port;
1120 int ret;
997
998 irqs = irqmap[1] & ~irqmap[0];
999 if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 &&
1000 ((1 << xirq) & irqs) == 0)
1001 printf(
1002 "sio%d: configured irq %ld not in bitmap of probed irqs %#x\n",
1003 device_get_unit(dev), xirq, irqs);
1004 if (bootverbose)

--- 102 unchanged lines hidden (view full) ---

1107 Port_t *espp;
1108#endif
1109 Port_t iobase;
1110 int unit;
1111 u_int flags;
1112 int rid;
1113 struct resource *port;
1114 int ret;
1121 int intrstate;
1122
1123 rid = xrid;
1124 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1125 0, ~0, IO_COMSIZE, RF_ACTIVE);
1126 if (!port)
1127 return (ENXIO);
1128
1129 iobase = rman_get_start(port);

--- 52 unchanged lines hidden (view full) ---

1182 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
1183 com->it_in.c_lflag = TTYDEF_LFLAG;
1184 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
1185 com->lt_out.c_ispeed = com->lt_out.c_ospeed =
1186 com->lt_in.c_ispeed = com->lt_in.c_ospeed =
1187 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
1188 } else
1189 com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
1115
1116 rid = xrid;
1117 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1118 0, ~0, IO_COMSIZE, RF_ACTIVE);
1119 if (!port)
1120 return (ENXIO);
1121
1122 iobase = rman_get_start(port);

--- 52 unchanged lines hidden (view full) ---

1175 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
1176 com->it_in.c_lflag = TTYDEF_LFLAG;
1177 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
1178 com->lt_out.c_ispeed = com->lt_out.c_ospeed =
1179 com->lt_in.c_ispeed = com->lt_in.c_ospeed =
1180 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
1181 } else
1182 com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
1190 intrstate = save_intr();
1191 if (siosetwater(com, com->it_in.c_ispeed) != 0) {
1183 if (siosetwater(com, com->it_in.c_ispeed) != 0) {
1192 COM_UNLOCK();
1193 restore_intr(intrstate);
1184 mtx_exit(&sio_lock, MTX_SPIN);
1194 /*
1195 * Leave i/o resources allocated if this is a `cn'-level
1196 * console, so that other devices can't snarf them.
1197 */
1198 if (iobase != siocniobase)
1199 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1200 return (ENOMEM);
1201 }
1185 /*
1186 * Leave i/o resources allocated if this is a `cn'-level
1187 * console, so that other devices can't snarf them.
1188 */
1189 if (iobase != siocniobase)
1190 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1191 return (ENOMEM);
1192 }
1202 COM_UNLOCK();
1203 restore_intr(intrstate);
1193 mtx_exit(&sio_lock, MTX_SPIN);
1204 termioschars(&com->it_in);
1205 com->it_out = com->it_in;
1206
1207 /* attempt to determine UART type */
1208 printf("sio%d: type", unit);
1209
1210
1211#ifdef COM_MULTIPORT

--- 219 unchanged lines hidden (view full) ---

1431 }
1432 }
1433 if (tp->t_state & TS_XCLUDE &&
1434 suser(p)) {
1435 error = EBUSY;
1436 goto out;
1437 }
1438 } else {
1194 termioschars(&com->it_in);
1195 com->it_out = com->it_in;
1196
1197 /* attempt to determine UART type */
1198 printf("sio%d: type", unit);
1199
1200
1201#ifdef COM_MULTIPORT

--- 219 unchanged lines hidden (view full) ---

1421 }
1422 }
1423 if (tp->t_state & TS_XCLUDE &&
1424 suser(p)) {
1425 error = EBUSY;
1426 goto out;
1427 }
1428 } else {
1439 int intrsave;
1440
1441 /*
1442 * The device isn't open, so there are no conflicts.
1443 * Initialize it. Initialization is done twice in many
1444 * cases: to preempt sleeping callin opens if we are
1445 * callout, and to complete a callin open after DCD rises.
1446 */
1447 tp->t_oproc = comstart;
1448 tp->t_param = comparam;

--- 43 unchanged lines hidden (view full) ---

1492 if (!(inb(com->line_status_port) & LSR_RXRDY))
1493 break;
1494 sio_setreg(com, com_fifo, 0);
1495 DELAY(50);
1496 (void) inb(com->data_port);
1497 }
1498 }
1499
1429 /*
1430 * The device isn't open, so there are no conflicts.
1431 * Initialize it. Initialization is done twice in many
1432 * cases: to preempt sleeping callin opens if we are
1433 * callout, and to complete a callin open after DCD rises.
1434 */
1435 tp->t_oproc = comstart;
1436 tp->t_param = comparam;

--- 43 unchanged lines hidden (view full) ---

1480 if (!(inb(com->line_status_port) & LSR_RXRDY))
1481 break;
1482 sio_setreg(com, com_fifo, 0);
1483 DELAY(50);
1484 (void) inb(com->data_port);
1485 }
1486 }
1487
1500 intrsave = save_intr();
1501 disable_intr();
1502 COM_LOCK();
1488 mtx_enter(&sio_lock, MTX_SPIN);
1503 (void) inb(com->line_status_port);
1504 (void) inb(com->data_port);
1505 com->prev_modem_status = com->last_modem_status
1506 = inb(com->modem_status_port);
1507 if (COM_IIR_TXRDYBUG(com->flags)) {
1508 outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
1509 | IER_EMSC);
1510 } else {
1511 outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
1512 | IER_ERLS | IER_EMSC);
1513 }
1489 (void) inb(com->line_status_port);
1490 (void) inb(com->data_port);
1491 com->prev_modem_status = com->last_modem_status
1492 = inb(com->modem_status_port);
1493 if (COM_IIR_TXRDYBUG(com->flags)) {
1494 outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
1495 | IER_EMSC);
1496 } else {
1497 outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
1498 | IER_ERLS | IER_EMSC);
1499 }
1514 COM_UNLOCK();
1515 restore_intr(intrsave);
1500 mtx_exit(&sio_lock, MTX_SPIN);
1516 /*
1517 * Handle initial DCD. Callout devices get a fake initial
1518 * DCD (trapdoor DCD). If we are callout, then any sleeping
1519 * callin opens get woken up and resume sleeping on "siobi"
1520 * instead of "siodcd".
1521 */
1522 /*
1523 * XXX `mynor & CALLOUT_MASK' should be

--- 205 unchanged lines hidden (view full) ---

1729 struct com_s *com;
1730
1731 com = (struct com_s *)chan;
1732 com->state &= ~CS_DTR_OFF;
1733 wakeup(&com->dtr_wait);
1734}
1735
1736/*
1501 /*
1502 * Handle initial DCD. Callout devices get a fake initial
1503 * DCD (trapdoor DCD). If we are callout, then any sleeping
1504 * callin opens get woken up and resume sleeping on "siobi"
1505 * instead of "siodcd".
1506 */
1507 /*
1508 * XXX `mynor & CALLOUT_MASK' should be

--- 205 unchanged lines hidden (view full) ---

1714 struct com_s *com;
1715
1716 com = (struct com_s *)chan;
1717 com->state &= ~CS_DTR_OFF;
1718 wakeup(&com->dtr_wait);
1719}
1720
1721/*
1737 * Call this function with COM_LOCK. It will return with the lock still held.
1722 * Call this function with the sio_lock mutex held. It will return with the
1723 * lock still held.
1738 */
1739static void
1740sioinput(com)
1741 struct com_s *com;
1742{
1743 u_char *buf;
1744 int incc;
1745 u_char line_status;
1746 int recv_data;
1747 struct tty *tp;
1724 */
1725static void
1726sioinput(com)
1727 struct com_s *com;
1728{
1729 u_char *buf;
1730 int incc;
1731 u_char line_status;
1732 int recv_data;
1733 struct tty *tp;
1748 int intrsave;
1749
1750 buf = com->ibuf;
1751 tp = com->tp;
1752 if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) {
1753 com_events -= (com->iptr - com->ibuf);
1754 com->iptr = com->ibuf;
1755 return;
1756 }

--- 6 unchanged lines hidden (view full) ---

1763 * call overhead).
1764 */
1765 do {
1766 /*
1767 * This may look odd, but it is using save-and-enable
1768 * semantics instead of the save-and-disable semantics
1769 * that are used everywhere else.
1770 */
1734
1735 buf = com->ibuf;
1736 tp = com->tp;
1737 if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) {
1738 com_events -= (com->iptr - com->ibuf);
1739 com->iptr = com->ibuf;
1740 return;
1741 }

--- 6 unchanged lines hidden (view full) ---

1748 * call overhead).
1749 */
1750 do {
1751 /*
1752 * This may look odd, but it is using save-and-enable
1753 * semantics instead of the save-and-disable semantics
1754 * that are used everywhere else.
1755 */
1771 intrsave = save_intr();
1772 COM_UNLOCK();
1773 enable_intr();
1756 mtx_exit(&sio_lock, MTX_SPIN);
1774 incc = com->iptr - buf;
1775 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
1776 && (com->state & CS_RTS_IFLOW
1777 || tp->t_iflag & IXOFF)
1778 && !(tp->t_state & TS_TBLOCK))
1779 ttyblock(tp);
1780 com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
1781 += b_to_q((char *)buf, incc, &tp->t_rawq);

--- 4 unchanged lines hidden (view full) ---

1786 ttwakeup(tp);
1787 if (tp->t_state & TS_TTSTOP
1788 && (tp->t_iflag & IXANY
1789 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
1790 tp->t_state &= ~TS_TTSTOP;
1791 tp->t_lflag &= ~FLUSHO;
1792 comstart(tp);
1793 }
1757 incc = com->iptr - buf;
1758 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
1759 && (com->state & CS_RTS_IFLOW
1760 || tp->t_iflag & IXOFF)
1761 && !(tp->t_state & TS_TBLOCK))
1762 ttyblock(tp);
1763 com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
1764 += b_to_q((char *)buf, incc, &tp->t_rawq);

--- 4 unchanged lines hidden (view full) ---

1769 ttwakeup(tp);
1770 if (tp->t_state & TS_TTSTOP
1771 && (tp->t_iflag & IXANY
1772 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
1773 tp->t_state &= ~TS_TTSTOP;
1774 tp->t_lflag &= ~FLUSHO;
1775 comstart(tp);
1776 }
1794 restore_intr(intrsave);
1795 COM_LOCK();
1777 mtx_enter(&sio_lock, MTX_SPIN);
1796 } while (buf < com->iptr);
1797 } else {
1798 do {
1799 /*
1800 * This may look odd, but it is using save-and-enable
1801 * semantics instead of the save-and-disable semantics
1802 * that are used everywhere else.
1803 */
1778 } while (buf < com->iptr);
1779 } else {
1780 do {
1781 /*
1782 * This may look odd, but it is using save-and-enable
1783 * semantics instead of the save-and-disable semantics
1784 * that are used everywhere else.
1785 */
1804 intrsave = save_intr();
1805 COM_UNLOCK();
1806 enable_intr();
1786 mtx_exit(&sio_lock, MTX_SPIN);
1807 line_status = buf[com->ierroff];
1808 recv_data = *buf++;
1809 if (line_status
1810 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
1811 if (line_status & LSR_BI)
1812 recv_data |= TTY_BI;
1813 if (line_status & LSR_FE)
1814 recv_data |= TTY_FE;
1815 if (line_status & LSR_OE)
1816 recv_data |= TTY_OE;
1817 if (line_status & LSR_PE)
1818 recv_data |= TTY_PE;
1819 }
1820 (*linesw[tp->t_line].l_rint)(recv_data, tp);
1787 line_status = buf[com->ierroff];
1788 recv_data = *buf++;
1789 if (line_status
1790 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
1791 if (line_status & LSR_BI)
1792 recv_data |= TTY_BI;
1793 if (line_status & LSR_FE)
1794 recv_data |= TTY_FE;
1795 if (line_status & LSR_OE)
1796 recv_data |= TTY_OE;
1797 if (line_status & LSR_PE)
1798 recv_data |= TTY_PE;
1799 }
1800 (*linesw[tp->t_line].l_rint)(recv_data, tp);
1821 restore_intr(intrsave);
1822 COM_LOCK();
1801 mtx_enter(&sio_lock, MTX_SPIN);
1823 } while (buf < com->iptr);
1824 }
1825 com_events -= (com->iptr - com->ibuf);
1826 com->iptr = com->ibuf;
1827
1828 /*
1829 * There is now room for another low-level buffer full of input,
1830 * so enable RTS if it is now disabled and there is room in the
1831 * high-level buffer.
1832 */
1833 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) &&
1834 !(tp->t_state & TS_TBLOCK))
1835 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
1836}
1837
1838void
1839siointr(arg)
1840 void *arg;
1841{
1802 } while (buf < com->iptr);
1803 }
1804 com_events -= (com->iptr - com->ibuf);
1805 com->iptr = com->ibuf;
1806
1807 /*
1808 * There is now room for another low-level buffer full of input,
1809 * so enable RTS if it is now disabled and there is room in the
1810 * high-level buffer.
1811 */
1812 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) &&
1813 !(tp->t_state & TS_TBLOCK))
1814 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
1815}
1816
1817void
1818siointr(arg)
1819 void *arg;
1820{
1821 struct com_s *com;
1822
1842#ifndef COM_MULTIPORT
1823#ifndef COM_MULTIPORT
1843 COM_LOCK();
1844 siointr1((struct com_s *) arg);
1845 COM_UNLOCK();
1824 com = (struct com_s *)arg;
1825
1826 mtx_enter(&sio_lock, MTX_SPIN);
1827 siointr1(com);
1828 mtx_exit(&sio_lock, MTX_SPIN);
1846#else /* COM_MULTIPORT */
1847 bool_t possibly_more_intrs;
1848 int unit;
1829#else /* COM_MULTIPORT */
1830 bool_t possibly_more_intrs;
1831 int unit;
1849 struct com_s *com;
1850
1851 /*
1852 * Loop until there is no activity on any port. This is necessary
1853 * to get an interrupt edge more than to avoid another interrupt.
1854 * If the IRQ signal is just an OR of the IRQ signals from several
1855 * devices, then the edge from one may be lost because another is
1856 * on.
1857 */
1832
1833 /*
1834 * Loop until there is no activity on any port. This is necessary
1835 * to get an interrupt edge more than to avoid another interrupt.
1836 * If the IRQ signal is just an OR of the IRQ signals from several
1837 * devices, then the edge from one may be lost because another is
1838 * on.
1839 */
1858 COM_LOCK();
1840 mtx_enter(&sio_lock, MTX_SPIN);
1859 do {
1860 possibly_more_intrs = FALSE;
1861 for (unit = 0; unit < sio_numunits; ++unit) {
1862 com = com_addr(unit);
1863 /*
1864 * XXX COM_LOCK();
1865 * would it work here, or be counter-productive?
1866 */
1867 if (com != NULL
1868 && !com->gone
1869 && (inb(com->int_id_port) & IIR_IMASK)
1870 != IIR_NOPEND) {
1871 siointr1(com);
1872 possibly_more_intrs = TRUE;
1873 }
1874 /* XXX COM_UNLOCK(); */
1875 }
1876 } while (possibly_more_intrs);
1841 do {
1842 possibly_more_intrs = FALSE;
1843 for (unit = 0; unit < sio_numunits; ++unit) {
1844 com = com_addr(unit);
1845 /*
1846 * XXX COM_LOCK();
1847 * would it work here, or be counter-productive?
1848 */
1849 if (com != NULL
1850 && !com->gone
1851 && (inb(com->int_id_port) & IIR_IMASK)
1852 != IIR_NOPEND) {
1853 siointr1(com);
1854 possibly_more_intrs = TRUE;
1855 }
1856 /* XXX COM_UNLOCK(); */
1857 }
1858 } while (possibly_more_intrs);
1877 COM_UNLOCK();
1859 mtx_exit(&sio_lock, MTX_SPIN);
1878#endif /* COM_MULTIPORT */
1879}
1880
1881static void
1882siointr1(com)
1883 struct com_s *com;
1884{
1885 u_char line_status;

--- 373 unchanged lines hidden (view full) ---

2259 return (0);
2260}
2261
2262/* software interrupt handler for SWI_TTY */
2263static void
2264siopoll(void *dummy)
2265{
2266 int unit;
1860#endif /* COM_MULTIPORT */
1861}
1862
1863static void
1864siointr1(com)
1865 struct com_s *com;
1866{
1867 u_char line_status;

--- 373 unchanged lines hidden (view full) ---

2241 return (0);
2242}
2243
2244/* software interrupt handler for SWI_TTY */
2245static void
2246siopoll(void *dummy)
2247{
2248 int unit;
2267 int intrsave;
2268
2269 if (com_events == 0)
2270 return;
2271repeat:
2272 for (unit = 0; unit < sio_numunits; ++unit) {
2273 struct com_s *com;
2274 int incc;
2275 struct tty *tp;
2276
2277 com = com_addr(unit);
2278 if (com == NULL)
2279 continue;
2280 tp = com->tp;
2281 if (tp == NULL || com->gone) {
2282 /*
2283 * Discard any events related to never-opened or
2284 * going-away devices.
2285 */
2249
2250 if (com_events == 0)
2251 return;
2252repeat:
2253 for (unit = 0; unit < sio_numunits; ++unit) {
2254 struct com_s *com;
2255 int incc;
2256 struct tty *tp;
2257
2258 com = com_addr(unit);
2259 if (com == NULL)
2260 continue;
2261 tp = com->tp;
2262 if (tp == NULL || com->gone) {
2263 /*
2264 * Discard any events related to never-opened or
2265 * going-away devices.
2266 */
2286 intrsave = save_intr();
2287 disable_intr();
2288 COM_LOCK();
2267 mtx_enter(&sio_lock, MTX_SPIN);
2289 incc = com->iptr - com->ibuf;
2290 com->iptr = com->ibuf;
2291 if (com->state & CS_CHECKMSR) {
2292 incc += LOTS_OF_EVENTS;
2293 com->state &= ~CS_CHECKMSR;
2294 }
2295 com_events -= incc;
2268 incc = com->iptr - com->ibuf;
2269 com->iptr = com->ibuf;
2270 if (com->state & CS_CHECKMSR) {
2271 incc += LOTS_OF_EVENTS;
2272 com->state &= ~CS_CHECKMSR;
2273 }
2274 com_events -= incc;
2296 COM_UNLOCK();
2297 restore_intr(intrsave);
2275 mtx_exit(&sio_lock, MTX_SPIN);
2298 continue;
2299 }
2300 if (com->iptr != com->ibuf) {
2276 continue;
2277 }
2278 if (com->iptr != com->ibuf) {
2301 intrsave = save_intr();
2302 disable_intr();
2303 COM_LOCK();
2279 mtx_enter(&sio_lock, MTX_SPIN);
2304 sioinput(com);
2280 sioinput(com);
2305 COM_UNLOCK();
2306 restore_intr(intrsave);
2281 mtx_exit(&sio_lock, MTX_SPIN);
2307 }
2308 if (com->state & CS_CHECKMSR) {
2309 u_char delta_modem_status;
2310
2282 }
2283 if (com->state & CS_CHECKMSR) {
2284 u_char delta_modem_status;
2285
2311 intrsave = save_intr();
2312 disable_intr();
2313 COM_LOCK();
2286 mtx_enter(&sio_lock, MTX_SPIN);
2314 delta_modem_status = com->last_modem_status
2315 ^ com->prev_modem_status;
2316 com->prev_modem_status = com->last_modem_status;
2317 com_events -= LOTS_OF_EVENTS;
2318 com->state &= ~CS_CHECKMSR;
2287 delta_modem_status = com->last_modem_status
2288 ^ com->prev_modem_status;
2289 com->prev_modem_status = com->last_modem_status;
2290 com_events -= LOTS_OF_EVENTS;
2291 com->state &= ~CS_CHECKMSR;
2319 COM_UNLOCK();
2320 restore_intr(intrsave);
2292 mtx_exit(&sio_lock, MTX_SPIN);
2321 if (delta_modem_status & MSR_DCD)
2322 (*linesw[tp->t_line].l_modem)
2323 (tp, com->prev_modem_status & MSR_DCD);
2324 }
2325 if (com->state & CS_ODONE) {
2293 if (delta_modem_status & MSR_DCD)
2294 (*linesw[tp->t_line].l_modem)
2295 (tp, com->prev_modem_status & MSR_DCD);
2296 }
2297 if (com->state & CS_ODONE) {
2326 intrsave = save_intr();
2327 disable_intr();
2328 COM_LOCK();
2298 mtx_enter(&sio_lock, MTX_SPIN);
2329 com_events -= LOTS_OF_EVENTS;
2330 com->state &= ~CS_ODONE;
2299 com_events -= LOTS_OF_EVENTS;
2300 com->state &= ~CS_ODONE;
2331 COM_UNLOCK();
2332 restore_intr(intrsave);
2301 mtx_exit(&sio_lock, MTX_SPIN);
2333 if (!(com->state & CS_BUSY)
2334 && !(com->extra_state & CSE_BUSYCHECK)) {
2335 timeout(siobusycheck, com, hz / 100);
2336 com->extra_state |= CSE_BUSYCHECK;
2337 }
2338 (*linesw[tp->t_line].l_start)(tp);
2339 }
2340 if (com_events == 0)

--- 11 unchanged lines hidden (view full) ---

2352 u_int cfcr;
2353 int cflag;
2354 struct com_s *com;
2355 int divisor;
2356 u_char dlbh;
2357 u_char dlbl;
2358 int s;
2359 int unit;
2302 if (!(com->state & CS_BUSY)
2303 && !(com->extra_state & CSE_BUSYCHECK)) {
2304 timeout(siobusycheck, com, hz / 100);
2305 com->extra_state |= CSE_BUSYCHECK;
2306 }
2307 (*linesw[tp->t_line].l_start)(tp);
2308 }
2309 if (com_events == 0)

--- 11 unchanged lines hidden (view full) ---

2321 u_int cfcr;
2322 int cflag;
2323 struct com_s *com;
2324 int divisor;
2325 u_char dlbh;
2326 u_char dlbl;
2327 int s;
2328 int unit;
2360 int intrsave;
2361
2362 /* do historical conversions */
2363 if (t->c_ispeed == 0)
2364 t->c_ispeed = t->c_ospeed;
2365
2366 /* check requested parameters */
2367 divisor = ttspeedtab(t->c_ospeed, comspeedtab);
2368 if (divisor < 0 || (divisor > 0 && t->c_ispeed != t->c_ospeed))

--- 55 unchanged lines hidden (view full) ---

2424 sio_setreg(com, com_fifo, com->fifo_image);
2425 }
2426
2427 /*
2428 * This returns with interrupts disabled so that we can complete
2429 * the speed change atomically. Keeping interrupts disabled is
2430 * especially important while com_data is hidden.
2431 */
2329
2330 /* do historical conversions */
2331 if (t->c_ispeed == 0)
2332 t->c_ispeed = t->c_ospeed;
2333
2334 /* check requested parameters */
2335 divisor = ttspeedtab(t->c_ospeed, comspeedtab);
2336 if (divisor < 0 || (divisor > 0 && t->c_ispeed != t->c_ospeed))

--- 55 unchanged lines hidden (view full) ---

2392 sio_setreg(com, com_fifo, com->fifo_image);
2393 }
2394
2395 /*
2396 * This returns with interrupts disabled so that we can complete
2397 * the speed change atomically. Keeping interrupts disabled is
2398 * especially important while com_data is hidden.
2399 */
2432 intrsave = save_intr();
2433 (void) siosetwater(com, t->c_ispeed);
2434
2435 if (divisor != 0) {
2436 sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
2437 /*
2438 * Only set the divisor registers if they would change,
2439 * since on some 16550 incompatibles (UMC8669F), setting
2440 * them while input is arriving them loses sync until

--- 71 unchanged lines hidden (view full) ---

2512 /*
2513 * Recover from fiddling with CS_TTGO. We used to call siointr1()
2514 * unconditionally, but that defeated the careful discarding of
2515 * stale input in sioopen().
2516 */
2517 if (com->state >= (CS_BUSY | CS_TTGO))
2518 siointr1(com);
2519
2400 (void) siosetwater(com, t->c_ispeed);
2401
2402 if (divisor != 0) {
2403 sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
2404 /*
2405 * Only set the divisor registers if they would change,
2406 * since on some 16550 incompatibles (UMC8669F), setting
2407 * them while input is arriving them loses sync until

--- 71 unchanged lines hidden (view full) ---

2479 /*
2480 * Recover from fiddling with CS_TTGO. We used to call siointr1()
2481 * unconditionally, but that defeated the careful discarding of
2482 * stale input in sioopen().
2483 */
2484 if (com->state >= (CS_BUSY | CS_TTGO))
2485 siointr1(com);
2486
2520 COM_UNLOCK();
2521 restore_intr(intrsave);
2487 mtx_exit(&sio_lock, MTX_SPIN);
2522 splx(s);
2523 comstart(tp);
2524 if (com->ibufold != NULL) {
2525 free(com->ibufold, M_DEVBUF);
2526 com->ibufold = NULL;
2527 }
2528 return (0);
2529}
2530
2531/*
2488 splx(s);
2489 comstart(tp);
2490 if (com->ibufold != NULL) {
2491 free(com->ibufold, M_DEVBUF);
2492 com->ibufold = NULL;
2493 }
2494 return (0);
2495}
2496
2497/*
2532 * This function must be called with interrupts enabled and the com_lock
2533 * unlocked. It will return with interrupts disabled and the com_lock locked.
2498 * This function must be called with the sio_lock mutex released and will
2499 * return with it obtained.
2534 */
2535static int
2536siosetwater(com, speed)
2537 struct com_s *com;
2538 speed_t speed;
2539{
2540 int cp4ticks;
2541 u_char *ibuf;

--- 5 unchanged lines hidden (view full) ---

2547 * latency of about 2 ticks without loss of throughput or data
2548 * (about 3 ticks if input flow control is not used or not honoured,
2549 * but a bit less for CS5-CS7 modes).
2550 */
2551 cp4ticks = speed / 10 / hz * 4;
2552 for (ibufsize = 128; ibufsize < cp4ticks;)
2553 ibufsize <<= 1;
2554 if (ibufsize == com->ibufsize) {
2500 */
2501static int
2502siosetwater(com, speed)
2503 struct com_s *com;
2504 speed_t speed;
2505{
2506 int cp4ticks;
2507 u_char *ibuf;

--- 5 unchanged lines hidden (view full) ---

2513 * latency of about 2 ticks without loss of throughput or data
2514 * (about 3 ticks if input flow control is not used or not honoured,
2515 * but a bit less for CS5-CS7 modes).
2516 */
2517 cp4ticks = speed / 10 / hz * 4;
2518 for (ibufsize = 128; ibufsize < cp4ticks;)
2519 ibufsize <<= 1;
2520 if (ibufsize == com->ibufsize) {
2555 disable_intr();
2556 COM_LOCK();
2521 mtx_enter(&sio_lock, MTX_SPIN);
2557 return (0);
2558 }
2559
2560 /*
2561 * Allocate input buffer. The extra factor of 2 in the size is
2562 * to allow for an error byte for each input byte.
2563 */
2564 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
2565 if (ibuf == NULL) {
2522 return (0);
2523 }
2524
2525 /*
2526 * Allocate input buffer. The extra factor of 2 in the size is
2527 * to allow for an error byte for each input byte.
2528 */
2529 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
2530 if (ibuf == NULL) {
2566 disable_intr();
2567 COM_LOCK();
2531 mtx_enter(&sio_lock, MTX_SPIN);
2568 return (ENOMEM);
2569 }
2570
2571 /* Initialize non-critical variables. */
2572 com->ibufold = com->ibuf;
2573 com->ibufsize = ibufsize;
2574 tp = com->tp;
2575 if (tp != NULL) {
2576 tp->t_ififosize = 2 * ibufsize;
2577 tp->t_ispeedwat = (speed_t)-1;
2578 tp->t_ospeedwat = (speed_t)-1;
2579 }
2580
2581 /*
2582 * Read current input buffer, if any. Continue with interrupts
2583 * disabled.
2584 */
2532 return (ENOMEM);
2533 }
2534
2535 /* Initialize non-critical variables. */
2536 com->ibufold = com->ibuf;
2537 com->ibufsize = ibufsize;
2538 tp = com->tp;
2539 if (tp != NULL) {
2540 tp->t_ififosize = 2 * ibufsize;
2541 tp->t_ispeedwat = (speed_t)-1;
2542 tp->t_ospeedwat = (speed_t)-1;
2543 }
2544
2545 /*
2546 * Read current input buffer, if any. Continue with interrupts
2547 * disabled.
2548 */
2585 disable_intr();
2586 COM_LOCK();
2549 mtx_enter(&sio_lock, MTX_SPIN);
2587 if (com->iptr != com->ibuf)
2588 sioinput(com);
2589
2590 /*-
2591 * Initialize critical variables, including input buffer watermarks.
2592 * The external device is asked to stop sending when the buffer
2593 * exactly reaches high water, or when the high level requests it.
2594 * The high level is notified immediately (rather than at a later

--- 12 unchanged lines hidden (view full) ---

2607
2608static void
2609comstart(tp)
2610 struct tty *tp;
2611{
2612 struct com_s *com;
2613 int s;
2614 int unit;
2550 if (com->iptr != com->ibuf)
2551 sioinput(com);
2552
2553 /*-
2554 * Initialize critical variables, including input buffer watermarks.
2555 * The external device is asked to stop sending when the buffer
2556 * exactly reaches high water, or when the high level requests it.
2557 * The high level is notified immediately (rather than at a later

--- 12 unchanged lines hidden (view full) ---

2570
2571static void
2572comstart(tp)
2573 struct tty *tp;
2574{
2575 struct com_s *com;
2576 int s;
2577 int unit;
2615 int intrsave;
2616
2617 unit = DEV_TO_UNIT(tp->t_dev);
2618 com = com_addr(unit);
2619 if (com == NULL)
2620 return;
2621 s = spltty();
2578
2579 unit = DEV_TO_UNIT(tp->t_dev);
2580 com = com_addr(unit);
2581 if (com == NULL)
2582 return;
2583 s = spltty();
2622 intrsave = save_intr();
2623 disable_intr();
2624 COM_LOCK();
2584 mtx_enter(&sio_lock, MTX_SPIN);
2625 if (tp->t_state & TS_TTSTOP)
2626 com->state &= ~CS_TTGO;
2627 else
2628 com->state |= CS_TTGO;
2629 if (tp->t_state & TS_TBLOCK) {
2630 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
2631 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
2632 } else {
2633 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
2634 && com->state & CS_RTS_IFLOW)
2635 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2636 }
2585 if (tp->t_state & TS_TTSTOP)
2586 com->state &= ~CS_TTGO;
2587 else
2588 com->state |= CS_TTGO;
2589 if (tp->t_state & TS_TBLOCK) {
2590 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
2591 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
2592 } else {
2593 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
2594 && com->state & CS_RTS_IFLOW)
2595 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2596 }
2637 COM_UNLOCK();
2638 restore_intr(intrsave);
2597 mtx_exit(&sio_lock, MTX_SPIN);
2639 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2640 ttwwakeup(tp);
2641 splx(s);
2642 return;
2643 }
2644 if (tp->t_outq.c_cc != 0) {
2645 struct lbq *qp;
2646 struct lbq *next;
2647
2648 if (!com->obufs[0].l_queued) {
2649 com->obufs[0].l_tail
2650 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2651 sizeof com->obuf1);
2652 com->obufs[0].l_next = NULL;
2653 com->obufs[0].l_queued = TRUE;
2598 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2599 ttwwakeup(tp);
2600 splx(s);
2601 return;
2602 }
2603 if (tp->t_outq.c_cc != 0) {
2604 struct lbq *qp;
2605 struct lbq *next;
2606
2607 if (!com->obufs[0].l_queued) {
2608 com->obufs[0].l_tail
2609 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2610 sizeof com->obuf1);
2611 com->obufs[0].l_next = NULL;
2612 com->obufs[0].l_queued = TRUE;
2654 intrsave = save_intr();
2655 disable_intr();
2656 COM_LOCK();
2613 mtx_enter(&sio_lock, MTX_SPIN);
2657 if (com->state & CS_BUSY) {
2658 qp = com->obufq.l_next;
2659 while ((next = qp->l_next) != NULL)
2660 qp = next;
2661 qp->l_next = &com->obufs[0];
2662 } else {
2663 com->obufq.l_head = com->obufs[0].l_head;
2664 com->obufq.l_tail = com->obufs[0].l_tail;
2665 com->obufq.l_next = &com->obufs[0];
2666 com->state |= CS_BUSY;
2667 }
2614 if (com->state & CS_BUSY) {
2615 qp = com->obufq.l_next;
2616 while ((next = qp->l_next) != NULL)
2617 qp = next;
2618 qp->l_next = &com->obufs[0];
2619 } else {
2620 com->obufq.l_head = com->obufs[0].l_head;
2621 com->obufq.l_tail = com->obufs[0].l_tail;
2622 com->obufq.l_next = &com->obufs[0];
2623 com->state |= CS_BUSY;
2624 }
2668 COM_UNLOCK();
2669 restore_intr(intrsave);
2625 mtx_exit(&sio_lock, MTX_SPIN);
2670 }
2671 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2672 com->obufs[1].l_tail
2673 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2674 sizeof com->obuf2);
2675 com->obufs[1].l_next = NULL;
2676 com->obufs[1].l_queued = TRUE;
2626 }
2627 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2628 com->obufs[1].l_tail
2629 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2630 sizeof com->obuf2);
2631 com->obufs[1].l_next = NULL;
2632 com->obufs[1].l_queued = TRUE;
2677 intrsave = save_intr();
2678 disable_intr();
2679 COM_LOCK();
2633 mtx_enter(&sio_lock, MTX_SPIN);
2680 if (com->state & CS_BUSY) {
2681 qp = com->obufq.l_next;
2682 while ((next = qp->l_next) != NULL)
2683 qp = next;
2684 qp->l_next = &com->obufs[1];
2685 } else {
2686 com->obufq.l_head = com->obufs[1].l_head;
2687 com->obufq.l_tail = com->obufs[1].l_tail;
2688 com->obufq.l_next = &com->obufs[1];
2689 com->state |= CS_BUSY;
2690 }
2634 if (com->state & CS_BUSY) {
2635 qp = com->obufq.l_next;
2636 while ((next = qp->l_next) != NULL)
2637 qp = next;
2638 qp->l_next = &com->obufs[1];
2639 } else {
2640 com->obufq.l_head = com->obufs[1].l_head;
2641 com->obufq.l_tail = com->obufs[1].l_tail;
2642 com->obufq.l_next = &com->obufs[1];
2643 com->state |= CS_BUSY;
2644 }
2691 COM_UNLOCK();
2692 restore_intr(intrsave);
2645 mtx_exit(&sio_lock, MTX_SPIN);
2693 }
2694 tp->t_state |= TS_BUSY;
2695 }
2646 }
2647 tp->t_state |= TS_BUSY;
2648 }
2696 intrsave = save_intr();
2697 disable_intr();
2698 COM_LOCK();
2649 mtx_enter(&sio_lock, MTX_SPIN);
2699 if (com->state >= (CS_BUSY | CS_TTGO))
2700 siointr1(com); /* fake interrupt to start output */
2650 if (com->state >= (CS_BUSY | CS_TTGO))
2651 siointr1(com); /* fake interrupt to start output */
2701 COM_UNLOCK();
2702 restore_intr(intrsave);
2652 mtx_exit(&sio_lock, MTX_SPIN);
2703 ttwwakeup(tp);
2704 splx(s);
2705}
2706
2707static void
2708comstop(tp, rw)
2709 struct tty *tp;
2710 int rw;
2711{
2712 struct com_s *com;
2653 ttwwakeup(tp);
2654 splx(s);
2655}
2656
2657static void
2658comstop(tp, rw)
2659 struct tty *tp;
2660 int rw;
2661{
2662 struct com_s *com;
2713 int intrsave;
2714
2715 com = com_addr(DEV_TO_UNIT(tp->t_dev));
2716 if (com == NULL || com->gone)
2717 return;
2663
2664 com = com_addr(DEV_TO_UNIT(tp->t_dev));
2665 if (com == NULL || com->gone)
2666 return;
2718 intrsave = save_intr();
2719 disable_intr();
2720 COM_LOCK();
2667 mtx_enter(&sio_lock, MTX_SPIN);
2721 if (rw & FWRITE) {
2722 if (com->hasfifo)
2723#ifdef COM_ESP
2724 /* XXX avoid h/w bug. */
2725 if (!com->esp)
2726#endif
2727 sio_setreg(com, com_fifo,
2728 FIFO_XMT_RST | com->fifo_image);

--- 10 unchanged lines hidden (view full) ---

2739 /* XXX avoid h/w bug. */
2740 if (!com->esp)
2741#endif
2742 sio_setreg(com, com_fifo,
2743 FIFO_RCV_RST | com->fifo_image);
2744 com_events -= (com->iptr - com->ibuf);
2745 com->iptr = com->ibuf;
2746 }
2668 if (rw & FWRITE) {
2669 if (com->hasfifo)
2670#ifdef COM_ESP
2671 /* XXX avoid h/w bug. */
2672 if (!com->esp)
2673#endif
2674 sio_setreg(com, com_fifo,
2675 FIFO_XMT_RST | com->fifo_image);

--- 10 unchanged lines hidden (view full) ---

2686 /* XXX avoid h/w bug. */
2687 if (!com->esp)
2688#endif
2689 sio_setreg(com, com_fifo,
2690 FIFO_RCV_RST | com->fifo_image);
2691 com_events -= (com->iptr - com->ibuf);
2692 com->iptr = com->ibuf;
2693 }
2747 COM_UNLOCK();
2748 restore_intr(intrsave);
2694 mtx_exit(&sio_lock, MTX_SPIN);
2749 comstart(tp);
2750}
2751
2752static int
2753commctl(com, bits, how)
2754 struct com_s *com;
2755 int bits;
2756 int how;
2757{
2758 int mcr;
2759 int msr;
2695 comstart(tp);
2696}
2697
2698static int
2699commctl(com, bits, how)
2700 struct com_s *com;
2701 int bits;
2702 int how;
2703{
2704 int mcr;
2705 int msr;
2760 int intrsave;
2761
2762 if (how == DMGET) {
2763 bits = TIOCM_LE; /* XXX - always enabled while open */
2764 mcr = com->mcr_image;
2765 if (mcr & MCR_DTR)
2766 bits |= TIOCM_DTR;
2767 if (mcr & MCR_RTS)
2768 bits |= TIOCM_RTS;

--- 15 unchanged lines hidden (view full) ---

2784 }
2785 mcr = 0;
2786 if (bits & TIOCM_DTR)
2787 mcr |= MCR_DTR;
2788 if (bits & TIOCM_RTS)
2789 mcr |= MCR_RTS;
2790 if (com->gone)
2791 return(0);
2706
2707 if (how == DMGET) {
2708 bits = TIOCM_LE; /* XXX - always enabled while open */
2709 mcr = com->mcr_image;
2710 if (mcr & MCR_DTR)
2711 bits |= TIOCM_DTR;
2712 if (mcr & MCR_RTS)
2713 bits |= TIOCM_RTS;

--- 15 unchanged lines hidden (view full) ---

2729 }
2730 mcr = 0;
2731 if (bits & TIOCM_DTR)
2732 mcr |= MCR_DTR;
2733 if (bits & TIOCM_RTS)
2734 mcr |= MCR_RTS;
2735 if (com->gone)
2736 return(0);
2792 intrsave = save_intr();
2793 disable_intr();
2794 COM_LOCK();
2737 mtx_enter(&sio_lock, MTX_SPIN);
2795 switch (how) {
2796 case DMSET:
2797 outb(com->modem_ctl_port,
2798 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
2799 break;
2800 case DMBIS:
2801 outb(com->modem_ctl_port, com->mcr_image |= mcr);
2802 break;
2803 case DMBIC:
2804 outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
2805 break;
2806 }
2738 switch (how) {
2739 case DMSET:
2740 outb(com->modem_ctl_port,
2741 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
2742 break;
2743 case DMBIS:
2744 outb(com->modem_ctl_port, com->mcr_image |= mcr);
2745 break;
2746 case DMBIC:
2747 outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
2748 break;
2749 }
2807 COM_UNLOCK();
2808 restore_intr(intrsave);
2750 mtx_exit(&sio_lock, MTX_SPIN);
2809 return (0);
2810}
2811
2812static void
2813siosettimeout()
2814{
2815 struct com_s *com;
2816 bool_t someopen;

--- 31 unchanged lines hidden (view full) ---

2848}
2849
2850static void
2851comwakeup(chan)
2852 void *chan;
2853{
2854 struct com_s *com;
2855 int unit;
2751 return (0);
2752}
2753
2754static void
2755siosettimeout()
2756{
2757 struct com_s *com;
2758 bool_t someopen;

--- 31 unchanged lines hidden (view full) ---

2790}
2791
2792static void
2793comwakeup(chan)
2794 void *chan;
2795{
2796 struct com_s *com;
2797 int unit;
2856 int intrsave;
2857
2858 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
2859
2860 /*
2861 * Recover from lost output interrupts.
2862 * Poll any lines that don't use interrupts.
2863 */
2864 for (unit = 0; unit < sio_numunits; ++unit) {
2865 com = com_addr(unit);
2866 if (com != NULL && !com->gone
2867 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2798
2799 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
2800
2801 /*
2802 * Recover from lost output interrupts.
2803 * Poll any lines that don't use interrupts.
2804 */
2805 for (unit = 0; unit < sio_numunits; ++unit) {
2806 com = com_addr(unit);
2807 if (com != NULL && !com->gone
2808 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2868 intrsave = save_intr();
2869 disable_intr();
2870 COM_LOCK();
2809 mtx_enter(&sio_lock, MTX_SPIN);
2871 siointr1(com);
2810 siointr1(com);
2872 COM_UNLOCK();
2873 restore_intr(intrsave);
2811 mtx_exit(&sio_lock, MTX_SPIN);
2874 }
2875 }
2876
2877 /*
2878 * Check for and log errors, but not too often.
2879 */
2880 if (--sio_timeouts_until_log > 0)
2881 return;

--- 5 unchanged lines hidden (view full) ---

2887 if (com == NULL)
2888 continue;
2889 if (com->gone)
2890 continue;
2891 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2892 u_int delta;
2893 u_long total;
2894
2812 }
2813 }
2814
2815 /*
2816 * Check for and log errors, but not too often.
2817 */
2818 if (--sio_timeouts_until_log > 0)
2819 return;

--- 5 unchanged lines hidden (view full) ---

2825 if (com == NULL)
2826 continue;
2827 if (com->gone)
2828 continue;
2829 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2830 u_int delta;
2831 u_long total;
2832
2895 intrsave = save_intr();
2896 disable_intr();
2897 COM_LOCK();
2833 mtx_enter(&sio_lock, MTX_SPIN);
2898 delta = com->delta_error_counts[errnum];
2899 com->delta_error_counts[errnum] = 0;
2834 delta = com->delta_error_counts[errnum];
2835 com->delta_error_counts[errnum] = 0;
2900 COM_UNLOCK();
2901 restore_intr(intrsave);
2836 mtx_exit(&sio_lock, MTX_SPIN);
2902 if (delta == 0)
2903 continue;
2904 total = com->error_counts[errnum] += delta;
2905 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
2906 unit, delta, error_desc[errnum],
2907 delta == 1 ? "" : "s", total);
2908 }
2909 }

--- 512 unchanged lines hidden ---
2837 if (delta == 0)
2838 continue;
2839 total = com->error_counts[errnum] += delta;
2840 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
2841 unit, delta, error_desc[errnum],
2842 delta == 1 ? "" : "s", total);
2843 }
2844 }

--- 512 unchanged lines hidden ---