Deleted Added
sdiff udiff text old ( 61011 ) new ( 65557 )
full compact
1/*-
2 * cyclades cyclom-y serial driver
3 * Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993
4 *
5 * Copyright (c) 1993 Andrew Herbert.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

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

22 * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $FreeBSD: head/sys/dev/cy/cy.c 61011 2000-05-28 13:40:48Z peter $
31 */
32
33#include "opt_compat.h"
34#include "cy.h"
35
36/*
37 * TODO:
38 * Atomic COR change.

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

89#include <i386/isa/isa_device.h>
90#include <i386/isa/cyreg.h>
91#include <i386/isa/ic/cd1400.h>
92
93#ifndef COMPAT_OLDISA
94#error "The cy device requires the old isa compatibility shims"
95#endif
96
97#ifdef SMP
98#define disable_intr() COM_DISABLE_INTR()
99#define enable_intr() COM_ENABLE_INTR()
100#endif /* SMP */
101
102/*
103 * Dictionary so that I can name everything *sio* or *com* to compare with
104 * sio.c. There is also lots of ugly formatting and unnecessary ifdefs to
105 * simplify the comparision. These will go away.
106 */
107#define LSR_BI CD1400_RDSR_BREAK
108#define LSR_FE CD1400_RDSR_FE
109#define LSR_OE CD1400_RDSR_OE

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

361
362static char driver_name[] = "cy";
363
364/* table and macro for fast conversion from a unit number to its com struct */
365static struct com_s *p_com_addr[NSIO];
366#define com_addr(unit) (p_com_addr[unit])
367
368struct isa_driver siodriver = {
369 INTR_TYPE_TTY | INTR_TYPE_FAST,
370 sioprobe,
371 sioattach,
372 driver_name
373};
374COMPAT_ISA_DRIVER(cy, cydriver); /* XXX */
375
376static d_open_t sioopen;
377static d_close_t sioclose;

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

599 if (unit == comconsole) {
600 com->it_in.c_iflag = TTYDEF_IFLAG;
601 com->it_in.c_oflag = TTYDEF_OFLAG;
602 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
603 com->it_in.c_lflag = TTYDEF_LFLAG;
604 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
605 }
606 if (siosetwater(com, com->it_in.c_ispeed) != 0) {
607 enable_intr();
608 free(com, M_DEVBUF);
609 return (0);
610 }
611 enable_intr();
612 termioschars(&com->it_in);
613 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
614 com->it_out = com->it_in;
615
616 s = spltty();
617 com_addr(unit) = com;
618 splx(s);
619

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

657 struct proc *p;
658{
659 struct com_s *com;
660 int error;
661 int mynor;
662 int s;
663 struct tty *tp;
664 int unit;
665
666 mynor = minor(dev);
667 unit = MINOR_TO_UNIT(mynor);
668 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL)
669 return (ENXIO);
670 if (mynor & CONTROL_MASK)
671 return (0);
672#if 0 /* XXX */

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

763 if (!(inb(com->line_status_port) & LSR_RXRDY))
764 break;
765 outb(iobase + com_fifo, 0);
766 DELAY(100);
767 (void) inb(com->data_port);
768 }
769 }
770
771 disable_intr();
772 (void) inb(com->line_status_port);
773 (void) inb(com->data_port);
774 com->prev_modem_status = com->last_modem_status
775 = inb(com->modem_status_port);
776 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS
777 | IER_EMSC);
778 enable_intr();
779#else /* !0 */
780 /*
781 * Flush fifos. This requires a full channel reset which
782 * also disables the transmitter and receiver. Recover
783 * from this.
784 */
785 cd1400_channel_cmd(com,
786 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET);
787 cd1400_channel_cmd(com, com->channel_control);
788
789 disable_intr();
790 com->prev_modem_status = com->last_modem_status
791 = cd_getreg(com, CD1400_MSVR2);
792 cd_setreg(com, CD1400_SRER,
793 com->intr_enable
794 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
795 enable_intr();
796#endif /* 0 */
797 /*
798 * Handle initial DCD. Callout devices get a fake initial
799 * DCD (trapdoor DCD). If we are callout, then any sleeping
800 * callin opens get woken up and resume sleeping on "cybi"
801 * instead of "cydcd".
802 */
803 /*

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

870static void
871comhardclose(com)
872 struct com_s *com;
873{
874 cy_addr iobase;
875 int s;
876 struct tty *tp;
877 int unit;
878
879 unit = com->unit;
880 iobase = com->iobase;
881 s = spltty();
882#if 0
883 com->poll = FALSE;
884 com->poll_output = FALSE;
885#endif
886 com->do_timestamp = 0;
887#if 0
888 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
889#else
890 /* XXX */
891 disable_intr();
892 com->etc = ETC_NONE;
893 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC);
894 enable_intr();
895 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
896#endif
897
898 {
899#if 0
900 outb(iobase + com_ier, 0);
901#else
902 disable_intr();
903 cd_setreg(com, CD1400_SRER, com->intr_enable = 0);
904 enable_intr();
905#endif
906 tp = com->tp;
907 if ((tp->t_cflag & HUPCL)
908 /*
909 * XXX we will miss any carrier drop between here and the
910 * next open. Perhaps we should watch DCD even when the
911 * port is closed; it is not sufficient to check it at
912 * the next open because it might go up and down while

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

986{
987 struct com_s *com;
988
989 com = (struct com_s *)chan;
990 com->state &= ~CS_DTR_OFF;
991 wakeup(&com->dtr_wait);
992}
993
994static void
995sioinput(com)
996 struct com_s *com;
997{
998 u_char *buf;
999 int incc;
1000 u_char line_status;
1001 int recv_data;
1002 struct tty *tp;
1003
1004 buf = com->ibuf;
1005 tp = com->tp;
1006 if (!(tp->t_state & TS_ISOPEN)) {
1007 com_events -= (com->iptr - com->ibuf);
1008 com->iptr = com->ibuf;
1009 return;
1010 }
1011 if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
1012 /*
1013 * Avoid the grotesquely inefficient lineswitch routine
1014 * (ttyinput) in "raw" mode. It usually takes about 450
1015 * instructions (that's without canonical processing or echo!).
1016 * slinput is reasonably fast (usually 40 instructions plus
1017 * call overhead).
1018 */
1019 do {
1020 enable_intr();
1021 incc = com->iptr - buf;
1022 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
1023 && (com->state & CS_RTS_IFLOW
1024 || tp->t_iflag & IXOFF)
1025 && !(tp->t_state & TS_TBLOCK))
1026 ttyblock(tp);
1027 com->delta_error_counts[CE_TTY_BUF_OVERFLOW]

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

1033 ttwakeup(tp);
1034 if (tp->t_state & TS_TTSTOP
1035 && (tp->t_iflag & IXANY
1036 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
1037 tp->t_state &= ~TS_TTSTOP;
1038 tp->t_lflag &= ~FLUSHO;
1039 comstart(tp);
1040 }
1041 disable_intr();
1042 } while (buf < com->iptr);
1043 } else {
1044 do {
1045 enable_intr();
1046 line_status = buf[com->ierroff];
1047 recv_data = *buf++;
1048 if (line_status
1049 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
1050 if (line_status & LSR_BI)
1051 recv_data |= TTY_BI;
1052 if (line_status & LSR_FE)
1053 recv_data |= TTY_FE;
1054 if (line_status & LSR_OE)
1055 recv_data |= TTY_OE;
1056 if (line_status & LSR_PE)
1057 recv_data |= TTY_PE;
1058 }
1059 (*linesw[tp->t_line].l_rint)(recv_data, tp);
1060 disable_intr();
1061 } while (buf < com->iptr);
1062 }
1063 com_events -= (com->iptr - com->ibuf);
1064 com->iptr = com->ibuf;
1065
1066 /*
1067 * There is now room for another low-level buffer full of input,
1068 * so enable RTS if it is now disabled and there is room in the

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

1724 splx(s);
1725 return (0);
1726}
1727
1728static void
1729siopoll()
1730{
1731 int unit;
1732
1733#ifdef CyDebug
1734 ++cy_timeouts;
1735#endif
1736 if (com_events == 0)
1737 return;
1738repeat:
1739 for (unit = 0; unit < NSIO; ++unit) {

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

1746 continue;
1747 tp = com->tp;
1748 if (tp == NULL) {
1749 /*
1750 * XXX forget any events related to closed devices
1751 * (actually never opened devices) so that we don't
1752 * loop.
1753 */
1754 disable_intr();
1755 incc = com->iptr - com->ibuf;
1756 com->iptr = com->ibuf;
1757 if (com->state & CS_CHECKMSR) {
1758 incc += LOTS_OF_EVENTS;
1759 com->state &= ~CS_CHECKMSR;
1760 }
1761 com_events -= incc;
1762 enable_intr();
1763 if (incc != 0)
1764 log(LOG_DEBUG,
1765 "sio%d: %d events for device with no tp\n",
1766 unit, incc);
1767 continue;
1768 }
1769 if (com->iptr != com->ibuf) {
1770 disable_intr();
1771 sioinput(com);
1772 enable_intr();
1773 }
1774 if (com->state & CS_CHECKMSR) {
1775 u_char delta_modem_status;
1776
1777 disable_intr();
1778 delta_modem_status = com->last_modem_status
1779 ^ com->prev_modem_status;
1780 com->prev_modem_status = com->last_modem_status;
1781 com_events -= LOTS_OF_EVENTS;
1782 com->state &= ~CS_CHECKMSR;
1783 enable_intr();
1784 if (delta_modem_status & MSR_DCD)
1785 (*linesw[tp->t_line].l_modem)
1786 (tp, com->prev_modem_status & MSR_DCD);
1787 }
1788 if (com->extra_state & CSE_ODONE) {
1789 disable_intr();
1790 com_events -= LOTS_OF_EVENTS;
1791 com->extra_state &= ~CSE_ODONE;
1792 enable_intr();
1793 if (!(com->state & CS_BUSY)) {
1794 tp->t_state &= ~TS_BUSY;
1795 ttwwakeup(com->tp);
1796 }
1797 if (com->etc != ETC_NONE) {
1798 if (com->etc == ETC_BREAK_ENDED)
1799 com->etc = ETC_NONE;
1800 wakeup(&com->etc);
1801 }
1802 }
1803 if (com->state & CS_ODONE) {
1804 disable_intr();
1805 com_events -= LOTS_OF_EVENTS;
1806 com->state &= ~CS_ODONE;
1807 enable_intr();
1808 (*linesw[tp->t_line].l_start)(tp);
1809 }
1810 if (com_events == 0)
1811 break;
1812 }
1813 if (com_events >= LOTS_OF_EVENTS)
1814 goto repeat;
1815}

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

1828 int iflag;
1829 int iprescaler;
1830 int itimeout;
1831 int odivisor;
1832 int oprescaler;
1833 u_char opt;
1834 int s;
1835 int unit;
1836
1837 /* do historical conversions */
1838 if (t->c_ispeed == 0)
1839 t->c_ispeed = t->c_ospeed;
1840
1841 unit = DEV_TO_UNIT(tp->t_dev);
1842 com = com_addr(unit);
1843

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

1852
1853 /* parameters are OK, convert them to the com struct and the device */
1854 s = spltty();
1855 if (odivisor == 0)
1856 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */
1857 else
1858 (void)commctl(com, TIOCM_DTR, DMBIS);
1859
1860 /*
1861 * This returns with interrupts disabled so that we can complete
1862 * the speed change atomically.
1863 */
1864 (void) siosetwater(com, t->c_ispeed);
1865
1866 /* XXX we don't actually change the speed atomically. */
1867 enable_intr();
1868
1869 if (idivisor != 0) {
1870 cd_setreg(com, CD1400_RBPR, idivisor);
1871 cd_setreg(com, CD1400_RCOR, iprescaler);
1872 }
1873 if (odivisor != 0) {
1874 cd_setreg(com, CD1400_TBPR, odivisor);
1875 cd_setreg(com, CD1400_TCOR, oprescaler);

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

1980 opt |= CD1400_COR2_IXANY;
1981 if (iflag & IXOFF)
1982 opt |= CD1400_COR2_IXOFF;
1983#endif
1984#ifndef SOFT_CTS_OFLOW
1985 if (cflag & CCTS_OFLOW)
1986 opt |= CD1400_COR2_CCTS_OFLOW;
1987#endif
1988 disable_intr();
1989 if (opt != com->cor[1]) {
1990 cor_change |= CD1400_CCR_COR2;
1991 cd_setreg(com, CD1400_COR2, com->cor[1] = opt);
1992 }
1993 enable_intr();
1994
1995 /*
1996 * set channel option register 3 -
1997 * receiver FIFO interrupt threshold
1998 * flow control
1999 */
2000 opt = RxFifoThreshold;
2001#ifdef Smarts

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

2106 opt |= CD1400_MCOR2_CTSod;
2107#endif
2108 cd_setreg(com, CD1400_MCOR2, opt);
2109
2110 /*
2111 * XXX should have done this long ago, but there is too much state
2112 * to change all atomically.
2113 */
2114 disable_intr();
2115
2116 com->state &= ~CS_TTGO;
2117 if (!(tp->t_state & TS_TTSTOP))
2118 com->state |= CS_TTGO;
2119 if (cflag & CRTS_IFLOW) {
2120 com->state |= CS_RTS_IFLOW;
2121 /*
2122 * If CS_RTS_IFLOW just changed from off to on, the change

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

2172 } else {
2173 if (com->intr_enable & CD1400_SRER_TXRDY)
2174 cd_setreg(com, CD1400_SRER,
2175 com->intr_enable
2176 = (com->intr_enable & ~CD1400_SRER_TXRDY)
2177 | CD1400_SRER_TXMPTY);
2178 }
2179
2180 enable_intr();
2181 splx(s);
2182 comstart(tp);
2183 if (com->ibufold != NULL) {
2184 free(com->ibufold, M_DEVBUF);
2185 com->ibufold = NULL;
2186 }
2187 return (0);
2188}
2189
2190static int
2191siosetwater(com, speed)
2192 struct com_s *com;
2193 speed_t speed;
2194{
2195 int cp4ticks;
2196 u_char *ibuf;
2197 int ibufsize;
2198 struct tty *tp;
2199
2200 /*
2201 * Make the buffer size large enough to handle a softtty interrupt
2202 * latency of about 2 ticks without loss of throughput or data
2203 * (about 3 ticks if input flow control is not used or not honoured,
2204 * but a bit less for CS5-CS7 modes).
2205 */
2206 cp4ticks = speed / 10 / hz * 4;
2207 for (ibufsize = 128; ibufsize < cp4ticks;)
2208 ibufsize <<= 1;
2209 if (ibufsize == com->ibufsize) {
2210 disable_intr();
2211 return (0);
2212 }
2213
2214 /*
2215 * Allocate input buffer. The extra factor of 2 in the size is
2216 * to allow for an error byte for each input byte.
2217 */
2218 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
2219 if (ibuf == NULL) {
2220 disable_intr();
2221 return (ENOMEM);
2222 }
2223
2224 /* Initialize non-critical variables. */
2225 com->ibufold = com->ibuf;
2226 com->ibufsize = ibufsize;
2227 tp = com->tp;
2228 if (tp != NULL) {
2229 tp->t_ififosize = 2 * ibufsize;
2230 tp->t_ispeedwat = (speed_t)-1;
2231 tp->t_ospeedwat = (speed_t)-1;
2232 }
2233
2234 /*
2235 * Read current input buffer, if any. Continue with interrupts
2236 * disabled.
2237 */
2238 disable_intr();
2239 if (com->iptr != com->ibuf)
2240 sioinput(com);
2241
2242 /*-
2243 * Initialize critical variables, including input buffer watermarks.
2244 * The external device is asked to stop sending when the buffer
2245 * exactly reaches high water, or when the high level requests it.
2246 * The high level is notified immediately (rather than at a later
2247 * clock tick) when this watermark is reached.
2248 * The buffer size is chosen so the watermark should almost never
2249 * be reached.
2250 * The low watermark is invisibly 0 since the buffer is always
2251 * emptied all at once.
2252 */
2253 com->iptr = com->ibuf = ibuf;
2254 com->ibufend = ibuf + ibufsize;
2255 com->ierroff = ibufsize;
2256 com->ihighwater = ibuf + 3 * ibufsize / 4;
2257 return (0);
2258}
2259
2260static void
2261comstart(tp)
2262 struct tty *tp;
2263{
2264 struct com_s *com;
2265 int s;
2266#ifdef CyDebug
2267 bool_t started;
2268#endif
2269 int unit;
2270
2271 unit = DEV_TO_UNIT(tp->t_dev);
2272 com = com_addr(unit);
2273 s = spltty();
2274
2275#ifdef CyDebug
2276 ++com->start_count;
2277 started = FALSE;
2278#endif
2279
2280 disable_intr();
2281 if (tp->t_state & TS_TTSTOP) {
2282 com->state &= ~CS_TTGO;
2283 if (com->intr_enable & CD1400_SRER_TXRDY)
2284 cd_setreg(com, CD1400_SRER,
2285 com->intr_enable
2286 = (com->intr_enable & ~CD1400_SRER_TXRDY)
2287 | CD1400_SRER_TXMPTY);
2288 } else {

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

2308 && com->state & CS_RTS_IFLOW)
2309#if 0
2310 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2311#else
2312 cd_setreg(com, com->mcr_rts_reg,
2313 com->mcr_image |= com->mcr_rts);
2314#endif
2315 }
2316 enable_intr();
2317 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2318 ttwwakeup(tp);
2319 splx(s);
2320 return;
2321 }
2322 if (tp->t_outq.c_cc != 0) {
2323 struct lbq *qp;
2324 struct lbq *next;
2325
2326 if (!com->obufs[0].l_queued) {
2327#ifdef CyDebug
2328 started = TRUE;
2329#endif
2330 com->obufs[0].l_tail
2331 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2332 sizeof com->obuf1);
2333 com->obufs[0].l_next = NULL;
2334 com->obufs[0].l_queued = TRUE;
2335 disable_intr();
2336 if (com->state & CS_BUSY) {
2337 qp = com->obufq.l_next;
2338 while ((next = qp->l_next) != NULL)
2339 qp = next;
2340 qp->l_next = &com->obufs[0];
2341 } else {
2342 com->obufq.l_head = com->obufs[0].l_head;
2343 com->obufq.l_tail = com->obufs[0].l_tail;
2344 com->obufq.l_next = &com->obufs[0];
2345 com->state |= CS_BUSY;
2346 if (com->state >= (CS_BUSY | CS_TTGO
2347 | CS_ODEVREADY))
2348 cd_setreg(com, CD1400_SRER,
2349 com->intr_enable
2350 = (com->intr_enable
2351 & ~CD1400_SRER_TXMPTY)
2352 | CD1400_SRER_TXRDY);
2353 }
2354 enable_intr();
2355 }
2356 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2357#ifdef CyDebug
2358 started = TRUE;
2359#endif
2360 com->obufs[1].l_tail
2361 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2362 sizeof com->obuf2);
2363 com->obufs[1].l_next = NULL;
2364 com->obufs[1].l_queued = TRUE;
2365 disable_intr();
2366 if (com->state & CS_BUSY) {
2367 qp = com->obufq.l_next;
2368 while ((next = qp->l_next) != NULL)
2369 qp = next;
2370 qp->l_next = &com->obufs[1];
2371 } else {
2372 com->obufq.l_head = com->obufs[1].l_head;
2373 com->obufq.l_tail = com->obufs[1].l_tail;
2374 com->obufq.l_next = &com->obufs[1];
2375 com->state |= CS_BUSY;
2376 if (com->state >= (CS_BUSY | CS_TTGO
2377 | CS_ODEVREADY))
2378 cd_setreg(com, CD1400_SRER,
2379 com->intr_enable
2380 = (com->intr_enable
2381 & ~CD1400_SRER_TXMPTY)
2382 | CD1400_SRER_TXRDY);
2383 }
2384 enable_intr();
2385 }
2386 tp->t_state |= TS_BUSY;
2387 }
2388#ifdef CyDebug
2389 if (started)
2390 ++com->start_real;
2391#endif
2392#if 0
2393 disable_intr();
2394 if (com->state >= (CS_BUSY | CS_TTGO))
2395 siointr1(com); /* fake interrupt to start output */
2396 enable_intr();
2397#endif
2398 ttwwakeup(tp);
2399 splx(s);
2400}
2401
2402static void
2403comstop(tp, rw)
2404 struct tty *tp;
2405 int rw;
2406{
2407 struct com_s *com;
2408 bool_t wakeup_etc;
2409
2410 com = com_addr(DEV_TO_UNIT(tp->t_dev));
2411 wakeup_etc = FALSE;
2412 disable_intr();
2413 if (rw & FWRITE) {
2414 com->obufs[0].l_queued = FALSE;
2415 com->obufs[1].l_queued = FALSE;
2416 if (com->extra_state & CSE_ODONE) {
2417 com_events -= LOTS_OF_EVENTS;
2418 com->extra_state &= ~CSE_ODONE;
2419 if (com->etc != ETC_NONE) {
2420 if (com->etc == ETC_BREAK_ENDED)

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

2427 com_events -= LOTS_OF_EVENTS;
2428 com->state &= ~(CS_ODONE | CS_BUSY);
2429 }
2430 if (rw & FREAD) {
2431 /* XXX no way to reset only input fifo. */
2432 com_events -= (com->iptr - com->ibuf);
2433 com->iptr = com->ibuf;
2434 }
2435 enable_intr();
2436 if (wakeup_etc)
2437 wakeup(&com->etc);
2438 if (rw & FWRITE && com->etc == ETC_NONE)
2439 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
2440 comstart(tp);
2441}
2442
2443static int
2444commctl(com, bits, how)
2445 struct com_s *com;
2446 int bits;
2447 int how;
2448{
2449 int mcr;
2450 int msr;
2451
2452 if (how == DMGET) {
2453 if (com->channel_control & CD1400_CCR_RCVEN)
2454 bits |= TIOCM_LE;
2455 mcr = com->mcr_image;
2456 if (mcr & com->mcr_dtr)
2457 bits |= TIOCM_DTR;
2458 if (mcr & com->mcr_rts)

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

2480 bits |= TIOCM_RI;
2481 return (bits);
2482 }
2483 mcr = 0;
2484 if (bits & TIOCM_DTR)
2485 mcr |= com->mcr_dtr;
2486 if (bits & TIOCM_RTS)
2487 mcr |= com->mcr_rts;
2488 disable_intr();
2489 switch (how) {
2490 case DMSET:
2491 com->mcr_image = mcr;
2492 cd_setreg(com, CD1400_MSVR1, mcr);
2493 cd_setreg(com, CD1400_MSVR2, mcr);
2494 break;
2495 case DMBIS:
2496 com->mcr_image = mcr = com->mcr_image | mcr;
2497 cd_setreg(com, CD1400_MSVR1, mcr);
2498 cd_setreg(com, CD1400_MSVR2, mcr);
2499 break;
2500 case DMBIC:
2501 com->mcr_image = mcr = com->mcr_image & ~mcr;
2502 cd_setreg(com, CD1400_MSVR1, mcr);
2503 cd_setreg(com, CD1400_MSVR2, mcr);
2504 break;
2505 }
2506 enable_intr();
2507 return (0);
2508}
2509
2510static void
2511siosettimeout()
2512{
2513 struct com_s *com;
2514 bool_t someopen;

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

2560 /*
2561 * Recover from lost output interrupts.
2562 * Poll any lines that don't use interrupts.
2563 */
2564 for (unit = 0; unit < NSIO; ++unit) {
2565 com = com_addr(unit);
2566 if (com != NULL
2567 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2568 disable_intr();
2569 siointr1(com);
2570 enable_intr();
2571 }
2572 }
2573#endif
2574
2575 /*
2576 * Check for and log errors, but not too often.
2577 */
2578 if (--sio_timeouts_until_log > 0)
2579 return;
2580 sio_timeouts_until_log = hz / sio_timeout;
2581 for (unit = 0; unit < NSIO; ++unit) {
2582 int errnum;
2583
2584 com = com_addr(unit);
2585 if (com == NULL)
2586 continue;
2587 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2588 u_int delta;
2589 u_long total;
2590
2591 disable_intr();
2592 delta = com->delta_error_counts[errnum];
2593 com->delta_error_counts[errnum] = 0;
2594 enable_intr();
2595 if (delta == 0)
2596 continue;
2597 total = com->error_counts[errnum] += delta;
2598 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n",
2599 unit, delta, error_desc[errnum],
2600 delta == 1 ? "" : "s", total);
2601 }
2602 }

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

2738 }
2739}
2740
2741static void
2742cd_etc(com, etc)
2743 struct com_s *com;
2744 int etc;
2745{
2746 /*
2747 * We can't change the hardware's ETC state while there are any
2748 * characters in the tx fifo, since those characters would be
2749 * interpreted as commands! Unputting characters from the fifo
2750 * is difficult, so we wait up to 12 character times for the fifo
2751 * to drain. The command will be delayed for up to 2 character
2752 * times for the tx to become empty. Unputting characters from
2753 * the tx holding and shift registers is impossible, so we wait
2754 * for the tx to become empty so that the command is sure to be
2755 * executed soon after we issue it.
2756 */
2757 disable_intr();
2758 if (com->etc == etc) {
2759 enable_intr();
2760 goto wait;
2761 }
2762 if ((etc == CD1400_ETC_SENDBREAK
2763 && (com->etc == ETC_BREAK_STARTING
2764 || com->etc == ETC_BREAK_STARTED))
2765 || (etc == CD1400_ETC_STOPBREAK
2766 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED
2767 || com->etc == ETC_NONE))) {
2768 enable_intr();
2769 return;
2770 }
2771 com->etc = etc;
2772 cd_setreg(com, CD1400_SRER,
2773 com->intr_enable
2774 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY);
2775 enable_intr();
2776wait:
2777 while (com->etc == etc
2778 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0)
2779 continue;
2780}
2781
2782static int
2783cd_getreg(com, reg)
2784 struct com_s *com;
2785 int reg;
2786{
2787 struct com_s *basecom;
2788 u_char car;
2789 int cy_align;
2790 u_long ef;
2791 cy_addr iobase;
2792 int val;
2793
2794 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2795 car = com->unit & CD1400_CAR_CHAN;
2796 cy_align = com->cy_align;
2797 iobase = com->iobase;
2798 ef = read_eflags();
2799 if (ef & PSL_I)
2800 disable_intr();
2801 if (basecom->car != car)
2802 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2803 val = cd_inb(iobase, reg, cy_align);
2804 if (ef & PSL_I)
2805 enable_intr();
2806 return (val);
2807}
2808
2809static void
2810cd_setreg(com, reg, val)
2811 struct com_s *com;
2812 int reg;
2813 int val;
2814{
2815 struct com_s *basecom;
2816 u_char car;
2817 int cy_align;
2818 u_long ef;
2819 cy_addr iobase;
2820
2821 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2822 car = com->unit & CD1400_CAR_CHAN;
2823 cy_align = com->cy_align;
2824 iobase = com->iobase;
2825 ef = read_eflags();
2826 if (ef & PSL_I)
2827 disable_intr();
2828 if (basecom->car != car)
2829 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2830 cd_outb(iobase, reg, cy_align, val);
2831 if (ef & PSL_I)
2832 enable_intr();
2833}
2834
2835#ifdef CyDebug
2836/* useful in ddb */
2837void
2838cystatus(unit)
2839 int unit;
2840{

--- 54 unchanged lines hidden ---