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