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 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, 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 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 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(); |
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 |
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(); |
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; |
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 */ |
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(); |
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 |
920 savecrit = critical_enter(); |
921 COM_LOCK(); 922 cd_setreg(com, CD1400_SRER, com->intr_enable = 0); 923 COM_UNLOCK(); |
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 |
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; |
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 */ |
1052 COM_UNLOCK(); |
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 } |
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 */ |
1084 COM_UNLOCK(); |
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); |
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; |
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 */ |
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(); |
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) { |
1815 savecrit = critical_enter(); |
1816 COM_LOCK(); |
1817 sioinput(com, &savecrit); |
1818 COM_UNLOCK(); |
1819 critical_exit(savecrit); |
1820 } 1821 if (com->state & CS_CHECKMSR) { 1822 u_char delta_modem_status; 1823 |
1824 savecrit = critical_enter(); |
1825 COM_LOCK(); |
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(); |
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) { |
1839 savecrit = critical_enter(); |
1840 COM_LOCK(); 1841 com_events -= LOTS_OF_EVENTS; 1842 com->extra_state &= ~CSE_ODONE; 1843 COM_UNLOCK(); |
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) { |
1856 savecrit = critical_enter(); |
1857 COM_LOCK(); 1858 com_events -= LOTS_OF_EVENTS; 1859 com->state &= ~CS_ODONE; 1860 COM_UNLOCK(); |
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; |
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 |
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(); |
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 */ |
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(); |
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; |
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 */ |
2291 savecrit = critical_enter(); |
2292 COM_LOCK(); 2293 if (com->iptr != com->ibuf) |
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(); |
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; |
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 |
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(); |
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; |
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(); |
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; |
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(); |
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 |
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(); |
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; |
2475 critical_t savecrit; |
2476 2477 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2478 wakeup_etc = FALSE; |
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(); |
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; |
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; |
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(); |
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)) { |
2640 critical_t savecrit; |
2641 |
2642 savecrit = critical_enter(); |
2643 COM_LOCK(); 2644 siointr1(com); 2645 COM_UNLOCK(); |
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; |
2666 critical_t savecrit; |
2667 |
2668 savecrit = critical_enter(); |
2669 COM_LOCK(); 2670 delta = com->delta_error_counts[errnum]; 2671 com->delta_error_counts[errnum] = 0; 2672 COM_UNLOCK(); |
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{ |
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 */ |
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(); |
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(); |
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; |
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; |
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); |
2888 if (eflags & PSL_I) |
2889 COM_UNLOCK(); |
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; |
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; |
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); |
2918 if (eflags & PSL_I) |
2919 COM_UNLOCK(); |
2920 critical_exit(savecrit); |
2921} 2922 2923#ifdef CyDebug 2924/* useful in ddb */ 2925void 2926cystatus(unit) 2927 int unit; 2928{ --- 54 unchanged lines hidden --- |