Deleted Added
sdiff udiff text old ( 74810 ) new ( 74903 )
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_isa.c 74810 2001-03-26 12:41:29Z phk $
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));
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;
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();
784 COM_LOCK();
785 (void) inb(com->line_status_port);
786 (void) inb(com->data_port);
787 com->prev_modem_status = com->last_modem_status
788 = inb(com->modem_status_port);
789 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS
790 | IER_EMSC);
791 COM_UNLOCK();
792 restore_intr(intrsave);
793#else /* !0 */
794 /*
795 * Flush fifos. This requires a full channel reset which
796 * also disables the transmitter and receiver. Recover
797 * from this.
798 */
799 cd1400_channel_cmd(com,
800 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET);
801 cd1400_channel_cmd(com, com->channel_control);
802
803 intrsave = save_intr();
804 disable_intr();
805 COM_LOCK();
806 com->prev_modem_status = com->last_modem_status
807 = cd_getreg(com, CD1400_MSVR2);
808 cd_setreg(com, CD1400_SRER,
809 com->intr_enable
810 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
811 COM_UNLOCK();
812 restore_intr(intrsave);
813#endif /* 0 */
814 /*
815 * Handle initial DCD. Callout devices get a fake initial
816 * DCD (trapdoor DCD). If we are callout, then any sleeping
817 * callin opens get woken up and resume sleeping on "cybi"
818 * instead of "cydcd".
819 */
820 /*

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

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

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

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

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

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

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

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

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

1772 splx(s);
1773 return (0);
1774}
1775
1776static void
1777siopoll(void *arg)
1778{
1779 int unit;
1780 int intrsave;
1781
1782#ifdef CyDebug
1783 ++cy_timeouts;
1784#endif
1785 if (com_events == 0)
1786 return;
1787repeat:
1788 for (unit = 0; unit < NSIO; ++unit) {

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

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

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

1893 int iflag;
1894 int iprescaler;
1895 int itimeout;
1896 int odivisor;
1897 int oprescaler;
1898 u_char opt;
1899 int s;
1900 int unit;
1901 int intrsave;
1902
1903 /* do historical conversions */
1904 if (t->c_ispeed == 0)
1905 t->c_ispeed = t->c_ospeed;
1906
1907 unit = DEV_TO_UNIT(tp->t_dev);
1908 com = com_addr(unit);
1909

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

2041 opt |= CD1400_COR2_IXANY;
2042 if (iflag & IXOFF)
2043 opt |= CD1400_COR2_IXOFF;
2044#endif
2045#ifndef SOFT_CTS_OFLOW
2046 if (cflag & CCTS_OFLOW)
2047 opt |= CD1400_COR2_CCTS_OFLOW;
2048#endif
2049 intrsave = save_intr();
2050 disable_intr();
2051 COM_LOCK();
2052 if (opt != com->cor[1]) {
2053 cor_change |= CD1400_CCR_COR2;
2054 cd_setreg(com, CD1400_COR2, com->cor[1] = opt);
2055 }
2056 COM_UNLOCK();
2057 restore_intr(intrsave);
2058
2059 /*
2060 * set channel option register 3 -
2061 * receiver FIFO interrupt threshold
2062 * flow control
2063 */
2064 opt = RxFifoThreshold;
2065#ifdef Smarts

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

2170 opt |= CD1400_MCOR2_CTSod;
2171#endif
2172 cd_setreg(com, CD1400_MCOR2, opt);
2173
2174 /*
2175 * XXX should have done this long ago, but there is too much state
2176 * to change all atomically.
2177 */
2178 intrsave = save_intr();
2179 disable_intr();
2180 COM_LOCK();
2181
2182 com->state &= ~CS_TTGO;
2183 if (!(tp->t_state & TS_TTSTOP))
2184 com->state |= CS_TTGO;
2185 if (cflag & CRTS_IFLOW) {
2186 com->state |= CS_RTS_IFLOW;
2187 /*

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

2239 if (com->intr_enable & CD1400_SRER_TXRDY)
2240 cd_setreg(com, CD1400_SRER,
2241 com->intr_enable
2242 = (com->intr_enable & ~CD1400_SRER_TXRDY)
2243 | CD1400_SRER_TXMPTY);
2244 }
2245
2246 COM_UNLOCK();
2247 restore_intr(intrsave);
2248 splx(s);
2249 comstart(tp);
2250 if (com->ibufold != NULL) {
2251 free(com->ibufold, M_DEVBUF);
2252 com->ibufold = NULL;
2253 }
2254 return (0);
2255}
2256
2257static int
2258siosetwater(com, speed)
2259 struct com_s *com;
2260 speed_t speed;
2261{
2262 int cp4ticks;
2263 u_char *ibuf;
2264 int ibufsize;
2265 struct tty *tp;
2266 int intrsave;
2267
2268 /*
2269 * Make the buffer size large enough to handle a softtty interrupt
2270 * latency of about 2 ticks without loss of throughput or data
2271 * (about 3 ticks if input flow control is not used or not honoured,
2272 * but a bit less for CS5-CS7 modes).
2273 */
2274 cp4ticks = speed / 10 / hz * 4;

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

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

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

2383#if 0
2384 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2385#else
2386 cd_setreg(com, com->mcr_rts_reg,
2387 com->mcr_image |= com->mcr_rts);
2388#endif
2389 }
2390 COM_UNLOCK();
2391 restore_intr(intrsave);
2392 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2393 ttwwakeup(tp);
2394 splx(s);
2395 return;
2396 }
2397 if (tp->t_outq.c_cc != 0) {
2398 struct lbq *qp;
2399 struct lbq *next;
2400
2401 if (!com->obufs[0].l_queued) {
2402#ifdef CyDebug
2403 started = TRUE;
2404#endif
2405 com->obufs[0].l_tail
2406 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2407 sizeof com->obuf1);
2408 com->obufs[0].l_next = NULL;
2409 com->obufs[0].l_queued = TRUE;
2410 intrsave = save_intr();
2411 disable_intr();
2412 COM_LOCK();
2413 if (com->state & CS_BUSY) {
2414 qp = com->obufq.l_next;
2415 while ((next = qp->l_next) != NULL)
2416 qp = next;
2417 qp->l_next = &com->obufs[0];
2418 } else {
2419 com->obufq.l_head = com->obufs[0].l_head;

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

2424 | CS_ODEVREADY))
2425 cd_setreg(com, CD1400_SRER,
2426 com->intr_enable
2427 = (com->intr_enable
2428 & ~CD1400_SRER_TXMPTY)
2429 | CD1400_SRER_TXRDY);
2430 }
2431 COM_UNLOCK();
2432 restore_intr(intrsave);
2433 }
2434 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2435#ifdef CyDebug
2436 started = TRUE;
2437#endif
2438 com->obufs[1].l_tail
2439 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2440 sizeof com->obuf2);
2441 com->obufs[1].l_next = NULL;
2442 com->obufs[1].l_queued = TRUE;
2443 intrsave = save_intr();
2444 disable_intr();
2445 COM_LOCK();
2446 if (com->state & CS_BUSY) {
2447 qp = com->obufq.l_next;
2448 while ((next = qp->l_next) != NULL)
2449 qp = next;
2450 qp->l_next = &com->obufs[1];
2451 } else {
2452 com->obufq.l_head = com->obufs[1].l_head;

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

2457 | CS_ODEVREADY))
2458 cd_setreg(com, CD1400_SRER,
2459 com->intr_enable
2460 = (com->intr_enable
2461 & ~CD1400_SRER_TXMPTY)
2462 | CD1400_SRER_TXRDY);
2463 }
2464 COM_UNLOCK();
2465 restore_intr(intrsave);
2466 }
2467 tp->t_state |= TS_BUSY;
2468 }
2469#ifdef CyDebug
2470 if (started)
2471 ++com->start_real;
2472#endif
2473#if 0
2474 intrsave = save_intr();
2475 disable_intr();
2476 COM_LOCK();
2477 if (com->state >= (CS_BUSY | CS_TTGO))
2478 siointr1(com); /* fake interrupt to start output */
2479 COM_UNLOCK();
2480 restore_intr(intrsave);
2481#endif
2482 ttwwakeup(tp);
2483 splx(s);
2484}
2485
2486static void
2487comstop(tp, rw)
2488 struct tty *tp;
2489 int rw;
2490{
2491 struct com_s *com;
2492 bool_t wakeup_etc;
2493 int intrsave;
2494
2495 com = com_addr(DEV_TO_UNIT(tp->t_dev));
2496 wakeup_etc = FALSE;
2497 intrsave = save_intr();
2498 disable_intr();
2499 COM_LOCK();
2500 if (rw & FWRITE) {
2501 com->obufs[0].l_queued = FALSE;
2502 com->obufs[1].l_queued = FALSE;
2503 if (com->extra_state & CSE_ODONE) {
2504 com_events -= LOTS_OF_EVENTS;
2505 com->extra_state &= ~CSE_ODONE;
2506 if (com->etc != ETC_NONE) {

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

2515 com->state &= ~(CS_ODONE | CS_BUSY);
2516 }
2517 if (rw & FREAD) {
2518 /* XXX no way to reset only input fifo. */
2519 com_events -= (com->iptr - com->ibuf);
2520 com->iptr = com->ibuf;
2521 }
2522 COM_UNLOCK();
2523 restore_intr(intrsave);
2524 if (wakeup_etc)
2525 wakeup(&com->etc);
2526 if (rw & FWRITE && com->etc == ETC_NONE)
2527 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
2528 comstart(tp);
2529}
2530
2531static int
2532commctl(com, bits, how)
2533 struct com_s *com;
2534 int bits;
2535 int how;
2536{
2537 int mcr;
2538 int msr;
2539 int intrsave;
2540
2541 if (how == DMGET) {
2542 if (com->channel_control & CD1400_CCR_RCVEN)
2543 bits |= TIOCM_LE;
2544 mcr = com->mcr_image;
2545 if (mcr & com->mcr_dtr)
2546 bits |= TIOCM_DTR;
2547 if (mcr & com->mcr_rts)

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

2569 bits |= TIOCM_RI;
2570 return (bits);
2571 }
2572 mcr = 0;
2573 if (bits & TIOCM_DTR)
2574 mcr |= com->mcr_dtr;
2575 if (bits & TIOCM_RTS)
2576 mcr |= com->mcr_rts;
2577 intrsave = save_intr();
2578 disable_intr();
2579 COM_LOCK();
2580 switch (how) {
2581 case DMSET:
2582 com->mcr_image = mcr;
2583 cd_setreg(com, CD1400_MSVR1, mcr);
2584 cd_setreg(com, CD1400_MSVR2, mcr);
2585 break;
2586 case DMBIS:
2587 com->mcr_image = mcr = com->mcr_image | mcr;
2588 cd_setreg(com, CD1400_MSVR1, mcr);
2589 cd_setreg(com, CD1400_MSVR2, mcr);
2590 break;
2591 case DMBIC:
2592 com->mcr_image = mcr = com->mcr_image & ~mcr;
2593 cd_setreg(com, CD1400_MSVR1, mcr);
2594 cd_setreg(com, CD1400_MSVR2, mcr);
2595 break;
2596 }
2597 COM_UNLOCK();
2598 restore_intr(intrsave);
2599 return (0);
2600}
2601
2602static void
2603siosettimeout()
2604{
2605 struct com_s *com;
2606 bool_t someopen;

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

2652 /*
2653 * Recover from lost output interrupts.
2654 * Poll any lines that don't use interrupts.
2655 */
2656 for (unit = 0; unit < NSIO; ++unit) {
2657 com = com_addr(unit);
2658 if (com != NULL
2659 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2660 int intrsave;
2661
2662 intrsave = save_intr();
2663 disable_intr();
2664 COM_LOCK();
2665 siointr1(com);
2666 COM_UNLOCK();
2667 restore_intr(intrsave);
2668 }
2669 }
2670#endif
2671
2672 /*
2673 * Check for and log errors, but not too often.
2674 */
2675 if (--sio_timeouts_until_log > 0)
2676 return;
2677 sio_timeouts_until_log = hz / sio_timeout;
2678 for (unit = 0; unit < NSIO; ++unit) {
2679 int errnum;
2680
2681 com = com_addr(unit);
2682 if (com == NULL)
2683 continue;
2684 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2685 u_int delta;
2686 u_long total;
2687 int intrsave;
2688
2689 intrsave = save_intr();
2690 disable_intr();
2691 COM_LOCK();
2692 delta = com->delta_error_counts[errnum];
2693 com->delta_error_counts[errnum] = 0;
2694 COM_UNLOCK();
2695 restore_intr(intrsave);
2696 if (delta == 0)
2697 continue;
2698 total = com->error_counts[errnum] += delta;
2699 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n",
2700 unit, delta, error_desc[errnum],
2701 delta == 1 ? "" : "s", total);
2702 }
2703 }

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

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

--- 54 unchanged lines hidden ---