1 1.58 riastrad /* $NetBSD: dhu.c,v 1.58 2022/10/26 23:46:37 riastradh Exp $ */ 2 1.34 agc /* 3 1.36 wiz * Copyright (c) 2003, Hugh Graham. 4 1.34 agc * Copyright (c) 1992, 1993 5 1.34 agc * The Regents of the University of California. All rights reserved. 6 1.34 agc * 7 1.34 agc * This code is derived from software contributed to Berkeley by 8 1.34 agc * Ralph Campbell and Rick Macklem. 9 1.34 agc * 10 1.34 agc * Redistribution and use in source and binary forms, with or without 11 1.34 agc * modification, are permitted provided that the following conditions 12 1.34 agc * are met: 13 1.34 agc * 1. Redistributions of source code must retain the above copyright 14 1.34 agc * notice, this list of conditions and the following disclaimer. 15 1.34 agc * 2. Redistributions in binary form must reproduce the above copyright 16 1.34 agc * notice, this list of conditions and the following disclaimer in the 17 1.34 agc * documentation and/or other materials provided with the distribution. 18 1.34 agc * 3. Neither the name of the University nor the names of its contributors 19 1.34 agc * may be used to endorse or promote products derived from this software 20 1.34 agc * without specific prior written permission. 21 1.34 agc * 22 1.34 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.34 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.34 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.34 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.34 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.34 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.34 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.34 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.34 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.34 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.34 agc * SUCH DAMAGE. 33 1.34 agc */ 34 1.34 agc 35 1.1 ragge /* 36 1.1 ragge * Copyright (c) 1996 Ken C. Wellsch. All rights reserved. 37 1.1 ragge * 38 1.1 ragge * This code is derived from software contributed to Berkeley by 39 1.1 ragge * Ralph Campbell and Rick Macklem. 40 1.1 ragge * 41 1.1 ragge * Redistribution and use in source and binary forms, with or without 42 1.1 ragge * modification, are permitted provided that the following conditions 43 1.1 ragge * are met: 44 1.1 ragge * 1. Redistributions of source code must retain the above copyright 45 1.1 ragge * notice, this list of conditions and the following disclaimer. 46 1.1 ragge * 2. Redistributions in binary form must reproduce the above copyright 47 1.1 ragge * notice, this list of conditions and the following disclaimer in the 48 1.1 ragge * documentation and/or other materials provided with the distribution. 49 1.1 ragge * 3. All advertising materials mentioning features or use of this software 50 1.1 ragge * must display the following acknowledgement: 51 1.1 ragge * This product includes software developed by the University of 52 1.1 ragge * California, Berkeley and its contributors. 53 1.1 ragge * 4. Neither the name of the University nor the names of its contributors 54 1.1 ragge * may be used to endorse or promote products derived from this software 55 1.1 ragge * without specific prior written permission. 56 1.1 ragge * 57 1.1 ragge * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 1.1 ragge * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 1.1 ragge * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 1.1 ragge * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 1.1 ragge * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 1.1 ragge * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 1.1 ragge * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 1.1 ragge * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 1.1 ragge * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 1.1 ragge * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 1.1 ragge * SUCH DAMAGE. 68 1.1 ragge */ 69 1.25 lukem 70 1.25 lukem #include <sys/cdefs.h> 71 1.58 riastrad __KERNEL_RCSID(0, "$NetBSD: dhu.c,v 1.58 2022/10/26 23:46:37 riastradh Exp $"); 72 1.1 ragge 73 1.1 ragge #include <sys/param.h> 74 1.1 ragge #include <sys/systm.h> 75 1.1 ragge #include <sys/ioctl.h> 76 1.1 ragge #include <sys/tty.h> 77 1.1 ragge #include <sys/proc.h> 78 1.1 ragge #include <sys/buf.h> 79 1.1 ragge #include <sys/conf.h> 80 1.1 ragge #include <sys/file.h> 81 1.1 ragge #include <sys/uio.h> 82 1.1 ragge #include <sys/kernel.h> 83 1.1 ragge #include <sys/syslog.h> 84 1.1 ragge #include <sys/device.h> 85 1.44 yamt #include <sys/kauth.h> 86 1.1 ragge 87 1.48 ad #include <sys/bus.h> 88 1.13 ragge #include <machine/scb.h> 89 1.1 ragge 90 1.15 ragge #include <dev/qbus/ubavar.h> 91 1.15 ragge 92 1.15 ragge #include <dev/qbus/dhureg.h> 93 1.15 ragge 94 1.15 ragge #include "ioconf.h" 95 1.1 ragge 96 1.5 ragge /* A DHU-11 has 16 ports while a DHV-11 has only 8. We use 16 by default */ 97 1.1 ragge 98 1.38 simonb #define NDHULINE 16 99 1.2 ragge 100 1.5 ragge #define DHU_M2U(c) ((c)>>4) /* convert minor(dev) to unit # */ 101 1.5 ragge #define DHU_LINE(u) ((u)&0xF) /* extract line # from minor(dev) */ 102 1.2 ragge 103 1.52 matt struct dhu_softc { 104 1.52 matt device_t sc_dev; /* Device struct used by config */ 105 1.52 matt struct evcnt sc_rintrcnt; /* Interrupt statistics */ 106 1.52 matt struct evcnt sc_tintrcnt; /* Interrupt statistics */ 107 1.5 ragge int sc_type; /* controller type, DHU or DHV */ 108 1.33 ragge int sc_lines; /* number of lines */ 109 1.15 ragge bus_space_tag_t sc_iot; 110 1.15 ragge bus_space_handle_t sc_ioh; 111 1.16 ragge bus_dma_tag_t sc_dmat; 112 1.5 ragge struct { 113 1.5 ragge struct tty *dhu_tty; /* what we work on */ 114 1.16 ragge bus_dmamap_t dhu_dmah; 115 1.5 ragge int dhu_state; /* to manage TX output status */ 116 1.5 ragge short dhu_cc; /* character count on TX */ 117 1.5 ragge short dhu_modem; /* modem bits state */ 118 1.5 ragge } sc_dhu[NDHULINE]; 119 1.1 ragge }; 120 1.1 ragge 121 1.5 ragge #define IS_DHU 16 /* Unibus DHU-11 board linecount */ 122 1.5 ragge #define IS_DHV 8 /* Q-bus DHV-11 or DHQ-11 */ 123 1.2 ragge 124 1.2 ragge #define STATE_IDLE 000 /* no current output in progress */ 125 1.2 ragge #define STATE_DMA_RUNNING 001 /* DMA TX in progress */ 126 1.2 ragge #define STATE_DMA_STOPPED 002 /* DMA TX was aborted */ 127 1.2 ragge #define STATE_TX_ONE_CHAR 004 /* did a single char directly */ 128 1.2 ragge 129 1.2 ragge /* Flags used to monitor modem bits, make them understood outside driver */ 130 1.2 ragge 131 1.2 ragge #define DML_DTR TIOCM_DTR 132 1.2 ragge #define DML_RTS TIOCM_RTS 133 1.2 ragge #define DML_CTS TIOCM_CTS 134 1.2 ragge #define DML_DCD TIOCM_CD 135 1.2 ragge #define DML_RI TIOCM_RI 136 1.2 ragge #define DML_DSR TIOCM_DSR 137 1.2 ragge #define DML_BRK 0100000 /* no equivalent, we will mask */ 138 1.2 ragge 139 1.15 ragge #define DHU_READ_WORD(reg) \ 140 1.15 ragge bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg) 141 1.15 ragge #define DHU_WRITE_WORD(reg, val) \ 142 1.15 ragge bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val) 143 1.15 ragge #define DHU_READ_BYTE(reg) \ 144 1.15 ragge bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg) 145 1.15 ragge #define DHU_WRITE_BYTE(reg, val) \ 146 1.15 ragge bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val) 147 1.15 ragge 148 1.15 ragge 149 1.1 ragge /* On a stock DHV, channel pairs (0/1, 2/3, etc.) must use */ 150 1.1 ragge /* a baud rate from the same group. So limiting to B is likely */ 151 1.1 ragge /* best, although clone boards like the ABLE QHV allow all settings. */ 152 1.1 ragge 153 1.35 matt static const struct speedtab dhuspeedtab[] = { 154 1.1 ragge { 0, 0 }, /* Groups */ 155 1.1 ragge { 50, DHU_LPR_B50 }, /* A */ 156 1.1 ragge { 75, DHU_LPR_B75 }, /* B */ 157 1.1 ragge { 110, DHU_LPR_B110 }, /* A and B */ 158 1.1 ragge { 134, DHU_LPR_B134 }, /* A and B */ 159 1.1 ragge { 150, DHU_LPR_B150 }, /* B */ 160 1.1 ragge { 300, DHU_LPR_B300 }, /* A and B */ 161 1.1 ragge { 600, DHU_LPR_B600 }, /* A and B */ 162 1.1 ragge { 1200, DHU_LPR_B1200 }, /* A and B */ 163 1.1 ragge { 1800, DHU_LPR_B1800 }, /* B */ 164 1.1 ragge { 2000, DHU_LPR_B2000 }, /* B */ 165 1.1 ragge { 2400, DHU_LPR_B2400 }, /* A and B */ 166 1.1 ragge { 4800, DHU_LPR_B4800 }, /* A and B */ 167 1.1 ragge { 7200, DHU_LPR_B7200 }, /* A */ 168 1.1 ragge { 9600, DHU_LPR_B9600 }, /* A and B */ 169 1.1 ragge { 19200, DHU_LPR_B19200 }, /* B */ 170 1.1 ragge { 38400, DHU_LPR_B38400 }, /* A */ 171 1.1 ragge { -1, -1 } 172 1.1 ragge }; 173 1.1 ragge 174 1.52 matt static int dhu_match(device_t, cfdata_t, void *); 175 1.52 matt static void dhu_attach(device_t, device_t, void *); 176 1.37 perry static void dhurint(void *); 177 1.37 perry static void dhuxint(void *); 178 1.37 perry static void dhustart(struct tty *); 179 1.37 perry static int dhuparam(struct tty *, struct termios *); 180 1.37 perry static int dhuiflow(struct tty *, int); 181 1.37 perry static unsigned dhumctl(struct dhu_softc *,int, int, int); 182 1.24 ragge 183 1.52 matt CFATTACH_DECL_NEW(dhu, sizeof(struct dhu_softc), 184 1.31 thorpej dhu_match, dhu_attach, NULL, NULL); 185 1.10 thorpej 186 1.52 matt static dev_type_open(dhuopen); 187 1.52 matt static dev_type_close(dhuclose); 188 1.52 matt static dev_type_read(dhuread); 189 1.52 matt static dev_type_write(dhuwrite); 190 1.52 matt static dev_type_ioctl(dhuioctl); 191 1.52 matt static dev_type_stop(dhustop); 192 1.52 matt static dev_type_tty(dhutty); 193 1.52 matt static dev_type_poll(dhupoll); 194 1.27 gehenna 195 1.27 gehenna const struct cdevsw dhu_cdevsw = { 196 1.52 matt .d_open = dhuopen, 197 1.52 matt .d_close = dhuclose, 198 1.52 matt .d_read = dhuread, 199 1.52 matt .d_write = dhuwrite, 200 1.52 matt .d_ioctl = dhuioctl, 201 1.52 matt .d_stop = dhustop, 202 1.52 matt .d_tty = dhutty, 203 1.52 matt .d_poll = dhupoll, 204 1.52 matt .d_mmap = nommap, 205 1.52 matt .d_kqfilter = ttykqfilter, 206 1.57 dholland .d_discard = nodiscard, 207 1.52 matt .d_flag = D_TTY 208 1.27 gehenna }; 209 1.27 gehenna 210 1.1 ragge /* Autoconfig handles: setup the controller to interrupt, */ 211 1.1 ragge /* then complete the housecleaning for full operation */ 212 1.1 ragge 213 1.1 ragge static int 214 1.52 matt dhu_match(device_t parent, cfdata_t cf, void *aux) 215 1.1 ragge { 216 1.1 ragge struct uba_attach_args *ua = aux; 217 1.18 augustss int n; 218 1.1 ragge 219 1.2 ragge /* Reset controller to initialize, enable TX/RX interrupts */ 220 1.1 ragge /* to catch floating vector info elsewhere when completed */ 221 1.1 ragge 222 1.15 ragge bus_space_write_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR, 223 1.15 ragge DHU_CSR_MASTER_RESET | DHU_CSR_RXIE | DHU_CSR_TXIE); 224 1.1 ragge 225 1.1 ragge /* Now wait up to 3 seconds for self-test to complete. */ 226 1.1 ragge 227 1.1 ragge for (n = 0; n < 300; n++) { 228 1.1 ragge DELAY(10000); 229 1.15 ragge if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR) & 230 1.15 ragge DHU_CSR_MASTER_RESET) == 0) 231 1.1 ragge break; 232 1.1 ragge } 233 1.1 ragge 234 1.1 ragge /* If the RESET did not clear after 3 seconds, */ 235 1.1 ragge /* the controller must be broken. */ 236 1.1 ragge 237 1.2 ragge if (n >= 300) 238 1.1 ragge return 0; 239 1.1 ragge 240 1.1 ragge /* Check whether diagnostic run has signalled a failure. */ 241 1.1 ragge 242 1.15 ragge if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR) & 243 1.15 ragge DHU_CSR_DIAG_FAIL) != 0) 244 1.1 ragge return 0; 245 1.1 ragge 246 1.38 simonb return 1; 247 1.1 ragge } 248 1.1 ragge 249 1.1 ragge static void 250 1.52 matt dhu_attach(device_t parent, device_t self, void *aux) 251 1.1 ragge { 252 1.42 thorpej struct dhu_softc *sc = device_private(self); 253 1.18 augustss struct uba_attach_args *ua = aux; 254 1.18 augustss unsigned c; 255 1.18 augustss int n, i; 256 1.1 ragge 257 1.52 matt sc->sc_dev = self; 258 1.15 ragge sc->sc_iot = ua->ua_iot; 259 1.15 ragge sc->sc_ioh = ua->ua_ioh; 260 1.16 ragge sc->sc_dmat = ua->ua_dmat; 261 1.1 ragge /* Process the 8 bytes of diagnostic info put into */ 262 1.1 ragge /* the FIFO following the master reset operation. */ 263 1.1 ragge 264 1.52 matt aprint_normal("\n"); 265 1.1 ragge for (n = 0; n < 8; n++) { 266 1.15 ragge c = DHU_READ_WORD(DHU_UBA_RBUF); 267 1.1 ragge 268 1.2 ragge if ((c&DHU_DIAG_CODE) == DHU_DIAG_CODE) { 269 1.2 ragge if ((c&0200) == 0000) 270 1.52 matt aprint_error_dev(self, "rom(%d) version %d\n", 271 1.1 ragge ((c>>1)&01), ((c>>2)&037)); 272 1.2 ragge else if (((c>>2)&07) != 0) 273 1.52 matt aprint_error_dev(self, "diag-error(proc%d)=%x\n", 274 1.1 ragge ((c>>1)&01), ((c>>2)&07)); 275 1.1 ragge } 276 1.1 ragge } 277 1.1 ragge 278 1.15 ragge c = DHU_READ_WORD(DHU_UBA_STAT); 279 1.2 ragge 280 1.5 ragge sc->sc_type = (c & DHU_STAT_DHU)? IS_DHU: IS_DHV; 281 1.1 ragge 282 1.33 ragge sc->sc_lines = 8; /* default */ 283 1.33 ragge if (sc->sc_type == IS_DHU && (c & DHU_STAT_MDL)) 284 1.33 ragge sc->sc_lines = 16; 285 1.33 ragge 286 1.52 matt aprint_normal_dev(self, "DH%s-11\n", 287 1.33 ragge sc->sc_type == IS_DHU ? "U" : "V"); 288 1.33 ragge 289 1.33 ragge for (i = 0; i < sc->sc_lines; i++) { 290 1.16 ragge struct tty *tp; 291 1.56 rmind 292 1.56 rmind tp = sc->sc_dhu[i].dhu_tty = tty_alloc(); 293 1.16 ragge sc->sc_dhu[i].dhu_state = STATE_IDLE; 294 1.38 simonb bus_dmamap_create(sc->sc_dmat, tp->t_outq.c_cn, 1, 295 1.16 ragge tp->t_outq.c_cn, 0, BUS_DMA_ALLOCNOW|BUS_DMA_NOWAIT, 296 1.16 ragge &sc->sc_dhu[i].dhu_dmah); 297 1.16 ragge bus_dmamap_load(sc->sc_dmat, sc->sc_dhu[i].dhu_dmah, 298 1.16 ragge tp->t_outq.c_cs, tp->t_outq.c_cn, 0, BUS_DMA_NOWAIT); 299 1.38 simonb 300 1.16 ragge } 301 1.16 ragge 302 1.17 matt /* Now establish RX & TX interrupt handlers */ 303 1.17 matt 304 1.19 matt uba_intr_establish(ua->ua_icookie, ua->ua_cvec, 305 1.19 matt dhurint, sc, &sc->sc_rintrcnt); 306 1.19 matt uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 4, 307 1.19 matt dhuxint, sc, &sc->sc_tintrcnt); 308 1.20 matt evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, 309 1.52 matt device_xname(sc->sc_dev), "rintr"); 310 1.20 matt evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, 311 1.52 matt device_xname(sc->sc_dev), "tintr"); 312 1.1 ragge } 313 1.1 ragge 314 1.2 ragge /* Receiver Interrupt */ 315 1.2 ragge 316 1.1 ragge static void 317 1.52 matt dhurint(void *arg) 318 1.1 ragge { 319 1.52 matt struct dhu_softc *sc = arg; 320 1.18 augustss struct tty *tp; 321 1.18 augustss int cc, line; 322 1.18 augustss unsigned c, delta; 323 1.1 ragge int overrun = 0; 324 1.2 ragge 325 1.15 ragge while ((c = DHU_READ_WORD(DHU_UBA_RBUF)) & DHU_RBUF_DATA_VALID) { 326 1.1 ragge 327 1.1 ragge /* Ignore diagnostic FIFO entries. */ 328 1.1 ragge 329 1.5 ragge if ((c & DHU_DIAG_CODE) == DHU_DIAG_CODE) 330 1.1 ragge continue; 331 1.1 ragge 332 1.5 ragge cc = c & 0xFF; 333 1.5 ragge line = DHU_LINE(c>>8); 334 1.5 ragge tp = sc->sc_dhu[line].dhu_tty; 335 1.1 ragge 336 1.1 ragge /* LINK.TYPE is set so we get modem control FIFO entries */ 337 1.1 ragge 338 1.1 ragge if ((c & DHU_DIAG_CODE) == DHU_MODEM_CODE) { 339 1.2 ragge c = (c << 8); 340 1.1 ragge /* Do MDMBUF flow control, wakeup sleeping opens */ 341 1.1 ragge if (c & DHU_STAT_DCD) { 342 1.1 ragge if (!(tp->t_state & TS_CARR_ON)) 343 1.21 eeh (void)(*tp->t_linesw->l_modem)(tp, 1); 344 1.1 ragge } 345 1.1 ragge else if ((tp->t_state & TS_CARR_ON) && 346 1.21 eeh (*tp->t_linesw->l_modem)(tp, 0) == 0) 347 1.5 ragge (void) dhumctl(sc, line, 0, DMSET); 348 1.2 ragge 349 1.2 ragge /* Do CRTSCTS flow control */ 350 1.5 ragge delta = c ^ sc->sc_dhu[line].dhu_modem; 351 1.5 ragge sc->sc_dhu[line].dhu_modem = c; 352 1.2 ragge if ((delta & DHU_STAT_CTS) && 353 1.2 ragge (tp->t_state & TS_ISOPEN) && 354 1.2 ragge (tp->t_cflag & CRTSCTS)) { 355 1.2 ragge if (c & DHU_STAT_CTS) { 356 1.2 ragge tp->t_state &= ~TS_TTSTOP; 357 1.5 ragge ttstart(tp); 358 1.2 ragge } else { 359 1.2 ragge tp->t_state |= TS_TTSTOP; 360 1.5 ragge dhustop(tp, 0); 361 1.2 ragge } 362 1.2 ragge } 363 1.2 ragge continue; 364 1.1 ragge } 365 1.1 ragge 366 1.5 ragge if (!(tp->t_state & TS_ISOPEN)) { 367 1.54 ad cv_broadcast(&tp->t_rawcv); 368 1.5 ragge continue; 369 1.5 ragge } 370 1.5 ragge 371 1.1 ragge if ((c & DHU_RBUF_OVERRUN_ERR) && overrun == 0) { 372 1.5 ragge log(LOG_WARNING, "%s: silo overflow, line %d\n", 373 1.52 matt device_xname(sc->sc_dev), line); 374 1.1 ragge overrun = 1; 375 1.1 ragge } 376 1.1 ragge /* A BREAK key will appear as a NULL with a framing error */ 377 1.1 ragge if (c & DHU_RBUF_FRAMING_ERR) 378 1.1 ragge cc |= TTY_FE; 379 1.1 ragge if (c & DHU_RBUF_PARITY_ERR) 380 1.1 ragge cc |= TTY_PE; 381 1.1 ragge 382 1.21 eeh (*tp->t_linesw->l_rint)(cc, tp); 383 1.1 ragge } 384 1.1 ragge } 385 1.1 ragge 386 1.1 ragge /* Transmitter Interrupt */ 387 1.1 ragge 388 1.1 ragge static void 389 1.52 matt dhuxint(void *arg) 390 1.1 ragge { 391 1.52 matt struct dhu_softc *sc = arg; 392 1.18 augustss struct tty *tp; 393 1.33 ragge int line, i; 394 1.2 ragge 395 1.33 ragge while ((i = DHU_READ_BYTE(DHU_UBA_CSR_HI)) & (DHU_CSR_TX_ACTION >> 8)) { 396 1.1 ragge 397 1.33 ragge line = DHU_LINE(i); 398 1.33 ragge tp = sc->sc_dhu[line].dhu_tty; 399 1.2 ragge 400 1.33 ragge if (i & (DHU_CSR_TX_DMA_ERROR >> 8)) 401 1.33 ragge printf("%s: DMA ERROR on line: %d\n", 402 1.52 matt device_xname(sc->sc_dev), line); 403 1.33 ragge if (i & (DHU_CSR_DIAG_FAIL >> 8)) 404 1.33 ragge printf("%s: DIAG FAIL on line: %d\n", 405 1.52 matt device_xname(sc->sc_dev), line); 406 1.33 ragge 407 1.33 ragge tp->t_state &= ~TS_BUSY; 408 1.33 ragge if (tp->t_state & TS_FLUSH) 409 1.33 ragge tp->t_state &= ~TS_FLUSH; 410 1.33 ragge else { 411 1.33 ragge if (sc->sc_dhu[line].dhu_state == STATE_DMA_STOPPED) 412 1.38 simonb sc->sc_dhu[line].dhu_cc -= 413 1.33 ragge DHU_READ_WORD(DHU_UBA_TBUFCNT); 414 1.33 ragge ndflush(&tp->t_outq, sc->sc_dhu[line].dhu_cc); 415 1.33 ragge sc->sc_dhu[line].dhu_cc = 0; 416 1.33 ragge } 417 1.1 ragge 418 1.33 ragge sc->sc_dhu[line].dhu_state = STATE_IDLE; 419 1.2 ragge 420 1.33 ragge (*tp->t_linesw->l_start)(tp); 421 1.33 ragge } 422 1.1 ragge } 423 1.1 ragge 424 1.1 ragge int 425 1.52 matt dhuopen(dev_t dev, int flag, int mode, struct lwp *l) 426 1.1 ragge { 427 1.18 augustss struct tty *tp; 428 1.18 augustss int unit, line; 429 1.5 ragge struct dhu_softc *sc; 430 1.49 ad int error = 0; 431 1.1 ragge 432 1.5 ragge unit = DHU_M2U(minor(dev)); 433 1.5 ragge line = DHU_LINE(minor(dev)); 434 1.5 ragge 435 1.55 drochner sc = device_lookup_private(&dhu_cd, unit); 436 1.55 drochner if (!sc) 437 1.1 ragge return (ENXIO); 438 1.5 ragge 439 1.33 ragge if (line >= sc->sc_lines) 440 1.5 ragge return ENXIO; 441 1.5 ragge 442 1.58 riastrad tp = sc->sc_dhu[line].dhu_tty; 443 1.58 riastrad ttylock(tp); 444 1.33 ragge if (sc->sc_type == IS_DHU) { 445 1.49 ad /* CSR 3:0 must be 0 */ 446 1.33 ragge DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE); 447 1.49 ad /* RX int delay 10ms */ 448 1.33 ragge DHU_WRITE_BYTE(DHU_UBA_RXTIME, 10); 449 1.33 ragge } 450 1.16 ragge DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); 451 1.16 ragge sc->sc_dhu[line].dhu_modem = DHU_READ_WORD(DHU_UBA_STAT); 452 1.16 ragge 453 1.51 ad if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 454 1.51 ad return (EBUSY); 455 1.51 ad 456 1.2 ragge tp->t_oproc = dhustart; 457 1.2 ragge tp->t_param = dhuparam; 458 1.2 ragge tp->t_hwiflow = dhuiflow; 459 1.1 ragge tp->t_dev = dev; 460 1.46 elad 461 1.1 ragge if ((tp->t_state & TS_ISOPEN) == 0) { 462 1.1 ragge ttychars(tp); 463 1.2 ragge if (tp->t_ispeed == 0) { 464 1.2 ragge tp->t_iflag = TTYDEF_IFLAG; 465 1.2 ragge tp->t_oflag = TTYDEF_OFLAG; 466 1.2 ragge tp->t_cflag = TTYDEF_CFLAG; 467 1.2 ragge tp->t_lflag = TTYDEF_LFLAG; 468 1.2 ragge tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 469 1.2 ragge } 470 1.1 ragge (void) dhuparam(tp, &tp->t_termios); 471 1.1 ragge ttsetwater(tp); 472 1.46 elad } 473 1.1 ragge /* Use DMBIS and *not* DMSET or else we clobber incoming bits */ 474 1.5 ragge if (dhumctl(sc, line, DML_DTR|DML_RTS, DMBIS) & DML_DCD) 475 1.1 ragge tp->t_state |= TS_CARR_ON; 476 1.1 ragge while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 477 1.38 simonb !(tp->t_state & TS_CARR_ON)) { 478 1.12 ragge tp->t_wopen++; 479 1.53 ad error = ttysleep(tp, &tp->t_rawcv, true, 0); 480 1.12 ragge tp->t_wopen--; 481 1.1 ragge if (error) 482 1.1 ragge break; 483 1.1 ragge } 484 1.58 riastrad ttyunlock(tp); 485 1.1 ragge if (error) 486 1.1 ragge return (error); 487 1.21 eeh return ((*tp->t_linesw->l_open)(dev, tp)); 488 1.1 ragge } 489 1.1 ragge 490 1.1 ragge /*ARGSUSED*/ 491 1.1 ragge int 492 1.52 matt dhuclose(dev_t dev, int flag, int mode, struct lwp *l) 493 1.1 ragge { 494 1.52 matt const int unit = DHU_M2U(minor(dev)); 495 1.52 matt const int line = DHU_LINE(minor(dev)); 496 1.52 matt struct dhu_softc *sc = device_lookup_private(&dhu_cd, unit); 497 1.52 matt struct tty *tp = sc->sc_dhu[line].dhu_tty; 498 1.1 ragge 499 1.21 eeh (*tp->t_linesw->l_close)(tp, flag); 500 1.1 ragge 501 1.1 ragge /* Make sure a BREAK state is not left enabled. */ 502 1.1 ragge 503 1.5 ragge (void) dhumctl(sc, line, DML_BRK, DMBIC); 504 1.1 ragge 505 1.1 ragge /* Do a hangup if so required. */ 506 1.1 ragge 507 1.52 matt if ((tp->t_cflag & HUPCL) || tp->t_wopen || !(tp->t_state & TS_ISOPEN)) 508 1.5 ragge (void) dhumctl(sc, line, 0, DMSET); 509 1.1 ragge 510 1.1 ragge return (ttyclose(tp)); 511 1.1 ragge } 512 1.1 ragge 513 1.1 ragge int 514 1.52 matt dhuread(dev_t dev, struct uio *uio, int flag) 515 1.1 ragge { 516 1.52 matt struct dhu_softc *sc = device_lookup_private(&dhu_cd, DHU_M2U(minor(dev))); 517 1.52 matt struct tty *tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty; 518 1.5 ragge 519 1.21 eeh return ((*tp->t_linesw->l_read)(tp, uio, flag)); 520 1.1 ragge } 521 1.1 ragge 522 1.1 ragge int 523 1.52 matt dhuwrite(dev_t dev, struct uio *uio, int flag) 524 1.1 ragge { 525 1.52 matt struct dhu_softc *sc = device_lookup_private(&dhu_cd, DHU_M2U(minor(dev))); 526 1.52 matt struct tty *tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty; 527 1.5 ragge 528 1.21 eeh return ((*tp->t_linesw->l_write)(tp, uio, flag)); 529 1.23 scw } 530 1.23 scw 531 1.23 scw int 532 1.52 matt dhupoll(dev_t dev, int events, struct lwp *l) 533 1.23 scw { 534 1.52 matt struct dhu_softc *sc = device_lookup_private(&dhu_cd, DHU_M2U(minor(dev))); 535 1.52 matt struct tty *tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty; 536 1.23 scw 537 1.40 christos return ((*tp->t_linesw->l_poll)(tp, events, l)); 538 1.1 ragge } 539 1.1 ragge 540 1.1 ragge /*ARGSUSED*/ 541 1.1 ragge int 542 1.52 matt dhuioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 543 1.1 ragge { 544 1.52 matt const int unit = DHU_M2U(minor(dev)); 545 1.52 matt const int line = DHU_LINE(minor(dev)); 546 1.52 matt struct dhu_softc *sc = device_lookup_private(&dhu_cd, unit); 547 1.52 matt struct tty *tp = sc->sc_dhu[line].dhu_tty; 548 1.1 ragge int error; 549 1.1 ragge 550 1.40 christos error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 551 1.26 atatat if (error != EPASSTHROUGH) 552 1.1 ragge return (error); 553 1.26 atatat 554 1.40 christos error = ttioctl(tp, cmd, data, flag, l); 555 1.26 atatat if (error != EPASSTHROUGH) 556 1.1 ragge return (error); 557 1.1 ragge 558 1.1 ragge switch (cmd) { 559 1.1 ragge 560 1.1 ragge case TIOCSBRK: 561 1.5 ragge (void) dhumctl(sc, line, DML_BRK, DMBIS); 562 1.1 ragge break; 563 1.1 ragge 564 1.1 ragge case TIOCCBRK: 565 1.5 ragge (void) dhumctl(sc, line, DML_BRK, DMBIC); 566 1.1 ragge break; 567 1.1 ragge 568 1.1 ragge case TIOCSDTR: 569 1.5 ragge (void) dhumctl(sc, line, DML_DTR|DML_RTS, DMBIS); 570 1.1 ragge break; 571 1.1 ragge 572 1.1 ragge case TIOCCDTR: 573 1.5 ragge (void) dhumctl(sc, line, DML_DTR|DML_RTS, DMBIC); 574 1.1 ragge break; 575 1.1 ragge 576 1.1 ragge case TIOCMSET: 577 1.5 ragge (void) dhumctl(sc, line, *(int *)data, DMSET); 578 1.1 ragge break; 579 1.1 ragge 580 1.1 ragge case TIOCMBIS: 581 1.5 ragge (void) dhumctl(sc, line, *(int *)data, DMBIS); 582 1.1 ragge break; 583 1.1 ragge 584 1.1 ragge case TIOCMBIC: 585 1.5 ragge (void) dhumctl(sc, line, *(int *)data, DMBIC); 586 1.1 ragge break; 587 1.1 ragge 588 1.1 ragge case TIOCMGET: 589 1.5 ragge *(int *)data = (dhumctl(sc, line, 0, DMGET) & ~DML_BRK); 590 1.1 ragge break; 591 1.1 ragge 592 1.1 ragge default: 593 1.26 atatat return (EPASSTHROUGH); 594 1.1 ragge } 595 1.1 ragge return (0); 596 1.1 ragge } 597 1.1 ragge 598 1.2 ragge struct tty * 599 1.52 matt dhutty(dev_t dev) 600 1.2 ragge { 601 1.52 matt struct dhu_softc *sc = device_lookup_private(&dhu_cd, DHU_M2U(minor(dev))); 602 1.52 matt 603 1.52 matt return sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty; 604 1.2 ragge } 605 1.2 ragge 606 1.1 ragge /*ARGSUSED*/ 607 1.6 mycroft void 608 1.52 matt dhustop(struct tty *tp, int flag) 609 1.1 ragge { 610 1.1 ragge int s; 611 1.1 ragge 612 1.1 ragge s = spltty(); 613 1.1 ragge 614 1.5 ragge if (tp->t_state & TS_BUSY) { 615 1.52 matt const int unit = DHU_M2U(minor(tp->t_dev)); 616 1.52 matt const int line = DHU_LINE(minor(tp->t_dev)); 617 1.52 matt struct dhu_softc *sc = device_lookup_private(&dhu_cd, unit); 618 1.5 ragge 619 1.5 ragge if (sc->sc_dhu[line].dhu_state == STATE_DMA_RUNNING) { 620 1.5 ragge 621 1.5 ragge sc->sc_dhu[line].dhu_state = STATE_DMA_STOPPED; 622 1.2 ragge 623 1.15 ragge DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); 624 1.38 simonb DHU_WRITE_WORD(DHU_UBA_LNCTRL, 625 1.38 simonb DHU_READ_WORD(DHU_UBA_LNCTRL) | 626 1.15 ragge DHU_LNCTRL_DMA_ABORT); 627 1.2 ragge } 628 1.1 ragge 629 1.1 ragge if (!(tp->t_state & TS_TTSTOP)) 630 1.1 ragge tp->t_state |= TS_FLUSH; 631 1.1 ragge } 632 1.1 ragge (void) splx(s); 633 1.1 ragge } 634 1.1 ragge 635 1.1 ragge static void 636 1.52 matt dhustart(struct tty *tp) 637 1.1 ragge { 638 1.18 augustss struct dhu_softc *sc; 639 1.18 augustss int line, cc; 640 1.18 augustss int addr; 641 1.1 ragge int s; 642 1.1 ragge 643 1.1 ragge s = spltty(); 644 1.1 ragge if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 645 1.1 ragge goto out; 646 1.50 ad if (!ttypull(tp)) 647 1.1 ragge goto out; 648 1.1 ragge cc = ndqb(&tp->t_outq, 0); 649 1.38 simonb if (cc == 0) 650 1.1 ragge goto out; 651 1.1 ragge 652 1.1 ragge tp->t_state |= TS_BUSY; 653 1.1 ragge 654 1.52 matt sc = device_lookup_private(&dhu_cd,DHU_M2U(minor(tp->t_dev))); 655 1.5 ragge 656 1.5 ragge line = DHU_LINE(minor(tp->t_dev)); 657 1.1 ragge 658 1.15 ragge DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); 659 1.5 ragge 660 1.5 ragge sc->sc_dhu[line].dhu_cc = cc; 661 1.2 ragge 662 1.33 ragge if (cc == 1 && sc->sc_type == IS_DHV) { 663 1.2 ragge 664 1.5 ragge sc->sc_dhu[line].dhu_state = STATE_TX_ONE_CHAR; 665 1.38 simonb 666 1.38 simonb DHU_WRITE_WORD(DHU_UBA_TXCHAR, 667 1.15 ragge DHU_TXCHAR_DATA_VALID | *tp->t_outq.c_cf); 668 1.2 ragge 669 1.5 ragge } else { 670 1.5 ragge 671 1.5 ragge sc->sc_dhu[line].dhu_state = STATE_DMA_RUNNING; 672 1.5 ragge 673 1.16 ragge addr = sc->sc_dhu[line].dhu_dmah->dm_segs[0].ds_addr + 674 1.2 ragge (tp->t_outq.c_cf - tp->t_outq.c_cs); 675 1.2 ragge 676 1.15 ragge DHU_WRITE_WORD(DHU_UBA_TBUFCNT, cc); 677 1.15 ragge DHU_WRITE_WORD(DHU_UBA_TBUFAD1, addr & 0xFFFF); 678 1.15 ragge DHU_WRITE_WORD(DHU_UBA_TBUFAD2, ((addr>>16) & 0x3F) | 679 1.15 ragge DHU_TBUFAD2_TX_ENABLE); 680 1.38 simonb DHU_WRITE_WORD(DHU_UBA_LNCTRL, 681 1.15 ragge DHU_READ_WORD(DHU_UBA_LNCTRL) & ~DHU_LNCTRL_DMA_ABORT); 682 1.15 ragge DHU_WRITE_WORD(DHU_UBA_TBUFAD2, 683 1.15 ragge DHU_READ_WORD(DHU_UBA_TBUFAD2) | DHU_TBUFAD2_DMA_START); 684 1.2 ragge } 685 1.1 ragge out: 686 1.1 ragge (void) splx(s); 687 1.1 ragge return; 688 1.1 ragge } 689 1.1 ragge 690 1.1 ragge static int 691 1.52 matt dhuparam(struct tty *tp, struct termios *t) 692 1.1 ragge { 693 1.18 augustss int cflag = t->c_cflag; 694 1.1 ragge int ispeed = ttspeedtab(t->c_ispeed, dhuspeedtab); 695 1.1 ragge int ospeed = ttspeedtab(t->c_ospeed, dhuspeedtab); 696 1.52 matt unsigned int lpr; 697 1.52 matt unsigned int lnctrl; 698 1.52 matt const int unit = DHU_M2U(minor(tp->t_dev)); 699 1.52 matt const int line = DHU_LINE(minor(tp->t_dev)); 700 1.52 matt struct dhu_softc * const sc = device_lookup_private(&dhu_cd, unit); 701 1.1 ragge int s; 702 1.1 ragge 703 1.5 ragge 704 1.1 ragge /* check requested parameters */ 705 1.38 simonb if (ospeed < 0 || ispeed < 0) 706 1.38 simonb return (EINVAL); 707 1.1 ragge 708 1.38 simonb tp->t_ispeed = t->c_ispeed; 709 1.38 simonb tp->t_ospeed = t->c_ospeed; 710 1.38 simonb tp->t_cflag = cflag; 711 1.1 ragge 712 1.1 ragge if (ospeed == 0) { 713 1.5 ragge (void) dhumctl(sc, line, 0, DMSET); /* hang up line */ 714 1.1 ragge return (0); 715 1.1 ragge } 716 1.1 ragge 717 1.1 ragge s = spltty(); 718 1.15 ragge DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); 719 1.1 ragge 720 1.1 ragge lpr = ((ispeed&017)<<8) | ((ospeed&017)<<12) ; 721 1.1 ragge 722 1.5 ragge switch (cflag & CSIZE) { 723 1.5 ragge 724 1.5 ragge case CS5: 725 1.1 ragge lpr |= DHU_LPR_5_BIT_CHAR; 726 1.1 ragge break; 727 1.5 ragge 728 1.5 ragge case CS6: 729 1.1 ragge lpr |= DHU_LPR_6_BIT_CHAR; 730 1.1 ragge break; 731 1.5 ragge 732 1.5 ragge case CS7: 733 1.1 ragge lpr |= DHU_LPR_7_BIT_CHAR; 734 1.1 ragge break; 735 1.5 ragge 736 1.5 ragge default: 737 1.1 ragge lpr |= DHU_LPR_8_BIT_CHAR; 738 1.1 ragge break; 739 1.1 ragge } 740 1.5 ragge 741 1.1 ragge if (cflag & PARENB) 742 1.1 ragge lpr |= DHU_LPR_PARENB; 743 1.1 ragge if (!(cflag & PARODD)) 744 1.1 ragge lpr |= DHU_LPR_EPAR; 745 1.1 ragge if (cflag & CSTOPB) 746 1.1 ragge lpr |= DHU_LPR_2_STOP; 747 1.1 ragge 748 1.15 ragge DHU_WRITE_WORD(DHU_UBA_LPR, lpr); 749 1.1 ragge 750 1.38 simonb DHU_WRITE_WORD(DHU_UBA_TBUFAD2, 751 1.15 ragge DHU_READ_WORD(DHU_UBA_TBUFAD2) | DHU_TBUFAD2_TX_ENABLE); 752 1.2 ragge 753 1.15 ragge lnctrl = DHU_READ_WORD(DHU_UBA_LNCTRL); 754 1.2 ragge 755 1.1 ragge /* Setting LINK.TYPE enables modem signal change interrupts. */ 756 1.1 ragge 757 1.2 ragge lnctrl |= (DHU_LNCTRL_RX_ENABLE | DHU_LNCTRL_LINK_TYPE); 758 1.2 ragge 759 1.5 ragge /* Enable the auto XON/XOFF feature on the controller */ 760 1.5 ragge 761 1.2 ragge if (t->c_iflag & IXON) 762 1.2 ragge lnctrl |= DHU_LNCTRL_OAUTO; 763 1.2 ragge else 764 1.2 ragge lnctrl &= ~DHU_LNCTRL_OAUTO; 765 1.2 ragge 766 1.2 ragge if (t->c_iflag & IXOFF) 767 1.2 ragge lnctrl |= DHU_LNCTRL_IAUTO; 768 1.2 ragge else 769 1.2 ragge lnctrl &= ~DHU_LNCTRL_IAUTO; 770 1.2 ragge 771 1.15 ragge DHU_WRITE_WORD(DHU_UBA_LNCTRL, lnctrl); 772 1.2 ragge 773 1.1 ragge (void) splx(s); 774 1.1 ragge return (0); 775 1.1 ragge } 776 1.1 ragge 777 1.1 ragge static int 778 1.52 matt dhuiflow(struct tty *tp, int flag) 779 1.2 ragge { 780 1.2 ragge 781 1.2 ragge if (tp->t_cflag & CRTSCTS) { 782 1.52 matt const int unit = DHU_M2U(minor(tp->t_dev)); 783 1.52 matt const int line = DHU_LINE(minor(tp->t_dev)); 784 1.52 matt struct dhu_softc * const sc = device_lookup_private(&dhu_cd, unit); 785 1.5 ragge (void) dhumctl(sc, line, DML_RTS, ((flag)? DMBIC: DMBIS)); 786 1.2 ragge return (1); 787 1.2 ragge } 788 1.2 ragge return (0); 789 1.2 ragge } 790 1.2 ragge 791 1.52 matt static unsigned int 792 1.52 matt dhumctl(struct dhu_softc *sc, int line, int bits, int how) 793 1.1 ragge { 794 1.18 augustss unsigned status; 795 1.18 augustss unsigned lnctrl; 796 1.18 augustss unsigned mbits; 797 1.1 ragge int s; 798 1.1 ragge 799 1.1 ragge s = spltty(); 800 1.1 ragge 801 1.15 ragge DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line); 802 1.1 ragge 803 1.1 ragge mbits = 0; 804 1.1 ragge 805 1.1 ragge /* external signals as seen from the port */ 806 1.1 ragge 807 1.15 ragge status = DHU_READ_WORD(DHU_UBA_STAT); 808 1.1 ragge 809 1.2 ragge if (status & DHU_STAT_CTS) 810 1.1 ragge mbits |= DML_CTS; 811 1.1 ragge 812 1.2 ragge if (status & DHU_STAT_DCD) 813 1.1 ragge mbits |= DML_DCD; 814 1.1 ragge 815 1.2 ragge if (status & DHU_STAT_DSR) 816 1.1 ragge mbits |= DML_DSR; 817 1.1 ragge 818 1.2 ragge if (status & DHU_STAT_RI) 819 1.1 ragge mbits |= DML_RI; 820 1.1 ragge 821 1.1 ragge /* internal signals/state delivered to port */ 822 1.1 ragge 823 1.15 ragge lnctrl = DHU_READ_WORD(DHU_UBA_LNCTRL); 824 1.1 ragge 825 1.2 ragge if (lnctrl & DHU_LNCTRL_RTS) 826 1.1 ragge mbits |= DML_RTS; 827 1.1 ragge 828 1.2 ragge if (lnctrl & DHU_LNCTRL_DTR) 829 1.1 ragge mbits |= DML_DTR; 830 1.1 ragge 831 1.2 ragge if (lnctrl & DHU_LNCTRL_BREAK) 832 1.1 ragge mbits |= DML_BRK; 833 1.1 ragge 834 1.5 ragge switch (how) { 835 1.5 ragge 836 1.5 ragge case DMSET: 837 1.1 ragge mbits = bits; 838 1.1 ragge break; 839 1.1 ragge 840 1.5 ragge case DMBIS: 841 1.1 ragge mbits |= bits; 842 1.1 ragge break; 843 1.1 ragge 844 1.5 ragge case DMBIC: 845 1.1 ragge mbits &= ~bits; 846 1.1 ragge break; 847 1.1 ragge 848 1.5 ragge case DMGET: 849 1.1 ragge (void) splx(s); 850 1.1 ragge return (mbits); 851 1.1 ragge } 852 1.1 ragge 853 1.1 ragge if (mbits & DML_RTS) 854 1.2 ragge lnctrl |= DHU_LNCTRL_RTS; 855 1.1 ragge else 856 1.2 ragge lnctrl &= ~DHU_LNCTRL_RTS; 857 1.1 ragge 858 1.1 ragge if (mbits & DML_DTR) 859 1.2 ragge lnctrl |= DHU_LNCTRL_DTR; 860 1.1 ragge else 861 1.2 ragge lnctrl &= ~DHU_LNCTRL_DTR; 862 1.1 ragge 863 1.1 ragge if (mbits & DML_BRK) 864 1.2 ragge lnctrl |= DHU_LNCTRL_BREAK; 865 1.1 ragge else 866 1.2 ragge lnctrl &= ~DHU_LNCTRL_BREAK; 867 1.2 ragge 868 1.15 ragge DHU_WRITE_WORD(DHU_UBA_LNCTRL, lnctrl); 869 1.1 ragge 870 1.1 ragge (void) splx(s); 871 1.1 ragge return (mbits); 872 1.1 ragge } 873