Deleted Added
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 74810 2001-03-26 12:41:29Z phk $
30 * $FreeBSD: head/sys/dev/cy/cy.c 74903 2001-03-28 03:06:10Z jhb $
31 */
32
33#include "opt_compat.h"
34#include "cy.h"
35
36/*
37 * TODO:
38 * Atomic COR change.

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

345static int sioattach __P((struct isa_device *dev));
346static void cd1400_channel_cmd __P((struct com_s *com, int cmd));
347static void cd1400_channel_cmd_wait __P((struct com_s *com));
348static void cd_etc __P((struct com_s *com, int etc));
349static int cd_getreg __P((struct com_s *com, int reg));
350static void cd_setreg __P((struct com_s *com, int reg, int val));
351static timeout_t siodtrwakeup;
352static void comhardclose __P((struct com_s *com));
353static void sioinput __P((struct com_s *com));
353static void sioinput __P((struct com_s *com, critical_t *savecrit));
354#if 0
355static void siointr1 __P((struct com_s *com));
356#endif
357static int commctl __P((struct com_s *com, int bits, int how));
358static int comparam __P((struct tty *tp, struct termios *t));
359static void siopoll __P((void *arg));
360static int sioprobe __P((struct isa_device *dev));
361static void siosettimeout __P((void));

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

667 struct proc *p;
668{
669 struct com_s *com;
670 int error;
671 int mynor;
672 int s;
673 struct tty *tp;
674 int unit;
675 int intrsave;
675 critical_t savecrit;
676
677 mynor = minor(dev);
678 unit = MINOR_TO_UNIT(mynor);
679 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL)
680 return (ENXIO);
681 if (mynor & CONTROL_MASK)
682 return (0);
683#if 0 /* XXX */

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

774 if (!(inb(com->line_status_port) & LSR_RXRDY))
775 break;
776 outb(iobase + com_fifo, 0);
777 DELAY(100);
778 (void) inb(com->data_port);
779 }
780 }
781
782 intrsave = save_intr();
783 disable_intr();
782 savecrit = critical_enter();
783 COM_LOCK();
784 (void) inb(com->line_status_port);
785 (void) inb(com->data_port);
786 com->prev_modem_status = com->last_modem_status
787 = inb(com->modem_status_port);
788 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS
789 | IER_EMSC);
790 COM_UNLOCK();
792 restore_intr(intrsave);
791 critical_exit(savecrit);
792#else /* !0 */
793 /*
794 * Flush fifos. This requires a full channel reset which
795 * also disables the transmitter and receiver. Recover
796 * from this.
797 */
798 cd1400_channel_cmd(com,
799 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET);
800 cd1400_channel_cmd(com, com->channel_control);
801
803 intrsave = save_intr();
804 disable_intr();
802 savecrit = critical_enter();
803 COM_LOCK();
804 com->prev_modem_status = com->last_modem_status
805 = cd_getreg(com, CD1400_MSVR2);
806 cd_setreg(com, CD1400_SRER,
807 com->intr_enable
808 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
809 COM_UNLOCK();
812 restore_intr(intrsave);
810 critical_exit(savecrit);
811#endif /* 0 */
812 /*
813 * Handle initial DCD. Callout devices get a fake initial
814 * DCD (trapdoor DCD). If we are callout, then any sleeping
815 * callin opens get woken up and resume sleeping on "cybi"
816 * instead of "cydcd".
817 */
818 /*

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

885static void
886comhardclose(com)
887 struct com_s *com;
888{
889 cy_addr iobase;
890 int s;
891 struct tty *tp;
892 int unit;
895 int intrsave;
893 critical_t savecrit;
894
895 unit = com->unit;
896 iobase = com->iobase;
897 s = spltty();
898#if 0
899 com->poll = FALSE;
900 com->poll_output = FALSE;
901#endif
902 com->do_timestamp = 0;
903#if 0
904 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
905#else
906 /* XXX */
909 intrsave = save_intr();
910 disable_intr();
907 savecrit = critical_enter();
908 COM_LOCK();
909 com->etc = ETC_NONE;
910 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC);
911 COM_UNLOCK();
915 restore_intr(intrsave);
912 critical_exit(savecrit);
913 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
914#endif
915
916 {
917#if 0
918 outb(iobase + com_ier, 0);
919#else
923 intrsave = save_intr();
924 disable_intr();
920 savecrit = critical_enter();
921 COM_LOCK();
922 cd_setreg(com, CD1400_SRER, com->intr_enable = 0);
923 COM_UNLOCK();
928 restore_intr(intrsave);
924 critical_exit(savecrit);
925#endif
926 tp = com->tp;
927 if ((tp->t_cflag & HUPCL)
928 /*
929 * XXX we will miss any carrier drop between here and the
930 * next open. Perhaps we should watch DCD even when the
931 * port is closed; it is not sufficient to check it at
932 * the next open because it might go up and down while

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

1012}
1013
1014/*
1015 * This function:
1016 * a) needs to be called with COM_LOCK() held, and
1017 * b) needs to return with COM_LOCK() held.
1018 */
1019static void
1024sioinput(com)
1020sioinput(com, savecrit)
1021 struct com_s *com;
1022 critical_t *savecrit;
1023{
1024 u_char *buf;
1025 int incc;
1026 u_char line_status;
1027 int recv_data;
1028 struct tty *tp;
1032 int intrsave;
1029
1030 buf = com->ibuf;
1031 tp = com->tp;
1032 if (!(tp->t_state & TS_ISOPEN)) {
1033 com_events -= (com->iptr - com->ibuf);
1034 com->iptr = com->ibuf;
1035 return;
1036 }

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

1044 */
1045
1046 do {
1047 /*
1048 * This may look odd, but it is using save-and-enable
1049 * semantics instead of the save-and-disable semantics
1050 * that are used everywhere else.
1051 */
1056 intrsave = save_intr();
1052 COM_UNLOCK();
1058 enable_intr();
1053 critical_exit(*savecrit);
1054 incc = com->iptr - buf;
1055 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
1056 && (com->state & CS_RTS_IFLOW
1057 || tp->t_iflag & IXOFF)
1058 && !(tp->t_state & TS_TBLOCK))
1059 ttyblock(tp);
1060 com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
1061 += b_to_q((char *)buf, incc, &tp->t_rawq);

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

1066 ttwakeup(tp);
1067 if (tp->t_state & TS_TTSTOP
1068 && (tp->t_iflag & IXANY
1069 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
1070 tp->t_state &= ~TS_TTSTOP;
1071 tp->t_lflag &= ~FLUSHO;
1072 comstart(tp);
1073 }
1079 restore_intr(intrsave);
1074 *savecrit = critical_enter();
1075 COM_LOCK();
1076 } while (buf < com->iptr);
1077 } else {
1078 do {
1079 /*
1080 * This may look odd, but it is using save-and-enable
1081 * semantics instead of the save-and-disable semantics
1082 * that are used everywhere else.
1083 */
1089 intrsave = save_intr();
1084 COM_UNLOCK();
1091 enable_intr();
1085 critical_exit(*savecrit);
1086 line_status = buf[com->ierroff];
1087 recv_data = *buf++;
1088 if (line_status
1089 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
1090 if (line_status & LSR_BI)
1091 recv_data |= TTY_BI;
1092 if (line_status & LSR_FE)
1093 recv_data |= TTY_FE;
1094 if (line_status & LSR_OE)
1095 recv_data |= TTY_OE;
1096 if (line_status & LSR_PE)
1097 recv_data |= TTY_PE;
1098 }
1099 (*linesw[tp->t_line].l_rint)(recv_data, tp);
1106 restore_intr(intrsave);
1100 *savecrit = critical_enter();
1101 COM_LOCK();
1102 } while (buf < com->iptr);
1103 }
1104 com_events -= (com->iptr - com->ibuf);
1105 com->iptr = com->ibuf;
1106
1107 /*
1108 * There is now room for another low-level buffer full of input,

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

1766 splx(s);
1767 return (0);
1768}
1769
1770static void
1771siopoll(void *arg)
1772{
1773 int unit;
1780 int intrsave;
1774 critical_t savecrit;
1775
1776#ifdef CyDebug
1777 ++cy_timeouts;
1778#endif
1779 if (com_events == 0)
1780 return;
1781repeat:
1782 for (unit = 0; unit < NSIO; ++unit) {

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

1789 continue;
1790 tp = com->tp;
1791 if (tp == NULL) {
1792 /*
1793 * XXX forget any events related to closed devices
1794 * (actually never opened devices) so that we don't
1795 * loop.
1796 */
1803 intrsave = save_intr();
1804 disable_intr();
1797 savecrit = critical_enter();
1798 COM_LOCK();
1799 incc = com->iptr - com->ibuf;
1800 com->iptr = com->ibuf;
1801 if (com->state & CS_CHECKMSR) {
1802 incc += LOTS_OF_EVENTS;
1803 com->state &= ~CS_CHECKMSR;
1804 }
1805 com_events -= incc;
1806 COM_UNLOCK();
1814 restore_intr(intrsave);
1807 critical_exit(savecrit);
1808 if (incc != 0)
1809 log(LOG_DEBUG,
1810 "sio%d: %d events for device with no tp\n",
1811 unit, incc);
1812 continue;
1813 }
1814 if (com->iptr != com->ibuf) {
1822 intrsave = save_intr();
1823 disable_intr();
1815 savecrit = critical_enter();
1816 COM_LOCK();
1825 sioinput(com);
1817 sioinput(com, &savecrit);
1818 COM_UNLOCK();
1827 restore_intr(intrsave);
1819 critical_exit(savecrit);
1820 }
1821 if (com->state & CS_CHECKMSR) {
1822 u_char delta_modem_status;
1823
1832 intrsave = save_intr();
1833 disable_intr();
1824 savecrit = critical_enter();
1825 COM_LOCK();
1835 sioinput(com);
1826 sioinput(com, &savecrit);
1827 delta_modem_status = com->last_modem_status
1828 ^ com->prev_modem_status;
1829 com->prev_modem_status = com->last_modem_status;
1830 com_events -= LOTS_OF_EVENTS;
1831 com->state &= ~CS_CHECKMSR;
1832 COM_UNLOCK();
1842 restore_intr(intrsave);
1833 critical_exit(savecrit);
1834 if (delta_modem_status & MSR_DCD)
1835 (*linesw[tp->t_line].l_modem)
1836 (tp, com->prev_modem_status & MSR_DCD);
1837 }
1838 if (com->extra_state & CSE_ODONE) {
1848 intrsave = save_intr();
1849 disable_intr();
1839 savecrit = critical_enter();
1840 COM_LOCK();
1841 com_events -= LOTS_OF_EVENTS;
1842 com->extra_state &= ~CSE_ODONE;
1843 COM_UNLOCK();
1854 restore_intr(intrsave);
1844 critical_exit(savecrit);
1845 if (!(com->state & CS_BUSY)) {
1846 tp->t_state &= ~TS_BUSY;
1847 ttwwakeup(com->tp);
1848 }
1849 if (com->etc != ETC_NONE) {
1850 if (com->etc == ETC_BREAK_ENDED)
1851 com->etc = ETC_NONE;
1852 wakeup(&com->etc);
1853 }
1854 }
1855 if (com->state & CS_ODONE) {
1866 intrsave = save_intr();
1867 disable_intr();
1856 savecrit = critical_enter();
1857 COM_LOCK();
1858 com_events -= LOTS_OF_EVENTS;
1859 com->state &= ~CS_ODONE;
1860 COM_UNLOCK();
1872 restore_intr(intrsave);
1861 critical_exit(savecrit);
1862 (*linesw[tp->t_line].l_start)(tp);
1863 }
1864 if (com_events == 0)
1865 break;
1866 }
1867 if (com_events >= LOTS_OF_EVENTS)
1868 goto repeat;
1869}

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

1882 int iflag;
1883 int iprescaler;
1884 int itimeout;
1885 int odivisor;
1886 int oprescaler;
1887 u_char opt;
1888 int s;
1889 int unit;
1901 int intrsave;
1890 critical_t savecrit;
1891
1892 /* do historical conversions */
1893 if (t->c_ispeed == 0)
1894 t->c_ispeed = t->c_ospeed;
1895
1896 unit = DEV_TO_UNIT(tp->t_dev);
1897 com = com_addr(unit);
1898

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

2030 opt |= CD1400_COR2_IXANY;
2031 if (iflag & IXOFF)
2032 opt |= CD1400_COR2_IXOFF;
2033#endif
2034#ifndef SOFT_CTS_OFLOW
2035 if (cflag & CCTS_OFLOW)
2036 opt |= CD1400_COR2_CCTS_OFLOW;
2037#endif
2049 intrsave = save_intr();
2050 disable_intr();
2038 savecrit = critical_enter();
2039 COM_LOCK();
2040 if (opt != com->cor[1]) {
2041 cor_change |= CD1400_CCR_COR2;
2042 cd_setreg(com, CD1400_COR2, com->cor[1] = opt);
2043 }
2044 COM_UNLOCK();
2057 restore_intr(intrsave);
2045 critical_exit(savecrit);
2046
2047 /*
2048 * set channel option register 3 -
2049 * receiver FIFO interrupt threshold
2050 * flow control
2051 */
2052 opt = RxFifoThreshold;
2053#ifdef Smarts

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

2158 opt |= CD1400_MCOR2_CTSod;
2159#endif
2160 cd_setreg(com, CD1400_MCOR2, opt);
2161
2162 /*
2163 * XXX should have done this long ago, but there is too much state
2164 * to change all atomically.
2165 */
2178 intrsave = save_intr();
2179 disable_intr();
2166 savecrit = critical_enter();
2167 COM_LOCK();
2168
2169 com->state &= ~CS_TTGO;
2170 if (!(tp->t_state & TS_TTSTOP))
2171 com->state |= CS_TTGO;
2172 if (cflag & CRTS_IFLOW) {
2173 com->state |= CS_RTS_IFLOW;
2174 /*

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

2226 if (com->intr_enable & CD1400_SRER_TXRDY)
2227 cd_setreg(com, CD1400_SRER,
2228 com->intr_enable
2229 = (com->intr_enable & ~CD1400_SRER_TXRDY)
2230 | CD1400_SRER_TXMPTY);
2231 }
2232
2233 COM_UNLOCK();
2247 restore_intr(intrsave);
2234 critical_exit(savecrit);
2235 splx(s);
2236 comstart(tp);
2237 if (com->ibufold != NULL) {
2238 free(com->ibufold, M_DEVBUF);
2239 com->ibufold = NULL;
2240 }
2241 return (0);
2242}
2243
2244static int
2245siosetwater(com, speed)
2246 struct com_s *com;
2247 speed_t speed;
2248{
2249 int cp4ticks;
2250 u_char *ibuf;
2251 int ibufsize;
2252 struct tty *tp;
2266 int intrsave;
2253 critical_t savecrit;
2254
2255 /*
2256 * Make the buffer size large enough to handle a softtty interrupt
2257 * latency of about 2 ticks without loss of throughput or data
2258 * (about 3 ticks if input flow control is not used or not honoured,
2259 * but a bit less for CS5-CS7 modes).
2260 */
2261 cp4ticks = speed / 10 / hz * 4;

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

2283 tp->t_ispeedwat = (speed_t)-1;
2284 tp->t_ospeedwat = (speed_t)-1;
2285 }
2286
2287 /*
2288 * Read current input buffer, if any. Continue with interrupts
2289 * disabled.
2290 */
2304 intrsave = save_intr();
2305 disable_intr();
2291 savecrit = critical_enter();
2292 COM_LOCK();
2293 if (com->iptr != com->ibuf)
2308 sioinput(com);
2294 sioinput(com, &savecrit);
2295
2296 /*-
2297 * Initialize critical variables, including input buffer watermarks.
2298 * The external device is asked to stop sending when the buffer
2299 * exactly reaches high water, or when the high level requests it.
2300 * The high level is notified immediately (rather than at a later
2301 * clock tick) when this watermark is reached.
2302 * The buffer size is chosen so the watermark should almost never
2303 * be reached.
2304 * The low watermark is invisibly 0 since the buffer is always
2305 * emptied all at once.
2306 */
2307 com->iptr = com->ibuf = ibuf;
2308 com->ibufend = ibuf + ibufsize;
2309 com->ierroff = ibufsize;
2310 com->ihighwater = ibuf + 3 * ibufsize / 4;
2311
2312 COM_UNLOCK();
2327 restore_intr(intrsave);
2313 critical_exit(savecrit);
2314 return (0);
2315}
2316
2317static void
2318comstart(tp)
2319 struct tty *tp;
2320{
2321 struct com_s *com;
2322 int s;
2323#ifdef CyDebug
2324 bool_t started;
2325#endif
2326 int unit;
2341 int intrsave;
2327 critical_t savecrit;
2328
2329 unit = DEV_TO_UNIT(tp->t_dev);
2330 com = com_addr(unit);
2331 s = spltty();
2332
2333#ifdef CyDebug
2334 ++com->start_count;
2335 started = FALSE;
2336#endif
2337
2352 intrsave = save_intr();
2353 disable_intr();
2338 savecrit = critical_enter();
2339 COM_LOCK();
2340 if (tp->t_state & TS_TTSTOP) {
2341 com->state &= ~CS_TTGO;
2342 if (com->intr_enable & CD1400_SRER_TXRDY)
2343 cd_setreg(com, CD1400_SRER,
2344 com->intr_enable
2345 = (com->intr_enable & ~CD1400_SRER_TXRDY)
2346 | CD1400_SRER_TXMPTY);

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

2368#if 0
2369 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2370#else
2371 cd_setreg(com, com->mcr_rts_reg,
2372 com->mcr_image |= com->mcr_rts);
2373#endif
2374 }
2375 COM_UNLOCK();
2391 restore_intr(intrsave);
2376 critical_exit(savecrit);
2377 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2378 ttwwakeup(tp);
2379 splx(s);
2380 return;
2381 }
2382 if (tp->t_outq.c_cc != 0) {
2383 struct lbq *qp;
2384 struct lbq *next;
2385
2386 if (!com->obufs[0].l_queued) {
2387#ifdef CyDebug
2388 started = TRUE;
2389#endif
2390 com->obufs[0].l_tail
2391 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2392 sizeof com->obuf1);
2393 com->obufs[0].l_next = NULL;
2394 com->obufs[0].l_queued = TRUE;
2410 intrsave = save_intr();
2411 disable_intr();
2395 savecrit = critical_enter();
2396 COM_LOCK();
2397 if (com->state & CS_BUSY) {
2398 qp = com->obufq.l_next;
2399 while ((next = qp->l_next) != NULL)
2400 qp = next;
2401 qp->l_next = &com->obufs[0];
2402 } else {
2403 com->obufq.l_head = com->obufs[0].l_head;

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

2408 | CS_ODEVREADY))
2409 cd_setreg(com, CD1400_SRER,
2410 com->intr_enable
2411 = (com->intr_enable
2412 & ~CD1400_SRER_TXMPTY)
2413 | CD1400_SRER_TXRDY);
2414 }
2415 COM_UNLOCK();
2432 restore_intr(intrsave);
2416 critical_exit(savecrit);
2417 }
2418 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2419#ifdef CyDebug
2420 started = TRUE;
2421#endif
2422 com->obufs[1].l_tail
2423 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2424 sizeof com->obuf2);
2425 com->obufs[1].l_next = NULL;
2426 com->obufs[1].l_queued = TRUE;
2443 intrsave = save_intr();
2444 disable_intr();
2427 savecrit = critical_enter();
2428 COM_LOCK();
2429 if (com->state & CS_BUSY) {
2430 qp = com->obufq.l_next;
2431 while ((next = qp->l_next) != NULL)
2432 qp = next;
2433 qp->l_next = &com->obufs[1];
2434 } else {
2435 com->obufq.l_head = com->obufs[1].l_head;

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

2440 | CS_ODEVREADY))
2441 cd_setreg(com, CD1400_SRER,
2442 com->intr_enable
2443 = (com->intr_enable
2444 & ~CD1400_SRER_TXMPTY)
2445 | CD1400_SRER_TXRDY);
2446 }
2447 COM_UNLOCK();
2465 restore_intr(intrsave);
2448 critical_exit(savecrit);
2449 }
2450 tp->t_state |= TS_BUSY;
2451 }
2452#ifdef CyDebug
2453 if (started)
2454 ++com->start_real;
2455#endif
2456#if 0
2474 intrsave = save_intr();
2475 disable_intr();
2457 savecrit = critical_enter();
2458 COM_LOCK();
2459 if (com->state >= (CS_BUSY | CS_TTGO))
2460 siointr1(com); /* fake interrupt to start output */
2461 COM_UNLOCK();
2480 restore_intr(intrsave);
2462 critical_exit(savecrit);
2463#endif
2464 ttwwakeup(tp);
2465 splx(s);
2466}
2467
2468static void
2469comstop(tp, rw)
2470 struct tty *tp;
2471 int rw;
2472{
2473 struct com_s *com;
2474 bool_t wakeup_etc;
2493 int intrsave;
2475 critical_t savecrit;
2476
2477 com = com_addr(DEV_TO_UNIT(tp->t_dev));
2478 wakeup_etc = FALSE;
2497 intrsave = save_intr();
2498 disable_intr();
2479 savecrit = critical_enter();
2480 COM_LOCK();
2481 if (rw & FWRITE) {
2482 com->obufs[0].l_queued = FALSE;
2483 com->obufs[1].l_queued = FALSE;
2484 if (com->extra_state & CSE_ODONE) {
2485 com_events -= LOTS_OF_EVENTS;
2486 com->extra_state &= ~CSE_ODONE;
2487 if (com->etc != ETC_NONE) {

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

2496 com->state &= ~(CS_ODONE | CS_BUSY);
2497 }
2498 if (rw & FREAD) {
2499 /* XXX no way to reset only input fifo. */
2500 com_events -= (com->iptr - com->ibuf);
2501 com->iptr = com->ibuf;
2502 }
2503 COM_UNLOCK();
2523 restore_intr(intrsave);
2504 critical_exit(savecrit);
2505 if (wakeup_etc)
2506 wakeup(&com->etc);
2507 if (rw & FWRITE && com->etc == ETC_NONE)
2508 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
2509 comstart(tp);
2510}
2511
2512static int
2513commctl(com, bits, how)
2514 struct com_s *com;
2515 int bits;
2516 int how;
2517{
2518 int mcr;
2519 int msr;
2539 int intrsave;
2520 critical_t savecrit;
2521
2522 if (how == DMGET) {
2523 if (com->channel_control & CD1400_CCR_RCVEN)
2524 bits |= TIOCM_LE;
2525 mcr = com->mcr_image;
2526 if (mcr & com->mcr_dtr)
2527 bits |= TIOCM_DTR;
2528 if (mcr & com->mcr_rts)

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

2550 bits |= TIOCM_RI;
2551 return (bits);
2552 }
2553 mcr = 0;
2554 if (bits & TIOCM_DTR)
2555 mcr |= com->mcr_dtr;
2556 if (bits & TIOCM_RTS)
2557 mcr |= com->mcr_rts;
2577 intrsave = save_intr();
2578 disable_intr();
2558 savecrit = critical_enter();
2559 COM_LOCK();
2560 switch (how) {
2561 case DMSET:
2562 com->mcr_image = mcr;
2563 cd_setreg(com, CD1400_MSVR1, mcr);
2564 cd_setreg(com, CD1400_MSVR2, mcr);
2565 break;
2566 case DMBIS:
2567 com->mcr_image = mcr = com->mcr_image | mcr;
2568 cd_setreg(com, CD1400_MSVR1, mcr);
2569 cd_setreg(com, CD1400_MSVR2, mcr);
2570 break;
2571 case DMBIC:
2572 com->mcr_image = mcr = com->mcr_image & ~mcr;
2573 cd_setreg(com, CD1400_MSVR1, mcr);
2574 cd_setreg(com, CD1400_MSVR2, mcr);
2575 break;
2576 }
2577 COM_UNLOCK();
2598 restore_intr(intrsave);
2578 critical_exit(savecrit);
2579 return (0);
2580}
2581
2582static void
2583siosettimeout()
2584{
2585 struct com_s *com;
2586 bool_t someopen;

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

2632 /*
2633 * Recover from lost output interrupts.
2634 * Poll any lines that don't use interrupts.
2635 */
2636 for (unit = 0; unit < NSIO; ++unit) {
2637 com = com_addr(unit);
2638 if (com != NULL
2639 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2660 int intrsave;
2640 critical_t savecrit;
2641
2662 intrsave = save_intr();
2663 disable_intr();
2642 savecrit = critical_enter();
2643 COM_LOCK();
2644 siointr1(com);
2645 COM_UNLOCK();
2667 restore_intr(intrsave);
2646 critical_exit(savecrit);
2647 }
2648 }
2649#endif
2650
2651 /*
2652 * Check for and log errors, but not too often.
2653 */
2654 if (--sio_timeouts_until_log > 0)
2655 return;
2656 sio_timeouts_until_log = hz / sio_timeout;
2657 for (unit = 0; unit < NSIO; ++unit) {
2658 int errnum;
2659
2660 com = com_addr(unit);
2661 if (com == NULL)
2662 continue;
2663 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2664 u_int delta;
2665 u_long total;
2687 int intrsave;
2666 critical_t savecrit;
2667
2689 intrsave = save_intr();
2690 disable_intr();
2668 savecrit = critical_enter();
2669 COM_LOCK();
2670 delta = com->delta_error_counts[errnum];
2671 com->delta_error_counts[errnum] = 0;
2672 COM_UNLOCK();
2695 restore_intr(intrsave);
2673 critical_exit(savecrit);
2674 if (delta == 0)
2675 continue;
2676 total = com->error_counts[errnum] += delta;
2677 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n",
2678 unit, delta, error_desc[errnum],
2679 delta == 1 ? "" : "s", total);
2680 }
2681 }

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

2817 }
2818}
2819
2820static void
2821cd_etc(com, etc)
2822 struct com_s *com;
2823 int etc;
2824{
2847 int intrsave;
2825 critical_t savecrit;
2826
2827 /*
2828 * We can't change the hardware's ETC state while there are any
2829 * characters in the tx fifo, since those characters would be
2830 * interpreted as commands! Unputting characters from the fifo
2831 * is difficult, so we wait up to 12 character times for the fifo
2832 * to drain. The command will be delayed for up to 2 character
2833 * times for the tx to become empty. Unputting characters from
2834 * the tx holding and shift registers is impossible, so we wait
2835 * for the tx to become empty so that the command is sure to be
2836 * executed soon after we issue it.
2837 */
2860 intrsave = save_intr();
2861 disable_intr();
2838 savecrit = critical_enter();
2839 COM_LOCK();
2840 if (com->etc == etc)
2841 goto wait;
2842 if ((etc == CD1400_ETC_SENDBREAK
2843 && (com->etc == ETC_BREAK_STARTING
2844 || com->etc == ETC_BREAK_STARTED))
2845 || (etc == CD1400_ETC_STOPBREAK
2846 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED
2847 || com->etc == ETC_NONE))) {
2848 COM_UNLOCK();
2872 restore_intr(intrsave);
2849 critical_exit(savecrit);
2850 return;
2851 }
2852 com->etc = etc;
2853 cd_setreg(com, CD1400_SRER,
2854 com->intr_enable
2855 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY);
2856wait:
2857 COM_UNLOCK();
2881 restore_intr(intrsave);
2858 critical_exit(savecrit);
2859 while (com->etc == etc
2860 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0)
2861 continue;
2862}
2863
2864static int
2865cd_getreg(com, reg)
2866 struct com_s *com;
2867 int reg;
2868{
2869 struct com_s *basecom;
2870 u_char car;
2871 int cy_align;
2895 int intrsave;
2872 criticale_t savecrit;
2873 register_t eflags;
2874 cy_addr iobase;
2875 int val;
2876
2877 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2878 car = com->unit & CD1400_CAR_CHAN;
2879 cy_align = com->cy_align;
2880 iobase = com->iobase;
2903 intrsave = save_intr();
2904 disable_intr();
2905 if (intrsave & PSL_I)
2881 eflags = read_eflags();
2882 savecrit = critical_enter();
2883 if (eflags & PSL_I)
2884 COM_LOCK();
2885 if (basecom->car != car)
2886 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2887 val = cd_inb(iobase, reg, cy_align);
2910 if (intrsave & PSL_I)
2888 if (eflags & PSL_I)
2889 COM_UNLOCK();
2912 restore_intr(intrsave);
2890 critical_exit(savecrit);
2891 return (val);
2892}
2893
2894static void
2895cd_setreg(com, reg, val)
2896 struct com_s *com;
2897 int reg;
2898 int val;
2899{
2900 struct com_s *basecom;
2901 u_char car;
2902 int cy_align;
2925 int intrsave;
2903 critical_t savecrit;
2904 register_t eflags;
2905 cy_addr iobase;
2906
2907 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2908 car = com->unit & CD1400_CAR_CHAN;
2909 cy_align = com->cy_align;
2910 iobase = com->iobase;
2932 intrsave = save_intr();
2933 disable_intr();
2934 if (intrsave & PSL_I)
2911 eflags = read_eflags();
2912 savecrit = critical_enter();
2913 if (eflags & PSL_I)
2914 COM_LOCK();
2915 if (basecom->car != car)
2916 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2917 cd_outb(iobase, reg, cy_align, val);
2939 if (intrsave & PSL_I)
2918 if (eflags & PSL_I)
2919 COM_UNLOCK();
2941 restore_intr(intrsave);
2920 critical_exit(savecrit);
2921}
2922
2923#ifdef CyDebug
2924/* useful in ddb */
2925void
2926cystatus(unit)
2927 int unit;
2928{

--- 54 unchanged lines hidden ---