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