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