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