1 /* $NetBSD: dcm.c,v 1.92 2023/04/21 23:01:59 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1988 University of Utah. 34 * Copyright (c) 1982, 1986, 1990, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * the Systems Programming Group of the University of Utah Computer 39 * Science Department. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * from Utah: $Hdr: dcm.c 1.29 92/01/21$ 66 * 67 * @(#)dcm.c 8.4 (Berkeley) 1/12/94 68 */ 69 70 /* 71 * TODO: 72 * Timeouts 73 * Test console support. 74 */ 75 76 /* 77 * 98642/MUX 78 */ 79 80 #include <sys/cdefs.h> 81 __KERNEL_RCSID(0, "$NetBSD: dcm.c,v 1.92 2023/04/21 23:01:59 tsutsui Exp $"); 82 83 #include "opt_kgdb.h" 84 85 #include <sys/param.h> 86 #include <sys/systm.h> 87 #include <sys/ioctl.h> 88 #include <sys/proc.h> 89 #include <sys/tty.h> 90 #include <sys/conf.h> 91 #include <sys/file.h> 92 #include <sys/uio.h> 93 #include <sys/kernel.h> 94 #include <sys/syslog.h> 95 #include <sys/time.h> 96 #include <sys/device.h> 97 #include <sys/kauth.h> 98 99 #include <machine/bus.h> 100 101 #include <dev/cons.h> 102 103 #include <hp300/dev/diovar.h> 104 #include <hp300/dev/diodevs.h> 105 #include <hp300/dev/dcmreg.h> 106 107 #include "ioconf.h" 108 109 #ifndef DEFAULT_BAUD_RATE 110 #define DEFAULT_BAUD_RATE 9600 111 #endif 112 113 static const struct speedtab dcmspeedtab[] = { 114 { 0, BR_0 }, 115 { 50, BR_50 }, 116 { 75, BR_75 }, 117 { 110, BR_110 }, 118 { 134, BR_134 }, 119 { 150, BR_150 }, 120 { 300, BR_300 }, 121 { 600, BR_600 }, 122 { 1200, BR_1200 }, 123 { 1800, BR_1800 }, 124 { 2400, BR_2400 }, 125 { 4800, BR_4800 }, 126 { 9600, BR_9600 }, 127 { 19200, BR_19200 }, 128 { 38400, BR_38400 }, 129 { -1, -1 }, 130 }; 131 132 /* u-sec per character based on baudrate (assumes 1 start/8 data/1 stop bit) */ 133 #define DCM_USPERCH(s) (10000000 / (s)) 134 135 /* 136 * Per board interrupt scheme. 16.7ms is the polling interrupt rate 137 * (16.7ms is about 550 baud, 38.4k is 72 chars in 16.7ms). 138 */ 139 #define DIS_TIMER 0 140 #define DIS_PERCHAR 1 141 #define DIS_RESET 2 142 143 static int dcmistype = -1; /* -1 == dynamic, 0 == timer, 1 == perchar */ 144 static int dcminterval = 5; /* interval (secs) between checks */ 145 struct dcmischeme { 146 int dis_perchar; /* non-zero if interrupting per char */ 147 long dis_time; /* last time examined */ 148 int dis_intr; /* recv interrupts during last interval */ 149 int dis_char; /* characters read during last interval */ 150 }; 151 152 #ifdef KGDB 153 /* 154 * Kernel GDB support 155 */ 156 #include <machine/remote-sl.h> 157 158 extern dev_t kgdb_dev; 159 extern int kgdb_rate; 160 extern int kgdb_debug_init; 161 #endif 162 163 /* #define DCMSTATS */ 164 165 #ifdef DEBUG 166 int dcmdebug = 0x0; 167 #define DDB_SIOERR 0x01 168 #define DDB_PARAM 0x02 169 #define DDB_INPUT 0x04 170 #define DDB_OUTPUT 0x08 171 #define DDB_INTR 0x10 172 #define DDB_IOCTL 0x20 173 #define DDB_INTSCHM 0x40 174 #define DDB_MODEM 0x80 175 #define DDB_OPENCLOSE 0x100 176 #endif 177 178 #ifdef DCMSTATS 179 #define DCMRBSIZE 94 180 #define DCMXBSIZE 24 181 182 struct dcmstats { 183 long xints; /* # of xmit ints */ 184 long xchars; /* # of xmit chars */ 185 long xempty; /* times outq is empty in dcmstart */ 186 long xrestarts; /* times completed while xmitting */ 187 long rints; /* # of recv ints */ 188 long rchars; /* # of recv chars */ 189 long xsilo[DCMXBSIZE+2]; /* times this many chars xmit on one int */ 190 long rsilo[DCMRBSIZE+2]; /* times this many chars read on one int */ 191 }; 192 #endif 193 194 #define DCMUNIT(x) TTUNIT(x) 195 #define DCMDIALOUT(x) TTDIALOUT(x) 196 #define DCMBOARD(x) (((x) >> 2) & 0x3f) 197 #define DCMPORT(x) ((x) & 3) 198 199 /* 200 * Conversion from "HP DCE" to almost-normal DCE: on the 638 8-port mux, 201 * the distribution panel uses "HP DCE" conventions. If requested via 202 * the device flags, we swap the inputs to something closer to normal DCE, 203 * allowing a straight-through cable to a DTE or a reversed cable 204 * to a DCE (reversing 2-3, 4-5, 8-20 and leaving 6 unconnected; 205 * this gets "DCD" on pin 20 and "CTS" on 4, but doesn't connect 206 * DSR or make RTS work, though). The following gives the full 207 * details of a cable from this mux panel to a modem: 208 * 209 * HP modem 210 * name pin pin name 211 * HP inputs: 212 * "Rx" 2 3 Tx 213 * CTS 4 5 CTS (only needed for CCTS_OFLOW) 214 * DCD 20 8 DCD 215 * "DSR" 9 6 DSR (unneeded) 216 * RI 22 22 RI (unneeded) 217 * 218 * HP outputs: 219 * "Tx" 3 2 Rx 220 * "DTR" 6 not connected 221 * "RTS" 8 20 DTR 222 * "SR" 23 4 RTS (often not needed) 223 */ 224 #define hp2dce_in(ibits) (iconv[(ibits) & 0xf]) 225 static const char iconv[16] = { 226 0, MI_DM, MI_CTS, MI_CTS|MI_DM, 227 MI_CD, MI_CD|MI_DM, MI_CD|MI_CTS, MI_CD|MI_CTS|MI_DM, 228 MI_RI, MI_RI|MI_DM, MI_RI|MI_CTS, MI_RI|MI_CTS|MI_DM, 229 MI_RI|MI_CD, MI_RI|MI_CD|MI_DM, MI_RI|MI_CD|MI_CTS, 230 MI_RI|MI_CD|MI_CTS|MI_DM 231 }; 232 233 /* 234 * Note that 8-port boards appear as 2 4-port boards at consecutive 235 * select codes. 236 */ 237 #define NDCMPORT 4 238 239 struct dcm_softc { 240 device_t sc_dev; /* generic device glue */ 241 242 bus_space_tag_t sc_bst; 243 bus_space_handle_t sc_bsh; 244 245 struct dcmdevice *sc_dcm; /* pointer to hardware */ 246 struct tty *sc_tty[NDCMPORT]; /* our tty instances */ 247 struct modemreg *sc_modem[NDCMPORT]; /* modem control */ 248 char sc_mcndlast[NDCMPORT]; /* XXX last modem status for port */ 249 short sc_softCAR; /* mask of ports with soft-carrier */ 250 struct dcmischeme sc_scheme; /* interrupt scheme for board */ 251 252 /* 253 * Mask of soft-carrier bits in config flags. 254 */ 255 #define DCM_SOFTCAR 0x0000000f 256 257 int sc_flags; /* misc. configuration info */ 258 259 /* 260 * Bits for sc_flags 261 */ 262 #define DCM_ACTIVE 0x00000001 /* indicates board is alive */ 263 #define DCM_ISCONSOLE 0x00000002 /* indicates board is console */ 264 #define DCM_STDDCE 0x00000010 /* re-map DCE to standard */ 265 #define DCM_FLAGMASK (DCM_STDDCE) /* mask of valid bits in config flags */ 266 267 #ifdef DCMSTATS 268 struct dcmstats sc_stats; /* metrics gathering */ 269 #endif 270 }; 271 272 static int dcmintr(void *); 273 static void dcmpint(struct dcm_softc *, int, int); 274 static void dcmrint(struct dcm_softc *); 275 static void dcmreadbuf(struct dcm_softc *, int); 276 static void dcmxint(struct dcm_softc *, int); 277 static void dcmmint(struct dcm_softc *, int, int); 278 279 static int dcmparam(struct tty *, struct termios *); 280 static void dcmstart(struct tty *); 281 static int dcmmctl(dev_t, int, int); 282 static void dcmsetischeme(int, int); 283 static void dcminit(struct dcmdevice *, int, int); 284 285 static int dcmselftest(struct dcm_softc *); 286 287 static int dcmcngetc(dev_t); 288 static void dcmcnputc(dev_t, int); 289 290 int dcmcnattach(bus_space_tag_t, bus_addr_t, int); 291 292 static int dcmmatch(device_t, cfdata_t, void *); 293 static void dcmattach(device_t, device_t, void *); 294 295 CFATTACH_DECL_NEW(dcm, sizeof(struct dcm_softc), 296 dcmmatch, dcmattach, NULL, NULL); 297 298 /* 299 * Stuff for DCM console support. This could probably be done a little 300 * better. 301 */ 302 static struct dcmdevice *dcm_cn = NULL; /* pointer to hardware */ 303 static int dcmconsinit; /* has been initialized */ 304 #if 0 305 static int dcm_lastcnpri = CN_DEAD; /* XXX last priority */ 306 #endif 307 308 static struct consdev dcm_cons = { 309 .cn_getc = dcmcngetc, 310 .cn_putc = dcmcnputc, 311 .cn_pollc = nullcnpollc, 312 .cn_dev = NODEV, 313 .cn_pri = CN_REMOTE 314 }; 315 int dcmconscode; 316 int dcmdefaultrate = DEFAULT_BAUD_RATE; 317 int dcmconbrdbusy = 0; 318 319 static dev_type_open(dcmopen); 320 static dev_type_close(dcmclose); 321 static dev_type_read(dcmread); 322 static dev_type_write(dcmwrite); 323 static dev_type_ioctl(dcmioctl); 324 static dev_type_stop(dcmstop); 325 static dev_type_tty(dcmtty); 326 static dev_type_poll(dcmpoll); 327 328 const struct cdevsw dcm_cdevsw = { 329 .d_open = dcmopen, 330 .d_close = dcmclose, 331 .d_read = dcmread, 332 .d_write = dcmwrite, 333 .d_ioctl = dcmioctl, 334 .d_stop = dcmstop, 335 .d_tty = dcmtty, 336 .d_poll = dcmpoll, 337 .d_mmap = nommap, 338 .d_kqfilter = ttykqfilter, 339 .d_discard = nodiscard, 340 .d_flag = D_TTY 341 }; 342 343 static int 344 dcmmatch(device_t parent, cfdata_t cf, void *aux) 345 { 346 struct dio_attach_args *da = aux; 347 348 switch (da->da_id) { 349 case DIO_DEVICE_ID_DCM: 350 case DIO_DEVICE_ID_DCMREM: 351 return 1; 352 } 353 354 return 0; 355 } 356 357 static void 358 dcmattach(device_t parent, device_t self, void *aux) 359 { 360 struct dcm_softc *sc = device_private(self); 361 struct dio_attach_args *da = aux; 362 struct dcmdevice *dcm; 363 int brd = device_unit(self); 364 int scode = da->da_scode; 365 int i, mbits, code; 366 367 sc->sc_dev = self; 368 sc->sc_flags = 0; 369 370 if (scode == dcmconscode) { 371 dcm = dcm_cn; 372 sc->sc_flags |= DCM_ISCONSOLE; 373 374 /* 375 * We didn't know which unit this would be during 376 * the console probe, so we have to fixup cn_dev here. 377 * Note that we always assume port 1 on the board. 378 */ 379 cn_tab->cn_dev = makedev(cdevsw_lookup_major(&dcm_cdevsw), 380 (brd << 2) | DCMCONSPORT); 381 } else { 382 sc->sc_bst = da->da_bst; 383 if (bus_space_map(sc->sc_bst, da->da_addr, da->da_size, 384 BUS_SPACE_MAP_LINEAR, &sc->sc_bsh)) { 385 aprint_error(": can't map registers\n"); 386 return; 387 } 388 dcm = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); 389 } 390 391 sc->sc_dcm = dcm; 392 393 /* 394 * XXX someone _should_ fix this; the self test screws 395 * autoconfig messages. 396 */ 397 if ((sc->sc_flags & DCM_ISCONSOLE) && dcmselftest(sc)) { 398 aprint_normal("\n"); 399 aprint_error_dev(self, "self-test failed\n"); 400 return; 401 } 402 403 /* Extract configuration info from flags. */ 404 sc->sc_softCAR = device_cfdata(self)->cf_flags & DCM_SOFTCAR; 405 sc->sc_flags |= device_cfdata(self)->cf_flags & DCM_FLAGMASK; 406 407 /* Mark our unit as configured. */ 408 sc->sc_flags |= DCM_ACTIVE; 409 410 /* Establish the interrupt handler. */ 411 (void)dio_intr_establish(dcmintr, sc, da->da_ipl, IPL_TTY); 412 413 if (dcmistype == DIS_TIMER) 414 dcmsetischeme(brd, DIS_RESET|DIS_TIMER); 415 else 416 dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR); 417 418 /* load pointers to modem control */ 419 sc->sc_modem[0] = &dcm->dcm_modem0; 420 sc->sc_modem[1] = &dcm->dcm_modem1; 421 sc->sc_modem[2] = &dcm->dcm_modem2; 422 sc->sc_modem[3] = &dcm->dcm_modem3; 423 424 /* set DCD (modem) and CTS (flow control) on all ports */ 425 if (sc->sc_flags & DCM_STDDCE) 426 mbits = hp2dce_in(MI_CD|MI_CTS); 427 else 428 mbits = MI_CD|MI_CTS; 429 430 for (i = 0; i < NDCMPORT; i++) 431 sc->sc_modem[i]->mdmmsk = mbits; 432 433 /* 434 * Get current state of mdmin register on all ports, so that 435 * deltas will work properly. 436 */ 437 for (i = 0; i < NDCMPORT; i++) { 438 code = sc->sc_modem[i]->mdmin; 439 if (sc->sc_flags & DCM_STDDCE) 440 code = hp2dce_in(code); 441 sc->sc_mcndlast[i] = code; 442 } 443 444 dcm->dcm_ic = IC_IE; /* turn all interrupts on */ 445 446 /* 447 * Need to reset baud rate, etc. of next print so reset dcmconsinit. 448 * Also make sure console is always "hardwired" 449 */ 450 if (sc->sc_flags & DCM_ISCONSOLE) { 451 dcmconsinit = 0; 452 sc->sc_softCAR |= (1 << DCMCONSPORT); 453 aprint_normal(": console on port %d\n", DCMCONSPORT); 454 } else 455 aprint_normal("\n"); 456 457 #ifdef KGDB 458 if (cdevsw_lookup(kgdb_dev) == &dcm_cdevsw && 459 DCMBOARD(DCMUNIT(kgdb_dev)) == brd) { 460 if (dcmconsole == DCMUNIT(kgdb_dev)) /* XXX fixme */ 461 kgdb_dev = NODEV; /* can't debug over console port */ 462 #ifndef KGDB_CHEAT 463 /* 464 * The following could potentially be replaced 465 * by the corresponding code in dcmcnprobe. 466 */ 467 else { 468 dcminit(dcm, DCMPORT(DCMUNIT(kgdb_dev)), 469 kgdb_rate); 470 if (kgdb_debug_init) { 471 aprint_normal_dev(self, "port %d: ", 472 DCMPORT(DCMUNIT(kgdb_dev))); 473 kgdb_connect(1); 474 } else 475 aprint_normal_dev(self, 476 "port %d: kgdb enabled\n", 477 DCMPORT(DCMUNIT(kgdb_dev))); 478 } 479 /* end could be replaced */ 480 #endif /* KGDB_CHEAT */ 481 } 482 #endif /* KGDB */ 483 } 484 485 static int 486 dcmopen(dev_t dev, int flag, int mode, struct lwp *l) 487 { 488 struct dcm_softc *sc; 489 struct tty *tp; 490 int unit, brd, port; 491 int error = 0, mbits, s; 492 493 unit = DCMUNIT(dev); 494 brd = DCMBOARD(unit); 495 port = DCMPORT(unit); 496 497 sc = device_lookup_private(&dcm_cd, brd); 498 if (sc == NULL) 499 return ENXIO; 500 501 if ((sc->sc_flags & DCM_ACTIVE) == 0) 502 return ENXIO; 503 504 if (sc->sc_tty[port] == NULL) { 505 tp = sc->sc_tty[port] = tty_alloc(); 506 tty_attach(tp); 507 } else 508 tp = sc->sc_tty[port]; 509 510 tp->t_oproc = dcmstart; 511 tp->t_param = dcmparam; 512 tp->t_dev = dev; 513 514 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 515 return (EBUSY); 516 517 s = spltty(); 518 519 if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { 520 /* 521 * Sanity clause: reset the card on first open. 522 * The card might be left in an inconsistent state 523 * if the card memory is read inadvertently. 524 */ 525 dcminit(sc->sc_dcm, port, dcmdefaultrate); 526 527 ttychars(tp); 528 tp->t_iflag = TTYDEF_IFLAG; 529 tp->t_oflag = TTYDEF_OFLAG; 530 tp->t_cflag = TTYDEF_CFLAG; 531 tp->t_lflag = TTYDEF_LFLAG; 532 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 533 534 (void) dcmparam(tp, &tp->t_termios); 535 ttsetwater(tp); 536 537 /* Set modem control state. */ 538 mbits = MO_ON; 539 if (sc->sc_flags & DCM_STDDCE) 540 mbits |= MO_SR; /* pin 23, could be used as RTS */ 541 542 (void) dcmmctl(dev, mbits, DMSET); /* enable port */ 543 544 /* Set soft-carrier if so configured. */ 545 if ((sc->sc_softCAR & (1 << port)) || 546 (dcmmctl(dev, MO_OFF, DMGET) & MI_CD)) 547 tp->t_state |= TS_CARR_ON; 548 } 549 550 splx(s); 551 552 #ifdef DEBUG 553 if (dcmdebug & DDB_MODEM) 554 printf("%s: dcmopen port %d softcarr %c\n", 555 device_xname(sc->sc_dev), port, 556 (tp->t_state & TS_CARR_ON) ? '1' : '0'); 557 #endif 558 559 error = ttyopen(tp, DCMDIALOUT(dev), (flag & O_NONBLOCK)); 560 if (error) 561 goto bad; 562 563 #ifdef DEBUG 564 if (dcmdebug & DDB_OPENCLOSE) 565 printf("%s port %d: dcmopen: st %x fl %x\n", 566 device_xname(sc->sc_dev), port, tp->t_state, tp->t_flags); 567 #endif 568 error = (*tp->t_linesw->l_open)(dev, tp); 569 570 bad: 571 return error; 572 } 573 574 static int 575 dcmclose(dev_t dev, int flag, int mode, struct lwp *l) 576 { 577 int s, unit, board, port; 578 struct dcm_softc *sc; 579 struct tty *tp; 580 581 unit = DCMUNIT(dev); 582 board = DCMBOARD(unit); 583 port = DCMPORT(unit); 584 585 sc = device_lookup_private(&dcm_cd,board); 586 tp = sc->sc_tty[port]; 587 588 (*tp->t_linesw->l_close)(tp, flag); 589 590 s = spltty(); 591 592 if (tp->t_cflag & HUPCL || tp->t_wopen != 0 || 593 (tp->t_state & TS_ISOPEN) == 0) 594 (void) dcmmctl(dev, MO_OFF, DMSET); 595 #ifdef DEBUG 596 if (dcmdebug & DDB_OPENCLOSE) 597 printf("%s port %d: dcmclose: st %x fl %x\n", 598 device_xname(sc->sc_dev), port, tp->t_state, tp->t_flags); 599 #endif 600 splx(s); 601 ttyclose(tp); 602 #if 0 603 tty_detach(tp); 604 tty_free(tp); 605 sc->sc_tty[port] == NULL; 606 #endif 607 return 0; 608 } 609 610 static int 611 dcmread(dev_t dev, struct uio *uio, int flag) 612 { 613 int unit, board, port; 614 struct dcm_softc *sc; 615 struct tty *tp; 616 617 unit = DCMUNIT(dev); 618 board = DCMBOARD(unit); 619 port = DCMPORT(unit); 620 621 sc = device_lookup_private(&dcm_cd,board); 622 tp = sc->sc_tty[port]; 623 624 return (*tp->t_linesw->l_read)(tp, uio, flag); 625 } 626 627 static int 628 dcmwrite(dev_t dev, struct uio *uio, int flag) 629 { 630 int unit, board, port; 631 struct dcm_softc *sc; 632 struct tty *tp; 633 634 unit = DCMUNIT(dev); 635 board = DCMBOARD(unit); 636 port = DCMPORT(unit); 637 638 sc = device_lookup_private(&dcm_cd, board); 639 tp = sc->sc_tty[port]; 640 641 return (*tp->t_linesw->l_write)(tp, uio, flag); 642 } 643 644 static int 645 dcmpoll(dev_t dev, int events, struct lwp *l) 646 { 647 int unit, board, port; 648 struct dcm_softc *sc; 649 struct tty *tp; 650 651 unit = DCMUNIT(dev); 652 board = DCMBOARD(unit); 653 port = DCMPORT(unit); 654 655 sc = device_lookup_private(&dcm_cd, board); 656 tp = sc->sc_tty[port]; 657 658 return (*tp->t_linesw->l_poll)(tp, events, l); 659 } 660 661 static struct tty * 662 dcmtty(dev_t dev) 663 { 664 int unit, board, port; 665 struct dcm_softc *sc; 666 667 unit = DCMUNIT(dev); 668 board = DCMBOARD(unit); 669 port = DCMPORT(unit); 670 671 sc = device_lookup_private(&dcm_cd, board); 672 673 return sc->sc_tty[port]; 674 } 675 676 static int 677 dcmintr(void *arg) 678 { 679 struct dcm_softc *sc = arg; 680 struct dcmdevice *dcm = sc->sc_dcm; 681 struct dcmischeme *dis = &sc->sc_scheme; 682 int brd = device_unit(sc->sc_dev); 683 int code, i; 684 int pcnd[4], mcode, mcnd[4]; 685 686 /* 687 * Do all guarded accesses right off to minimize 688 * block out of hardware. 689 */ 690 SEM_LOCK(dcm); 691 if ((dcm->dcm_ic & IC_IR) == 0) { 692 SEM_UNLOCK(dcm); 693 return 0; 694 } 695 for (i = 0; i < 4; i++) { 696 pcnd[i] = dcm->dcm_icrtab[i].dcm_data; 697 dcm->dcm_icrtab[i].dcm_data = 0; 698 code = sc->sc_modem[i]->mdmin; 699 if (sc->sc_flags & DCM_STDDCE) 700 code = hp2dce_in(code); 701 mcnd[i] = code; 702 } 703 code = dcm->dcm_iir & IIR_MASK; 704 dcm->dcm_iir = 0; /* XXX doc claims read clears interrupt?! */ 705 mcode = dcm->dcm_modemintr; 706 dcm->dcm_modemintr = 0; 707 SEM_UNLOCK(dcm); 708 709 #ifdef DEBUG 710 if (dcmdebug & DDB_INTR) { 711 printf("%s: dcmintr: iir %x pc %x/%x/%x/%x ", 712 device_xname(sc->sc_dev), code, pcnd[0], pcnd[1], 713 pcnd[2], pcnd[3]); 714 printf("miir %x mc %x/%x/%x/%x\n", 715 mcode, mcnd[0], mcnd[1], mcnd[2], mcnd[3]); 716 } 717 #endif 718 if (code & IIR_TIMEO) 719 dcmrint(sc); 720 if (code & IIR_PORT0) 721 dcmpint(sc, 0, pcnd[0]); 722 if (code & IIR_PORT1) 723 dcmpint(sc, 1, pcnd[1]); 724 if (code & IIR_PORT2) 725 dcmpint(sc, 2, pcnd[2]); 726 if (code & IIR_PORT3) 727 dcmpint(sc, 3, pcnd[3]); 728 if (code & IIR_MODM) { 729 if (mcode == 0 || mcode & 0x1) /* mcode==0 -> 98642 board */ 730 dcmmint(sc, 0, mcnd[0]); 731 if (mcode & 0x2) 732 dcmmint(sc, 1, mcnd[1]); 733 if (mcode & 0x4) 734 dcmmint(sc, 2, mcnd[2]); 735 if (mcode & 0x8) 736 dcmmint(sc, 3, mcnd[3]); 737 } 738 739 /* 740 * Chalk up a receiver interrupt if the timer running or one of 741 * the ports reports a special character interrupt. 742 */ 743 if ((code & IIR_TIMEO) || 744 ((pcnd[0]|pcnd[1]|pcnd[2]|pcnd[3]) & IT_SPEC)) 745 dis->dis_intr++; 746 /* 747 * See if it is time to check/change the interrupt rate. 748 */ 749 if (dcmistype < 0 && 750 (i = time_second - dis->dis_time) >= dcminterval) { 751 /* 752 * If currently per-character and averaged over 70 interrupts 753 * per-second (66 is threshold of 600 baud) in last interval, 754 * switch to timer mode. 755 * 756 * XXX decay counts ala load average to avoid spikes? 757 */ 758 if (dis->dis_perchar && dis->dis_intr > 70 * i) 759 dcmsetischeme(brd, DIS_TIMER); 760 /* 761 * If currently using timer and had more interrupts than 762 * received characters in the last interval, switch back 763 * to per-character. Note that after changing to per-char 764 * we must process any characters already in the queue 765 * since they may have arrived before the bitmap was setup. 766 * 767 * XXX decay counts? 768 */ 769 else if (!dis->dis_perchar && dis->dis_intr > dis->dis_char) { 770 dcmsetischeme(brd, DIS_PERCHAR); 771 dcmrint(sc); 772 } 773 dis->dis_intr = dis->dis_char = 0; 774 dis->dis_time = time_second; 775 } 776 return 1; 777 } 778 779 /* 780 * Port interrupt. Can be two things: 781 * First, it might be a special character (exception interrupt); 782 * Second, it may be a buffer empty (transmit interrupt); 783 */ 784 static void 785 dcmpint(struct dcm_softc *sc, int port, int code) 786 { 787 788 if (code & IT_SPEC) 789 dcmreadbuf(sc, port); 790 if (code & IT_TX) 791 dcmxint(sc, port); 792 } 793 794 static void 795 dcmrint(struct dcm_softc *sc) 796 { 797 int port; 798 799 for (port = 0; port < NDCMPORT; port++) 800 dcmreadbuf(sc, port); 801 } 802 803 static void 804 dcmreadbuf(struct dcm_softc *sc, int port) 805 { 806 struct dcmdevice *dcm = sc->sc_dcm; 807 struct dcmpreg *pp = dcm_preg(dcm, port); 808 struct dcmrfifo *fifo; 809 struct tty *tp; 810 int c, stat; 811 u_int head; 812 int nch = 0; 813 #ifdef DCMSTATS 814 struct dcmstats *dsp = &sc->sc_stats; 815 816 dsp->rints++; 817 #endif 818 tp = sc->sc_tty[port]; 819 if (tp == NULL) 820 return; 821 822 if ((tp->t_state & TS_ISOPEN) == 0) { 823 #ifdef KGDB 824 int maj; 825 826 maj = cdevsw_lookup_major(&dcm_cdevsw); 827 828 if ((makedev(maj, minor(tp->t_dev)) == kgdb_dev) && 829 (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) && 830 dcm->dcm_rfifos[3-port][head>>1].data_char == FRAME_START) { 831 pp->r_head = (head + 2) & RX_MASK; 832 kgdb_connect(0); /* trap into kgdb */ 833 return; 834 } 835 #endif /* KGDB */ 836 pp->r_head = pp->r_tail & RX_MASK; 837 return; 838 } 839 840 head = pp->r_head & RX_MASK; 841 fifo = &dcm->dcm_rfifos[3-port][head>>1]; 842 /* 843 * XXX upper bound on how many chars we will take in one swallow? 844 */ 845 while (head != (pp->r_tail & RX_MASK)) { 846 /* 847 * Get character/status and update head pointer as fast 848 * as possible to make room for more characters. 849 */ 850 c = fifo->data_char; 851 stat = fifo->data_stat; 852 head = (head + 2) & RX_MASK; 853 pp->r_head = head; 854 fifo = head ? fifo+1 : &dcm->dcm_rfifos[3-port][0]; 855 nch++; 856 857 #ifdef DEBUG 858 if (dcmdebug & DDB_INPUT) 859 printf("%s port %d: " 860 "dcmreadbuf: c%x('%c') s%x f%x h%x t%x\n", 861 device_xname(sc->sc_dev), port, 862 c&0xFF, c, stat&0xFF, 863 tp->t_flags, head, pp->r_tail); 864 #endif 865 /* 866 * Check for and handle errors 867 */ 868 if (stat & RD_MASK) { 869 #ifdef DEBUG 870 if (dcmdebug & (DDB_INPUT|DDB_SIOERR)) 871 printf("%s port %d: " 872 "dcmreadbuf: err: c%x('%c') s%x\n", 873 device_xname(sc->sc_dev), port, 874 stat, c&0xFF, c); 875 #endif 876 if (stat & (RD_BD | RD_FE)) 877 c |= TTY_FE; 878 else if (stat & RD_PE) 879 c |= TTY_PE; 880 else if (stat & RD_OVF) 881 log(LOG_WARNING, 882 "%s port %d: silo overflow\n", 883 device_xname(sc->sc_dev), port); 884 else if (stat & RD_OE) 885 log(LOG_WARNING, 886 "%s port %d: uart overflow\n", 887 device_xname(sc->sc_dev), port); 888 } 889 (*tp->t_linesw->l_rint)(c, tp); 890 } 891 sc->sc_scheme.dis_char += nch; 892 893 #ifdef DCMSTATS 894 dsp->rchars += nch; 895 if (nch <= DCMRBSIZE) 896 dsp->rsilo[nch]++; 897 else 898 dsp->rsilo[DCMRBSIZE+1]++; 899 #endif 900 } 901 902 static void 903 dcmxint(struct dcm_softc *sc, int port) 904 { 905 struct tty *tp; 906 907 tp = sc->sc_tty[port]; 908 if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0) 909 return; 910 911 tp->t_state &= ~TS_BUSY; 912 if (tp->t_state & TS_FLUSH) 913 tp->t_state &= ~TS_FLUSH; 914 (*tp->t_linesw->l_start)(tp); 915 } 916 917 static void 918 dcmmint(struct dcm_softc *sc, int port, int mcnd) 919 { 920 int delta; 921 struct tty *tp; 922 struct dcmdevice *dcm = sc->sc_dcm; 923 924 #ifdef DEBUG 925 if (dcmdebug & DDB_MODEM) 926 printf("%s port %d: dcmmint: mcnd %x mcndlast %x\n", 927 device_xname(sc->sc_dev), port, mcnd, 928 sc->sc_mcndlast[port]); 929 #endif 930 delta = mcnd ^ sc->sc_mcndlast[port]; 931 sc->sc_mcndlast[port] = mcnd; 932 tp = sc->sc_tty[port]; 933 if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0) 934 return; 935 936 if ((delta & MI_CTS) && (tp->t_state & TS_ISOPEN) && 937 (tp->t_cflag & CCTS_OFLOW)) { 938 if (mcnd & MI_CTS) { 939 tp->t_state &= ~TS_TTSTOP; 940 ttstart(tp); 941 } else 942 tp->t_state |= TS_TTSTOP; /* inline dcmstop */ 943 } 944 if (delta & MI_CD) { 945 if (mcnd & MI_CD) 946 (void)(*tp->t_linesw->l_modem)(tp, 1); 947 else if ((sc->sc_softCAR & (1 << port)) == 0 && 948 (*tp->t_linesw->l_modem)(tp, 0) == 0) { 949 sc->sc_modem[port]->mdmout = MO_OFF; 950 SEM_LOCK(dcm); 951 dcm->dcm_modemchng |= (1 << port); 952 dcm->dcm_cr |= CR_MODM; 953 SEM_UNLOCK(dcm); 954 DELAY(10); /* time to change lines */ 955 } 956 } 957 } 958 959 static int 960 dcmioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 961 { 962 struct dcm_softc *sc; 963 struct tty *tp; 964 struct dcmdevice *dcm; 965 int board, port, unit = DCMUNIT(dev); 966 int error, s; 967 968 port = DCMPORT(unit); 969 board = DCMBOARD(unit); 970 971 sc = device_lookup_private(&dcm_cd, board); 972 dcm = sc->sc_dcm; 973 tp = sc->sc_tty[port]; 974 975 #ifdef DEBUG 976 if (dcmdebug & DDB_IOCTL) 977 printf("%s port %d: dcmioctl: cmd %lx data %x flag %x\n", 978 device_xname(sc->sc_dev), port, cmd, *(int *)data, flag); 979 #endif 980 981 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 982 if (error != EPASSTHROUGH) 983 return error; 984 985 error = ttioctl(tp, cmd, data, flag, l); 986 if (error != EPASSTHROUGH) 987 return error; 988 989 switch (cmd) { 990 case TIOCSBRK: 991 /* 992 * Wait for transmitter buffer to empty 993 */ 994 s = spltty(); 995 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 996 DELAY(DCM_USPERCH(tp->t_ospeed)); 997 SEM_LOCK(dcm); 998 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK; 999 dcm->dcm_cr |= (1 << port); /* start break */ 1000 SEM_UNLOCK(dcm); 1001 splx(s); 1002 break; 1003 1004 case TIOCCBRK: 1005 SEM_LOCK(dcm); 1006 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK; 1007 dcm->dcm_cr |= (1 << port); /* end break */ 1008 SEM_UNLOCK(dcm); 1009 break; 1010 1011 case TIOCSDTR: 1012 (void) dcmmctl(dev, MO_ON, DMBIS); 1013 break; 1014 1015 case TIOCCDTR: 1016 (void) dcmmctl(dev, MO_ON, DMBIC); 1017 break; 1018 1019 case TIOCMSET: 1020 (void) dcmmctl(dev, *(int *)data, DMSET); 1021 break; 1022 1023 case TIOCMBIS: 1024 (void) dcmmctl(dev, *(int *)data, DMBIS); 1025 break; 1026 1027 case TIOCMBIC: 1028 (void) dcmmctl(dev, *(int *)data, DMBIC); 1029 break; 1030 1031 case TIOCMGET: 1032 *(int *)data = dcmmctl(dev, 0, DMGET); 1033 break; 1034 1035 case TIOCGFLAGS: { 1036 int bits = 0; 1037 1038 if ((sc->sc_softCAR & (1 << port))) 1039 bits |= TIOCFLAG_SOFTCAR; 1040 1041 if (tp->t_cflag & CLOCAL) 1042 bits |= TIOCFLAG_CLOCAL; 1043 1044 *(int *)data = bits; 1045 break; 1046 } 1047 1048 case TIOCSFLAGS: { 1049 int userbits; 1050 1051 if (kauth_authorize_device_tty(l->l_cred, 1052 KAUTH_DEVICE_TTY_PRIVSET, tp)) 1053 return (EPERM); 1054 1055 userbits = *(int *)data; 1056 1057 if ((userbits & TIOCFLAG_SOFTCAR) || 1058 ((sc->sc_flags & DCM_ISCONSOLE) && 1059 (port == DCMCONSPORT))) 1060 sc->sc_softCAR |= (1 << port); 1061 1062 if (userbits & TIOCFLAG_CLOCAL) 1063 tp->t_cflag |= CLOCAL; 1064 1065 break; 1066 } 1067 1068 default: 1069 return EPASSTHROUGH; 1070 } 1071 return 0; 1072 } 1073 1074 static int 1075 dcmparam(struct tty *tp, struct termios *t) 1076 { 1077 struct dcm_softc *sc; 1078 struct dcmdevice *dcm; 1079 int unit, board, port, mode, cflag = t->c_cflag; 1080 int ospeed = ttspeedtab(t->c_ospeed, dcmspeedtab); 1081 1082 unit = DCMUNIT(tp->t_dev); 1083 board = DCMBOARD(unit); 1084 port = DCMPORT(unit); 1085 1086 sc = device_lookup_private(&dcm_cd, board); 1087 dcm = sc->sc_dcm; 1088 1089 /* check requested parameters */ 1090 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 1091 return EINVAL; 1092 /* and copy to tty */ 1093 tp->t_ispeed = t->c_ispeed; 1094 tp->t_ospeed = t->c_ospeed; 1095 tp->t_cflag = cflag; 1096 if (ospeed == 0) { 1097 (void)dcmmctl(DCMUNIT(tp->t_dev), MO_OFF, DMSET); 1098 return 0; 1099 } 1100 1101 mode = 0; 1102 switch (cflag&CSIZE) { 1103 case CS5: 1104 mode = LC_5BITS; break; 1105 case CS6: 1106 mode = LC_6BITS; break; 1107 case CS7: 1108 mode = LC_7BITS; break; 1109 case CS8: 1110 mode = LC_8BITS; break; 1111 } 1112 if (cflag&PARENB) { 1113 if (cflag&PARODD) 1114 mode |= LC_PODD; 1115 else 1116 mode |= LC_PEVEN; 1117 } 1118 if (cflag&CSTOPB) 1119 mode |= LC_2STOP; 1120 else 1121 mode |= LC_1STOP; 1122 #ifdef DEBUG 1123 if (dcmdebug & DDB_PARAM) 1124 printf("%s port %d: " 1125 "dcmparam: cflag %x mode %x speed %d uperch %d\n", 1126 device_xname(sc->sc_dev), port, cflag, mode, tp->t_ospeed, 1127 DCM_USPERCH(tp->t_ospeed)); 1128 #endif 1129 1130 /* 1131 * Wait for transmitter buffer to empty. 1132 */ 1133 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 1134 DELAY(DCM_USPERCH(tp->t_ospeed)); 1135 /* 1136 * Make changes known to hardware. 1137 */ 1138 dcm->dcm_data[port].dcm_baud = ospeed; 1139 dcm->dcm_data[port].dcm_conf = mode; 1140 SEM_LOCK(dcm); 1141 dcm->dcm_cmdtab[port].dcm_data |= CT_CON; 1142 dcm->dcm_cr |= (1 << port); 1143 SEM_UNLOCK(dcm); 1144 /* 1145 * Delay for config change to take place. Weighted by baud. 1146 * XXX why do we do this? 1147 */ 1148 DELAY(16 * DCM_USPERCH(tp->t_ospeed)); 1149 return 0; 1150 } 1151 1152 static void 1153 dcmstart(struct tty *tp) 1154 { 1155 struct dcm_softc *sc; 1156 struct dcmdevice *dcm; 1157 struct dcmpreg *pp; 1158 struct dcmtfifo *fifo; 1159 char *bp; 1160 u_int head, tail, next; 1161 int unit, board, port, nch; 1162 char buf[16]; 1163 int s; 1164 #ifdef DCMSTATS 1165 struct dcmstats *dsp = &sc->sc_stats; 1166 int tch = 0; 1167 #endif 1168 1169 unit = DCMUNIT(tp->t_dev); 1170 board = DCMBOARD(unit); 1171 port = DCMPORT(unit); 1172 1173 sc = device_lookup_private(&dcm_cd, board); 1174 dcm = sc->sc_dcm; 1175 1176 s = spltty(); 1177 #ifdef DCMSTATS 1178 dsp->xints++; 1179 #endif 1180 #ifdef DEBUG 1181 if (dcmdebug & DDB_OUTPUT) 1182 printf("%s port %d: dcmstart: state %x flags %x outcc %d\n", 1183 device_xname(sc->sc_dev), port, tp->t_state, tp->t_flags, 1184 tp->t_outq.c_cc); 1185 #endif 1186 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 1187 goto out; 1188 if (!ttypull(tp)) { 1189 #ifdef DCMSTATS 1190 dsp->xempty++; 1191 #endif 1192 goto out; 1193 } 1194 1195 pp = dcm_preg(dcm, port); 1196 tail = pp->t_tail & TX_MASK; 1197 next = (tail + 1) & TX_MASK; 1198 head = pp->t_head & TX_MASK; 1199 if (head == next) 1200 goto out; 1201 fifo = &dcm->dcm_tfifos[3-port][tail]; 1202 again: 1203 nch = q_to_b(&tp->t_outq, buf, (head - next) & TX_MASK); 1204 #ifdef DCMSTATS 1205 tch += nch; 1206 #endif 1207 #ifdef DEBUG 1208 if (dcmdebug & DDB_OUTPUT) 1209 printf("\thead %x tail %x nch %d\n", head, tail, nch); 1210 #endif 1211 /* 1212 * Loop transmitting all the characters we can. 1213 */ 1214 for (bp = buf; --nch >= 0; bp++) { 1215 fifo->data_char = *bp; 1216 pp->t_tail = next; 1217 /* 1218 * If this is the first character, 1219 * get the hardware moving right now. 1220 */ 1221 if (bp == buf) { 1222 tp->t_state |= TS_BUSY; 1223 SEM_LOCK(dcm); 1224 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 1225 dcm->dcm_cr |= (1 << port); 1226 SEM_UNLOCK(dcm); 1227 } 1228 tail = next; 1229 fifo = tail ? fifo+1 : &dcm->dcm_tfifos[3-port][0]; 1230 next = (next + 1) & TX_MASK; 1231 } 1232 /* 1233 * Head changed while we were loading the buffer, 1234 * go back and load some more if we can. 1235 */ 1236 if (tp->t_outq.c_cc && head != (pp->t_head & TX_MASK)) { 1237 #ifdef DCMSTATS 1238 dsp->xrestarts++; 1239 #endif 1240 head = pp->t_head & TX_MASK; 1241 goto again; 1242 } 1243 1244 /* 1245 * Kick it one last time in case it finished while we were 1246 * loading the last bunch. 1247 */ 1248 if (bp > &buf[1]) { 1249 tp->t_state |= TS_BUSY; 1250 SEM_LOCK(dcm); 1251 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 1252 dcm->dcm_cr |= (1 << port); 1253 SEM_UNLOCK(dcm); 1254 } 1255 #ifdef DEBUG 1256 if (dcmdebug & DDB_INTR) 1257 printf("%s port %d: dcmstart: head %x tail %x outqcc %d\n", 1258 device_xname(sc->sc_dev), port, head, tail, 1259 tp->t_outq.c_cc); 1260 #endif 1261 out: 1262 #ifdef DCMSTATS 1263 dsp->xchars += tch; 1264 if (tch <= DCMXBSIZE) 1265 dsp->xsilo[tch]++; 1266 else 1267 dsp->xsilo[DCMXBSIZE+1]++; 1268 #endif 1269 splx(s); 1270 } 1271 1272 /* 1273 * Stop output on a line. 1274 */ 1275 static void 1276 dcmstop(struct tty *tp, int flag) 1277 { 1278 int s; 1279 1280 s = spltty(); 1281 if (tp->t_state & TS_BUSY) { 1282 /* XXX is there some way to safely stop transmission? */ 1283 if ((tp->t_state&TS_TTSTOP) == 0) 1284 tp->t_state |= TS_FLUSH; 1285 } 1286 splx(s); 1287 } 1288 1289 /* 1290 * Modem control 1291 */ 1292 int 1293 dcmmctl(dev_t dev, int bits, int how) 1294 { 1295 struct dcm_softc *sc; 1296 struct dcmdevice *dcm; 1297 int s, unit, brd, port, hit = 0; 1298 1299 unit = DCMUNIT(dev); 1300 brd = DCMBOARD(unit); 1301 port = DCMPORT(unit); 1302 1303 sc = device_lookup_private(&dcm_cd, brd); 1304 dcm = sc->sc_dcm; 1305 1306 #ifdef DEBUG 1307 if (dcmdebug & DDB_MODEM) 1308 printf("%s port %d: dcmmctl: bits 0x%x how %x\n", 1309 device_xname(sc->sc_dev), port, bits, how); 1310 #endif 1311 1312 s = spltty(); 1313 1314 switch (how) { 1315 case DMSET: 1316 sc->sc_modem[port]->mdmout = bits; 1317 hit++; 1318 break; 1319 1320 case DMBIS: 1321 sc->sc_modem[port]->mdmout |= bits; 1322 hit++; 1323 break; 1324 1325 case DMBIC: 1326 sc->sc_modem[port]->mdmout &= ~bits; 1327 hit++; 1328 break; 1329 1330 case DMGET: 1331 bits = sc->sc_modem[port]->mdmin; 1332 if (sc->sc_flags & DCM_STDDCE) 1333 bits = hp2dce_in(bits); 1334 break; 1335 } 1336 if (hit) { 1337 SEM_LOCK(dcm); 1338 dcm->dcm_modemchng |= 1<<(unit & 3); 1339 dcm->dcm_cr |= CR_MODM; 1340 SEM_UNLOCK(dcm); 1341 DELAY(10); /* delay until done */ 1342 splx(s); 1343 } 1344 return bits; 1345 } 1346 1347 /* 1348 * Set board to either interrupt per-character or at a fixed interval. 1349 */ 1350 static void 1351 dcmsetischeme(int brd, int flags) 1352 { 1353 struct dcm_softc *sc = device_lookup_private(&dcm_cd, brd); 1354 struct dcmdevice *dcm = sc->sc_dcm; 1355 struct dcmischeme *dis = &sc->sc_scheme; 1356 int i; 1357 u_char mask; 1358 int perchar = flags & DIS_PERCHAR; 1359 1360 #ifdef DEBUG 1361 if (dcmdebug & DDB_INTSCHM) 1362 printf("%s: dcmsetischeme(%d): cur %d, ints %d, chars %d\n", 1363 device_xname(sc->sc_dev), perchar, dis->dis_perchar, 1364 dis->dis_intr, dis->dis_char); 1365 if ((flags & DIS_RESET) == 0 && perchar == dis->dis_perchar) { 1366 printf("%s: dcmsetischeme: redundant request %d\n", 1367 device_xname(sc->sc_dev), perchar); 1368 return; 1369 } 1370 #endif 1371 /* 1372 * If perchar is non-zero, we enable interrupts on all characters 1373 * otherwise we disable perchar interrupts and use periodic 1374 * polling interrupts. 1375 */ 1376 dis->dis_perchar = perchar; 1377 mask = perchar ? 0xf : 0x0; 1378 for (i = 0; i < 256; i++) 1379 dcm->dcm_bmap[i].data_data = mask; 1380 /* 1381 * Don't slow down tandem mode, interrupt on flow control 1382 * chars for any port on the board. 1383 */ 1384 if (!perchar) { 1385 struct tty *tp; 1386 int c; 1387 1388 for (i = 0; i < NDCMPORT; i++) { 1389 tp = sc->sc_tty[i]; 1390 1391 c = tty_getctrlchar(tp, VSTART); 1392 if (c != _POSIX_VDISABLE) 1393 dcm->dcm_bmap[c].data_data |= (1 << i); 1394 c = tty_getctrlchar(tp, VSTOP); 1395 if (c != _POSIX_VDISABLE) 1396 dcm->dcm_bmap[c].data_data |= (1 << i); 1397 } 1398 } 1399 /* 1400 * Board starts with timer disabled so if first call is to 1401 * set perchar mode then we don't want to toggle the timer. 1402 */ 1403 if (flags == (DIS_RESET|DIS_PERCHAR)) 1404 return; 1405 /* 1406 * Toggle card 16.7ms interrupts (we first make sure that card 1407 * has cleared the bit so it will see the toggle). 1408 */ 1409 while (dcm->dcm_cr & CR_TIMER) 1410 ; 1411 SEM_LOCK(dcm); 1412 dcm->dcm_cr |= CR_TIMER; 1413 SEM_UNLOCK(dcm); 1414 } 1415 1416 static void 1417 dcminit(struct dcmdevice *dcm, int port, int rate) 1418 { 1419 int s, mode; 1420 1421 mode = LC_8BITS | LC_1STOP; 1422 1423 s = splhigh(); 1424 1425 /* 1426 * Wait for transmitter buffer to empty. 1427 */ 1428 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 1429 DELAY(DCM_USPERCH(rate)); 1430 1431 /* 1432 * Make changes known to hardware. 1433 */ 1434 dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab); 1435 dcm->dcm_data[port].dcm_conf = mode; 1436 SEM_LOCK(dcm); 1437 dcm->dcm_cmdtab[port].dcm_data |= CT_CON; 1438 dcm->dcm_cr |= (1 << port); 1439 SEM_UNLOCK(dcm); 1440 1441 /* 1442 * Delay for config change to take place. Weighted by baud. 1443 * XXX why do we do this? 1444 */ 1445 DELAY(16 * DCM_USPERCH(rate)); 1446 splx(s); 1447 } 1448 1449 /* 1450 * Empirically derived self-test magic 1451 */ 1452 static int 1453 dcmselftest(struct dcm_softc *sc) 1454 { 1455 struct dcmdevice *dcm = sc->sc_dcm; 1456 int timo = 0; 1457 int s, rv; 1458 1459 rv = 1; 1460 1461 s = splhigh(); 1462 dcm->dcm_rsid = DCMRS; 1463 DELAY(50000); /* 5000 is not long enough */ 1464 dcm->dcm_rsid = 0; 1465 dcm->dcm_ic = IC_IE; 1466 dcm->dcm_cr = CR_SELFT; 1467 while ((dcm->dcm_ic & IC_IR) == 0) { 1468 if (++timo == 20000) 1469 goto out; 1470 DELAY(1); 1471 } 1472 DELAY(50000); /* XXX why is this needed ???? */ 1473 while ((dcm->dcm_iir & IIR_SELFT) == 0) { 1474 if (++timo == 400000) 1475 goto out; 1476 DELAY(1); 1477 } 1478 DELAY(50000); /* XXX why is this needed ???? */ 1479 if (dcm->dcm_stcon != ST_OK) { 1480 #if 0 1481 if (hd->hp_args->hw_sc != conscode) 1482 aprint_error_dev(sc->sc_dev, "self test failed: %x\n", 1483 dcm->dcm_stcon); 1484 #endif 1485 goto out; 1486 } 1487 dcm->dcm_ic = IC_ID; 1488 rv = 0; 1489 1490 out: 1491 splx(s); 1492 return rv; 1493 } 1494 1495 /* 1496 * Following are all routines needed for DCM to act as console 1497 */ 1498 1499 int 1500 dcmcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode) 1501 { 1502 bus_space_handle_t bsh; 1503 void *va; 1504 struct dcmdevice *dcm; 1505 int maj; 1506 1507 if (bus_space_map(bst, addr, DIOCSIZE, 0, &bsh)) 1508 return 1; 1509 1510 va = bus_space_vaddr(bst, bsh); 1511 dcm = (struct dcmdevice *)va; 1512 1513 switch (dcm->dcm_rsid) { 1514 #ifdef CONSCODE 1515 case DCMID: 1516 #endif 1517 case DCMID|DCMCON: 1518 break; 1519 default: 1520 goto error; 1521 } 1522 1523 dcminit(dcm, DCMCONSPORT, dcmdefaultrate); 1524 dcmconsinit = 1; 1525 dcmconscode = scode; 1526 dcm_cn = dcm; 1527 1528 /* locate the major number */ 1529 maj = cdevsw_lookup_major(&dcm_cdevsw); 1530 1531 /* initialize required fields */ 1532 cn_tab = &dcm_cons; 1533 cn_tab->cn_dev = makedev(maj, 0); 1534 1535 #ifdef KGDB_CHEAT 1536 /* XXX this needs to be fixed. */ 1537 /* 1538 * This doesn't currently work, at least not with ite consoles; 1539 * the console hasn't been initialized yet. 1540 */ 1541 if (major(kgdb_dev) == maj && 1542 DCMBOARD(DCMUNIT(kgdb_dev)) == DCMBOARD(unit)) { 1543 dcminit(dcm_cn, DCMPORT(DCMUNIT(kgdb_dev)), kgdb_rate); 1544 if (kgdb_debug_init) { 1545 /* 1546 * We assume that console is ready for us... 1547 * this assumes that a dca or ite console 1548 * has been selected already and will init 1549 * on the first putc. 1550 */ 1551 printf("dcm%d: ", DCMUNIT(kgdb_dev)); 1552 kgdb_connect(1); 1553 } 1554 } 1555 #endif 1556 1557 1558 return 0; 1559 1560 error: 1561 bus_space_unmap(bst, bsh, DIOCSIZE); 1562 return 1; 1563 } 1564 1565 static int 1566 dcmcngetc(dev_t dev) 1567 { 1568 struct dcmrfifo *fifo; 1569 struct dcmpreg *pp; 1570 u_int head; 1571 int s, c, stat; 1572 1573 pp = dcm_preg(dcm_cn, DCMCONSPORT); 1574 1575 s = splhigh(); 1576 head = pp->r_head & RX_MASK; 1577 fifo = &dcm_cn->dcm_rfifos[3-DCMCONSPORT][head>>1]; 1578 while (head == (pp->r_tail & RX_MASK)) 1579 ; 1580 /* 1581 * If board interrupts are enabled, just let our received char 1582 * interrupt through in case some other port on the board was 1583 * busy. Otherwise we must clear the interrupt. 1584 */ 1585 SEM_LOCK(dcm_cn); 1586 if ((dcm_cn->dcm_ic & IC_IE) == 0) 1587 stat = dcm_cn->dcm_iir; 1588 SEM_UNLOCK(dcm_cn); 1589 c = fifo->data_char; 1590 stat = fifo->data_stat; 1591 pp->r_head = (head + 2) & RX_MASK; 1592 __USE(stat); 1593 splx(s); 1594 return c; 1595 } 1596 1597 /* 1598 * Console kernel output character routine. 1599 */ 1600 static void 1601 dcmcnputc(dev_t dev, int c) 1602 { 1603 struct dcmpreg *pp; 1604 unsigned tail; 1605 int s, stat; 1606 1607 pp = dcm_preg(dcm_cn, DCMCONSPORT); 1608 1609 s = splhigh(); 1610 #ifdef KGDB 1611 if (dev != kgdb_dev) 1612 #endif 1613 if (dcmconsinit == 0) { 1614 dcminit(dcm_cn, DCMCONSPORT, dcmdefaultrate); 1615 dcmconsinit = 1; 1616 } 1617 tail = pp->t_tail & TX_MASK; 1618 while (tail != (pp->t_head & TX_MASK)) 1619 continue; 1620 dcm_cn->dcm_tfifos[3-DCMCONSPORT][tail].data_char = c; 1621 pp->t_tail = tail = (tail + 1) & TX_MASK; 1622 SEM_LOCK(dcm_cn); 1623 dcm_cn->dcm_cmdtab[DCMCONSPORT].dcm_data |= CT_TX; 1624 dcm_cn->dcm_cr |= (1 << DCMCONSPORT); 1625 SEM_UNLOCK(dcm_cn); 1626 while (tail != (pp->t_head & TX_MASK)) 1627 continue; 1628 /* 1629 * If board interrupts are enabled, just let our completion 1630 * interrupt through in case some other port on the board 1631 * was busy. Otherwise we must clear the interrupt. 1632 */ 1633 if ((dcm_cn->dcm_ic & IC_IE) == 0) { 1634 SEM_LOCK(dcm_cn); 1635 stat = dcm_cn->dcm_iir; 1636 SEM_UNLOCK(dcm_cn); 1637 } 1638 __USE(stat); 1639 splx(s); 1640 } 1641