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