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 --- |