1 /* $NetBSD: dcm.c,v 1.86 2014/05/22 16:31:19 dholland 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.86 2014/05/22 16:31:19 dholland 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 .d_open = dcmopen, 335 .d_close = dcmclose, 336 .d_read = dcmread, 337 .d_write = dcmwrite, 338 .d_ioctl = dcmioctl, 339 .d_stop = dcmstop, 340 .d_tty = dcmtty, 341 .d_poll = dcmpoll, 342 .d_mmap = nommap, 343 .d_kqfilter = ttykqfilter, 344 .d_flag = D_TTY 345 }; 346 347 static int 348 dcmmatch(device_t parent, cfdata_t cf, void *aux) 349 { 350 struct dio_attach_args *da = aux; 351 352 switch (da->da_id) { 353 case DIO_DEVICE_ID_DCM: 354 case DIO_DEVICE_ID_DCMREM: 355 return 1; 356 } 357 358 return 0; 359 } 360 361 static void 362 dcmattach(device_t parent, device_t self, void *aux) 363 { 364 struct dcm_softc *sc = device_private(self); 365 struct dio_attach_args *da = aux; 366 struct dcmdevice *dcm; 367 int brd = device_unit(self); 368 int scode = da->da_scode; 369 int i, mbits, code; 370 371 sc->sc_dev = self; 372 sc->sc_flags = 0; 373 374 if (scode == dcmconscode) { 375 dcm = dcm_cn; 376 sc->sc_flags |= DCM_ISCONSOLE; 377 378 /* 379 * We didn't know which unit this would be during 380 * the console probe, so we have to fixup cn_dev here. 381 * Note that we always assume port 1 on the board. 382 */ 383 cn_tab->cn_dev = makedev(cdevsw_lookup_major(&dcm_cdevsw), 384 (brd << 2) | DCMCONSPORT); 385 } else { 386 sc->sc_bst = da->da_bst; 387 if (bus_space_map(sc->sc_bst, da->da_addr, da->da_size, 388 BUS_SPACE_MAP_LINEAR, &sc->sc_bsh)) { 389 aprint_error(": can't map registers\n"); 390 return; 391 } 392 dcm = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); 393 } 394 395 sc->sc_dcm = dcm; 396 397 /* 398 * XXX someone _should_ fix this; the self test screws 399 * autoconfig messages. 400 */ 401 if ((sc->sc_flags & DCM_ISCONSOLE) && dcmselftest(sc)) { 402 aprint_normal("\n"); 403 aprint_error_dev(self, "self-test failed\n"); 404 return; 405 } 406 407 /* Extract configuration info from flags. */ 408 sc->sc_softCAR = device_cfdata(self)->cf_flags & DCM_SOFTCAR; 409 sc->sc_flags |= device_cfdata(self)->cf_flags & DCM_FLAGMASK; 410 411 /* Mark our unit as configured. */ 412 sc->sc_flags |= DCM_ACTIVE; 413 414 /* Establish the interrupt handler. */ 415 (void)dio_intr_establish(dcmintr, sc, da->da_ipl, IPL_TTY); 416 417 if (dcmistype == DIS_TIMER) 418 dcmsetischeme(brd, DIS_RESET|DIS_TIMER); 419 else 420 dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR); 421 422 /* load pointers to modem control */ 423 sc->sc_modem[0] = &dcm->dcm_modem0; 424 sc->sc_modem[1] = &dcm->dcm_modem1; 425 sc->sc_modem[2] = &dcm->dcm_modem2; 426 sc->sc_modem[3] = &dcm->dcm_modem3; 427 428 /* set DCD (modem) and CTS (flow control) on all ports */ 429 if (sc->sc_flags & DCM_STDDCE) 430 mbits = hp2dce_in(MI_CD|MI_CTS); 431 else 432 mbits = MI_CD|MI_CTS; 433 434 for (i = 0; i < NDCMPORT; i++) 435 sc->sc_modem[i]->mdmmsk = mbits; 436 437 /* 438 * Get current state of mdmin register on all ports, so that 439 * deltas will work properly. 440 */ 441 for (i = 0; i < NDCMPORT; i++) { 442 code = sc->sc_modem[i]->mdmin; 443 if (sc->sc_flags & DCM_STDDCE) 444 code = hp2dce_in(code); 445 sc->sc_mcndlast[i] = code; 446 } 447 448 dcm->dcm_ic = IC_IE; /* turn all interrupts on */ 449 450 /* 451 * Need to reset baud rate, etc. of next print so reset dcmconsinit. 452 * Also make sure console is always "hardwired" 453 */ 454 if (sc->sc_flags & DCM_ISCONSOLE) { 455 dcmconsinit = 0; 456 sc->sc_softCAR |= (1 << DCMCONSPORT); 457 aprint_normal(": console on port %d\n", DCMCONSPORT); 458 } else 459 aprint_normal("\n"); 460 461 #ifdef KGDB 462 if (cdevsw_lookup(kgdb_dev) == &dcm_cdevsw && 463 DCMBOARD(DCMUNIT(kgdb_dev)) == brd) { 464 if (dcmconsole == DCMUNIT(kgdb_dev)) /* XXX fixme */ 465 kgdb_dev = NODEV; /* can't debug over console port */ 466 #ifndef KGDB_CHEAT 467 /* 468 * The following could potentially be replaced 469 * by the corresponding code in dcmcnprobe. 470 */ 471 else { 472 dcminit(dcm, DCMPORT(DCMUNIT(kgdb_dev)), 473 kgdb_rate); 474 if (kgdb_debug_init) { 475 aprint_normal_dev(self, "port %d: ", 476 DCMPORT(DCMUNIT(kgdb_dev))); 477 kgdb_connect(1); 478 } else 479 aprint_normal_dev(self, 480 "port %d: kgdb enabled\n", 481 DCMPORT(DCMUNIT(kgdb_dev))); 482 } 483 /* end could be replaced */ 484 #endif /* KGDB_CHEAT */ 485 } 486 #endif /* KGDB */ 487 } 488 489 /* ARGSUSED */ 490 static int 491 dcmopen(dev_t dev, int flag, int mode, struct lwp *l) 492 { 493 struct dcm_softc *sc; 494 struct tty *tp; 495 int unit, brd, port; 496 int error = 0, mbits, s; 497 498 unit = DCMUNIT(dev); 499 brd = DCMBOARD(unit); 500 port = DCMPORT(unit); 501 502 sc = device_lookup_private(&dcm_cd, brd); 503 if (sc == NULL) 504 return ENXIO; 505 506 if ((sc->sc_flags & DCM_ACTIVE) == 0) 507 return ENXIO; 508 509 if (sc->sc_tty[port] == NULL) { 510 tp = sc->sc_tty[port] = tty_alloc(); 511 tty_attach(tp); 512 } else 513 tp = sc->sc_tty[port]; 514 515 tp->t_oproc = dcmstart; 516 tp->t_param = dcmparam; 517 tp->t_dev = dev; 518 519 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 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 device_xname(sc->sc_dev), 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 device_xname(sc->sc_dev), 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 static int 581 dcmclose(dev_t dev, int flag, int mode, struct lwp *l) 582 { 583 int s, unit, board, port; 584 struct dcm_softc *sc; 585 struct tty *tp; 586 587 unit = DCMUNIT(dev); 588 board = DCMBOARD(unit); 589 port = DCMPORT(unit); 590 591 sc = device_lookup_private(&dcm_cd,board); 592 tp = sc->sc_tty[port]; 593 594 (*tp->t_linesw->l_close)(tp, flag); 595 596 s = spltty(); 597 598 if (tp->t_cflag & HUPCL || tp->t_wopen != 0 || 599 (tp->t_state & TS_ISOPEN) == 0) 600 (void) dcmmctl(dev, MO_OFF, DMSET); 601 #ifdef DEBUG 602 if (dcmdebug & DDB_OPENCLOSE) 603 printf("%s port %d: dcmclose: st %x fl %x\n", 604 device_xname(sc->sc_dev), port, tp->t_state, tp->t_flags); 605 #endif 606 splx(s); 607 ttyclose(tp); 608 #if 0 609 tty_detach(tp); 610 tty_free(tp); 611 sc->sc_tty[port] == NULL; 612 #endif 613 return 0; 614 } 615 616 static int 617 dcmread(dev_t dev, struct uio *uio, int flag) 618 { 619 int unit, board, port; 620 struct dcm_softc *sc; 621 struct tty *tp; 622 623 unit = DCMUNIT(dev); 624 board = DCMBOARD(unit); 625 port = DCMPORT(unit); 626 627 sc = device_lookup_private(&dcm_cd,board); 628 tp = sc->sc_tty[port]; 629 630 return (*tp->t_linesw->l_read)(tp, uio, flag); 631 } 632 633 static int 634 dcmwrite(dev_t dev, struct uio *uio, int flag) 635 { 636 int unit, board, port; 637 struct dcm_softc *sc; 638 struct tty *tp; 639 640 unit = DCMUNIT(dev); 641 board = DCMBOARD(unit); 642 port = DCMPORT(unit); 643 644 sc = device_lookup_private(&dcm_cd, board); 645 tp = sc->sc_tty[port]; 646 647 return (*tp->t_linesw->l_write)(tp, uio, flag); 648 } 649 650 static int 651 dcmpoll(dev_t dev, int events, struct lwp *l) 652 { 653 int unit, board, port; 654 struct dcm_softc *sc; 655 struct tty *tp; 656 657 unit = DCMUNIT(dev); 658 board = DCMBOARD(unit); 659 port = DCMPORT(unit); 660 661 sc = device_lookup_private(&dcm_cd, board); 662 tp = sc->sc_tty[port]; 663 664 return (*tp->t_linesw->l_poll)(tp, events, l); 665 } 666 667 static struct tty * 668 dcmtty(dev_t dev) 669 { 670 int unit, board, port; 671 struct dcm_softc *sc; 672 673 unit = DCMUNIT(dev); 674 board = DCMBOARD(unit); 675 port = DCMPORT(unit); 676 677 sc = device_lookup_private(&dcm_cd, board); 678 679 return sc->sc_tty[port]; 680 } 681 682 static int 683 dcmintr(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 = device_unit(sc->sc_dev); 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 device_xname(sc->sc_dev), 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_second - 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_second; 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 static void 791 dcmpint(struct dcm_softc *sc, int port, int code) 792 { 793 794 if (code & IT_SPEC) 795 dcmreadbuf(sc, port); 796 if (code & IT_TX) 797 dcmxint(sc, port); 798 } 799 800 static void 801 dcmrint(struct dcm_softc *sc) 802 { 803 int port; 804 805 for (port = 0; port < NDCMPORT; port++) 806 dcmreadbuf(sc, port); 807 } 808 809 static void 810 dcmreadbuf(struct dcm_softc *sc, int port) 811 { 812 struct dcmdevice *dcm = sc->sc_dcm; 813 struct dcmpreg *pp = dcm_preg(dcm, port); 814 struct dcmrfifo *fifo; 815 struct tty *tp; 816 int c, stat; 817 u_int head; 818 int nch = 0; 819 #ifdef DCMSTATS 820 struct dcmstats *dsp = &sc->sc_stats; 821 822 dsp->rints++; 823 #endif 824 tp = sc->sc_tty[port]; 825 if (tp == NULL) 826 return; 827 828 if ((tp->t_state & TS_ISOPEN) == 0) { 829 #ifdef KGDB 830 int maj; 831 832 maj = cdevsw_lookup_major(&dcm_cdevsw); 833 834 if ((makedev(maj, minor(tp->t_dev)) == kgdb_dev) && 835 (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) && 836 dcm->dcm_rfifos[3-port][head>>1].data_char == FRAME_START) { 837 pp->r_head = (head + 2) & RX_MASK; 838 kgdb_connect(0); /* trap into kgdb */ 839 return; 840 } 841 #endif /* KGDB */ 842 pp->r_head = pp->r_tail & RX_MASK; 843 return; 844 } 845 846 head = pp->r_head & RX_MASK; 847 fifo = &dcm->dcm_rfifos[3-port][head>>1]; 848 /* 849 * XXX upper bound on how many chars we will take in one swallow? 850 */ 851 while (head != (pp->r_tail & RX_MASK)) { 852 /* 853 * Get character/status and update head pointer as fast 854 * as possible to make room for more characters. 855 */ 856 c = fifo->data_char; 857 stat = fifo->data_stat; 858 head = (head + 2) & RX_MASK; 859 pp->r_head = head; 860 fifo = head ? fifo+1 : &dcm->dcm_rfifos[3-port][0]; 861 nch++; 862 863 #ifdef DEBUG 864 if (dcmdebug & DDB_INPUT) 865 printf("%s port %d: " 866 "dcmreadbuf: c%x('%c') s%x f%x h%x t%x\n", 867 device_xname(sc->sc_dev), 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: " 878 "dcmreadbuf: err: c%x('%c') s%x\n", 879 device_xname(sc->sc_dev), port, 880 stat, c&0xFF, c); 881 #endif 882 if (stat & (RD_BD | RD_FE)) 883 c |= TTY_FE; 884 else if (stat & RD_PE) 885 c |= TTY_PE; 886 else if (stat & RD_OVF) 887 log(LOG_WARNING, 888 "%s port %d: silo overflow\n", 889 device_xname(sc->sc_dev), port); 890 else if (stat & RD_OE) 891 log(LOG_WARNING, 892 "%s port %d: uart overflow\n", 893 device_xname(sc->sc_dev), port); 894 } 895 (*tp->t_linesw->l_rint)(c, tp); 896 } 897 sc->sc_scheme.dis_char += nch; 898 899 #ifdef DCMSTATS 900 dsp->rchars += nch; 901 if (nch <= DCMRBSIZE) 902 dsp->rsilo[nch]++; 903 else 904 dsp->rsilo[DCMRBSIZE+1]++; 905 #endif 906 } 907 908 static void 909 dcmxint(struct dcm_softc *sc, int port) 910 { 911 struct tty *tp; 912 913 tp = sc->sc_tty[port]; 914 if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0) 915 return; 916 917 tp->t_state &= ~TS_BUSY; 918 if (tp->t_state & TS_FLUSH) 919 tp->t_state &= ~TS_FLUSH; 920 (*tp->t_linesw->l_start)(tp); 921 } 922 923 static void 924 dcmmint(struct dcm_softc *sc, int port, int mcnd) 925 { 926 int delta; 927 struct tty *tp; 928 struct dcmdevice *dcm = sc->sc_dcm; 929 930 #ifdef DEBUG 931 if (dcmdebug & DDB_MODEM) 932 printf("%s port %d: dcmmint: mcnd %x mcndlast %x\n", 933 device_xname(sc->sc_dev), port, mcnd, 934 sc->sc_mcndlast[port]); 935 #endif 936 delta = mcnd ^ sc->sc_mcndlast[port]; 937 sc->sc_mcndlast[port] = mcnd; 938 tp = sc->sc_tty[port]; 939 if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0) 940 return; 941 942 if ((delta & MI_CTS) && (tp->t_state & TS_ISOPEN) && 943 (tp->t_cflag & CCTS_OFLOW)) { 944 if (mcnd & MI_CTS) { 945 tp->t_state &= ~TS_TTSTOP; 946 ttstart(tp); 947 } else 948 tp->t_state |= TS_TTSTOP; /* inline dcmstop */ 949 } 950 if (delta & MI_CD) { 951 if (mcnd & MI_CD) 952 (void)(*tp->t_linesw->l_modem)(tp, 1); 953 else if ((sc->sc_softCAR & (1 << port)) == 0 && 954 (*tp->t_linesw->l_modem)(tp, 0) == 0) { 955 sc->sc_modem[port]->mdmout = MO_OFF; 956 SEM_LOCK(dcm); 957 dcm->dcm_modemchng |= (1 << port); 958 dcm->dcm_cr |= CR_MODM; 959 SEM_UNLOCK(dcm); 960 DELAY(10); /* time to change lines */ 961 } 962 } 963 } 964 965 static int 966 dcmioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 967 { 968 struct dcm_softc *sc; 969 struct tty *tp; 970 struct dcmdevice *dcm; 971 int board, port, unit = DCMUNIT(dev); 972 int error, s; 973 974 port = DCMPORT(unit); 975 board = DCMBOARD(unit); 976 977 sc = device_lookup_private(&dcm_cd, board); 978 dcm = sc->sc_dcm; 979 tp = sc->sc_tty[port]; 980 981 #ifdef DEBUG 982 if (dcmdebug & DDB_IOCTL) 983 printf("%s port %d: dcmioctl: cmd %lx data %x flag %x\n", 984 device_xname(sc->sc_dev), port, cmd, *(int *)data, flag); 985 #endif 986 987 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 988 if (error != EPASSTHROUGH) 989 return error; 990 991 error = ttioctl(tp, cmd, data, flag, l); 992 if (error != EPASSTHROUGH) 993 return error; 994 995 switch (cmd) { 996 case TIOCSBRK: 997 /* 998 * Wait for transmitter buffer to empty 999 */ 1000 s = spltty(); 1001 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 1002 DELAY(DCM_USPERCH(tp->t_ospeed)); 1003 SEM_LOCK(dcm); 1004 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK; 1005 dcm->dcm_cr |= (1 << port); /* start break */ 1006 SEM_UNLOCK(dcm); 1007 splx(s); 1008 break; 1009 1010 case TIOCCBRK: 1011 SEM_LOCK(dcm); 1012 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK; 1013 dcm->dcm_cr |= (1 << port); /* end break */ 1014 SEM_UNLOCK(dcm); 1015 break; 1016 1017 case TIOCSDTR: 1018 (void) dcmmctl(dev, MO_ON, DMBIS); 1019 break; 1020 1021 case TIOCCDTR: 1022 (void) dcmmctl(dev, MO_ON, DMBIC); 1023 break; 1024 1025 case TIOCMSET: 1026 (void) dcmmctl(dev, *(int *)data, DMSET); 1027 break; 1028 1029 case TIOCMBIS: 1030 (void) dcmmctl(dev, *(int *)data, DMBIS); 1031 break; 1032 1033 case TIOCMBIC: 1034 (void) dcmmctl(dev, *(int *)data, DMBIC); 1035 break; 1036 1037 case TIOCMGET: 1038 *(int *)data = dcmmctl(dev, 0, DMGET); 1039 break; 1040 1041 case TIOCGFLAGS: { 1042 int bits = 0; 1043 1044 if ((sc->sc_softCAR & (1 << port))) 1045 bits |= TIOCFLAG_SOFTCAR; 1046 1047 if (tp->t_cflag & CLOCAL) 1048 bits |= TIOCFLAG_CLOCAL; 1049 1050 *(int *)data = bits; 1051 break; 1052 } 1053 1054 case TIOCSFLAGS: { 1055 int userbits; 1056 1057 if (kauth_authorize_device_tty(l->l_cred, 1058 KAUTH_DEVICE_TTY_PRIVSET, tp)) 1059 return (EPERM); 1060 1061 userbits = *(int *)data; 1062 1063 if ((userbits & TIOCFLAG_SOFTCAR) || 1064 ((sc->sc_flags & DCM_ISCONSOLE) && 1065 (port == DCMCONSPORT))) 1066 sc->sc_softCAR |= (1 << port); 1067 1068 if (userbits & TIOCFLAG_CLOCAL) 1069 tp->t_cflag |= CLOCAL; 1070 1071 break; 1072 } 1073 1074 default: 1075 return EPASSTHROUGH; 1076 } 1077 return 0; 1078 } 1079 1080 static int 1081 dcmparam(struct tty *tp, struct termios *t) 1082 { 1083 struct dcm_softc *sc; 1084 struct dcmdevice *dcm; 1085 int unit, board, port, mode, cflag = t->c_cflag; 1086 int ospeed = ttspeedtab(t->c_ospeed, dcmspeedtab); 1087 1088 unit = DCMUNIT(tp->t_dev); 1089 board = DCMBOARD(unit); 1090 port = DCMPORT(unit); 1091 1092 sc = device_lookup_private(&dcm_cd, board); 1093 dcm = sc->sc_dcm; 1094 1095 /* check requested parameters */ 1096 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 1097 return EINVAL; 1098 /* and copy to tty */ 1099 tp->t_ispeed = t->c_ispeed; 1100 tp->t_ospeed = t->c_ospeed; 1101 tp->t_cflag = cflag; 1102 if (ospeed == 0) { 1103 (void)dcmmctl(DCMUNIT(tp->t_dev), MO_OFF, DMSET); 1104 return 0; 1105 } 1106 1107 mode = 0; 1108 switch (cflag&CSIZE) { 1109 case CS5: 1110 mode = LC_5BITS; break; 1111 case CS6: 1112 mode = LC_6BITS; break; 1113 case CS7: 1114 mode = LC_7BITS; break; 1115 case CS8: 1116 mode = LC_8BITS; break; 1117 } 1118 if (cflag&PARENB) { 1119 if (cflag&PARODD) 1120 mode |= LC_PODD; 1121 else 1122 mode |= LC_PEVEN; 1123 } 1124 if (cflag&CSTOPB) 1125 mode |= LC_2STOP; 1126 else 1127 mode |= LC_1STOP; 1128 #ifdef DEBUG 1129 if (dcmdebug & DDB_PARAM) 1130 printf("%s port %d: " 1131 "dcmparam: cflag %x mode %x speed %d uperch %d\n", 1132 device_xname(sc->sc_dev), port, cflag, mode, tp->t_ospeed, 1133 DCM_USPERCH(tp->t_ospeed)); 1134 #endif 1135 1136 /* 1137 * Wait for transmitter buffer to empty. 1138 */ 1139 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 1140 DELAY(DCM_USPERCH(tp->t_ospeed)); 1141 /* 1142 * Make changes known to hardware. 1143 */ 1144 dcm->dcm_data[port].dcm_baud = ospeed; 1145 dcm->dcm_data[port].dcm_conf = mode; 1146 SEM_LOCK(dcm); 1147 dcm->dcm_cmdtab[port].dcm_data |= CT_CON; 1148 dcm->dcm_cr |= (1 << port); 1149 SEM_UNLOCK(dcm); 1150 /* 1151 * Delay for config change to take place. Weighted by baud. 1152 * XXX why do we do this? 1153 */ 1154 DELAY(16 * DCM_USPERCH(tp->t_ospeed)); 1155 return 0; 1156 } 1157 1158 static void 1159 dcmstart(struct tty *tp) 1160 { 1161 struct dcm_softc *sc; 1162 struct dcmdevice *dcm; 1163 struct dcmpreg *pp; 1164 struct dcmtfifo *fifo; 1165 char *bp; 1166 u_int head, tail, next; 1167 int unit, board, port, nch; 1168 char buf[16]; 1169 int s; 1170 #ifdef DCMSTATS 1171 struct dcmstats *dsp = &sc->sc_stats; 1172 int tch = 0; 1173 #endif 1174 1175 unit = DCMUNIT(tp->t_dev); 1176 board = DCMBOARD(unit); 1177 port = DCMPORT(unit); 1178 1179 sc = device_lookup_private(&dcm_cd, board); 1180 dcm = sc->sc_dcm; 1181 1182 s = spltty(); 1183 #ifdef DCMSTATS 1184 dsp->xints++; 1185 #endif 1186 #ifdef DEBUG 1187 if (dcmdebug & DDB_OUTPUT) 1188 printf("%s port %d: dcmstart: state %x flags %x outcc %d\n", 1189 device_xname(sc->sc_dev), port, tp->t_state, tp->t_flags, 1190 tp->t_outq.c_cc); 1191 #endif 1192 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 1193 goto out; 1194 if (!ttypull(tp)) { 1195 #ifdef DCMSTATS 1196 dsp->xempty++; 1197 #endif 1198 goto out; 1199 } 1200 1201 pp = dcm_preg(dcm, port); 1202 tail = pp->t_tail & TX_MASK; 1203 next = (tail + 1) & TX_MASK; 1204 head = pp->t_head & TX_MASK; 1205 if (head == next) 1206 goto out; 1207 fifo = &dcm->dcm_tfifos[3-port][tail]; 1208 again: 1209 nch = q_to_b(&tp->t_outq, buf, (head - next) & TX_MASK); 1210 #ifdef DCMSTATS 1211 tch += nch; 1212 #endif 1213 #ifdef DEBUG 1214 if (dcmdebug & DDB_OUTPUT) 1215 printf("\thead %x tail %x nch %d\n", head, tail, nch); 1216 #endif 1217 /* 1218 * Loop transmitting all the characters we can. 1219 */ 1220 for (bp = buf; --nch >= 0; bp++) { 1221 fifo->data_char = *bp; 1222 pp->t_tail = next; 1223 /* 1224 * If this is the first character, 1225 * get the hardware moving right now. 1226 */ 1227 if (bp == buf) { 1228 tp->t_state |= TS_BUSY; 1229 SEM_LOCK(dcm); 1230 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 1231 dcm->dcm_cr |= (1 << port); 1232 SEM_UNLOCK(dcm); 1233 } 1234 tail = next; 1235 fifo = tail ? fifo+1 : &dcm->dcm_tfifos[3-port][0]; 1236 next = (next + 1) & TX_MASK; 1237 } 1238 /* 1239 * Head changed while we were loading the buffer, 1240 * go back and load some more if we can. 1241 */ 1242 if (tp->t_outq.c_cc && head != (pp->t_head & TX_MASK)) { 1243 #ifdef DCMSTATS 1244 dsp->xrestarts++; 1245 #endif 1246 head = pp->t_head & TX_MASK; 1247 goto again; 1248 } 1249 1250 /* 1251 * Kick it one last time in case it finished while we were 1252 * loading the last bunch. 1253 */ 1254 if (bp > &buf[1]) { 1255 tp->t_state |= TS_BUSY; 1256 SEM_LOCK(dcm); 1257 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 1258 dcm->dcm_cr |= (1 << port); 1259 SEM_UNLOCK(dcm); 1260 } 1261 #ifdef DEBUG 1262 if (dcmdebug & DDB_INTR) 1263 printf("%s port %d: dcmstart: head %x tail %x outqcc %d\n", 1264 device_xname(sc->sc_dev), port, head, tail, 1265 tp->t_outq.c_cc); 1266 #endif 1267 out: 1268 #ifdef DCMSTATS 1269 dsp->xchars += tch; 1270 if (tch <= DCMXBSIZE) 1271 dsp->xsilo[tch]++; 1272 else 1273 dsp->xsilo[DCMXBSIZE+1]++; 1274 #endif 1275 splx(s); 1276 } 1277 1278 /* 1279 * Stop output on a line. 1280 */ 1281 static void 1282 dcmstop(struct tty *tp, int flag) 1283 { 1284 int s; 1285 1286 s = spltty(); 1287 if (tp->t_state & TS_BUSY) { 1288 /* XXX is there some way to safely stop transmission? */ 1289 if ((tp->t_state&TS_TTSTOP) == 0) 1290 tp->t_state |= TS_FLUSH; 1291 } 1292 splx(s); 1293 } 1294 1295 /* 1296 * Modem control 1297 */ 1298 int 1299 dcmmctl(dev_t dev, int bits, int how) 1300 { 1301 struct dcm_softc *sc; 1302 struct dcmdevice *dcm; 1303 int s, unit, brd, port, hit = 0; 1304 1305 unit = DCMUNIT(dev); 1306 brd = DCMBOARD(unit); 1307 port = DCMPORT(unit); 1308 1309 sc = device_lookup_private(&dcm_cd, brd); 1310 dcm = sc->sc_dcm; 1311 1312 #ifdef DEBUG 1313 if (dcmdebug & DDB_MODEM) 1314 printf("%s port %d: dcmmctl: bits 0x%x how %x\n", 1315 device_xname(sc->sc_dev), port, bits, how); 1316 #endif 1317 1318 s = spltty(); 1319 1320 switch (how) { 1321 case DMSET: 1322 sc->sc_modem[port]->mdmout = bits; 1323 hit++; 1324 break; 1325 1326 case DMBIS: 1327 sc->sc_modem[port]->mdmout |= bits; 1328 hit++; 1329 break; 1330 1331 case DMBIC: 1332 sc->sc_modem[port]->mdmout &= ~bits; 1333 hit++; 1334 break; 1335 1336 case DMGET: 1337 bits = sc->sc_modem[port]->mdmin; 1338 if (sc->sc_flags & DCM_STDDCE) 1339 bits = hp2dce_in(bits); 1340 break; 1341 } 1342 if (hit) { 1343 SEM_LOCK(dcm); 1344 dcm->dcm_modemchng |= 1<<(unit & 3); 1345 dcm->dcm_cr |= CR_MODM; 1346 SEM_UNLOCK(dcm); 1347 DELAY(10); /* delay until done */ 1348 splx(s); 1349 } 1350 return bits; 1351 } 1352 1353 /* 1354 * Set board to either interrupt per-character or at a fixed interval. 1355 */ 1356 static void 1357 dcmsetischeme(int brd, int flags) 1358 { 1359 struct dcm_softc *sc = device_lookup_private(&dcm_cd, brd); 1360 struct dcmdevice *dcm = sc->sc_dcm; 1361 struct dcmischeme *dis = &sc->sc_scheme; 1362 int i; 1363 u_char mask; 1364 int perchar = flags & DIS_PERCHAR; 1365 1366 #ifdef DEBUG 1367 if (dcmdebug & DDB_INTSCHM) 1368 printf("%s: dcmsetischeme(%d): cur %d, ints %d, chars %d\n", 1369 device_xname(sc->sc_dev), perchar, dis->dis_perchar, 1370 dis->dis_intr, dis->dis_char); 1371 if ((flags & DIS_RESET) == 0 && perchar == dis->dis_perchar) { 1372 printf("%s: dcmsetischeme: redundent request %d\n", 1373 device_xname(sc->sc_dev), perchar); 1374 return; 1375 } 1376 #endif 1377 /* 1378 * If perchar is non-zero, we enable interrupts on all characters 1379 * otherwise we disable perchar interrupts and use periodic 1380 * polling interrupts. 1381 */ 1382 dis->dis_perchar = perchar; 1383 mask = perchar ? 0xf : 0x0; 1384 for (i = 0; i < 256; i++) 1385 dcm->dcm_bmap[i].data_data = mask; 1386 /* 1387 * Don't slow down tandem mode, interrupt on flow control 1388 * chars for any port on the board. 1389 */ 1390 if (!perchar) { 1391 struct tty *tp; 1392 int c; 1393 1394 for (i = 0; i < NDCMPORT; i++) { 1395 tp = sc->sc_tty[i]; 1396 1397 c = tty_getctrlchar(tp, VSTART); 1398 if (c != _POSIX_VDISABLE) 1399 dcm->dcm_bmap[c].data_data |= (1 << i); 1400 c = tty_getctrlchar(tp, VSTOP); 1401 if (c != _POSIX_VDISABLE) 1402 dcm->dcm_bmap[c].data_data |= (1 << i); 1403 } 1404 } 1405 /* 1406 * Board starts with timer disabled so if first call is to 1407 * set perchar mode then we don't want to toggle the timer. 1408 */ 1409 if (flags == (DIS_RESET|DIS_PERCHAR)) 1410 return; 1411 /* 1412 * Toggle card 16.7ms interrupts (we first make sure that card 1413 * has cleared the bit so it will see the toggle). 1414 */ 1415 while (dcm->dcm_cr & CR_TIMER) 1416 ; 1417 SEM_LOCK(dcm); 1418 dcm->dcm_cr |= CR_TIMER; 1419 SEM_UNLOCK(dcm); 1420 } 1421 1422 static void 1423 dcminit(struct dcmdevice *dcm, int port, int rate) 1424 { 1425 int s, mode; 1426 1427 mode = LC_8BITS | LC_1STOP; 1428 1429 s = splhigh(); 1430 1431 /* 1432 * Wait for transmitter buffer to empty. 1433 */ 1434 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 1435 DELAY(DCM_USPERCH(rate)); 1436 1437 /* 1438 * Make changes known to hardware. 1439 */ 1440 dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab); 1441 dcm->dcm_data[port].dcm_conf = mode; 1442 SEM_LOCK(dcm); 1443 dcm->dcm_cmdtab[port].dcm_data |= CT_CON; 1444 dcm->dcm_cr |= (1 << port); 1445 SEM_UNLOCK(dcm); 1446 1447 /* 1448 * Delay for config change to take place. Weighted by baud. 1449 * XXX why do we do this? 1450 */ 1451 DELAY(16 * DCM_USPERCH(rate)); 1452 splx(s); 1453 } 1454 1455 /* 1456 * Empirically derived self-test magic 1457 */ 1458 static int 1459 dcmselftest(struct dcm_softc *sc) 1460 { 1461 struct dcmdevice *dcm = sc->sc_dcm; 1462 int timo = 0; 1463 int s, rv; 1464 1465 rv = 1; 1466 1467 s = splhigh(); 1468 dcm->dcm_rsid = DCMRS; 1469 DELAY(50000); /* 5000 is not long enough */ 1470 dcm->dcm_rsid = 0; 1471 dcm->dcm_ic = IC_IE; 1472 dcm->dcm_cr = CR_SELFT; 1473 while ((dcm->dcm_ic & IC_IR) == 0) { 1474 if (++timo == 20000) 1475 goto out; 1476 DELAY(1); 1477 } 1478 DELAY(50000); /* XXX why is this needed ???? */ 1479 while ((dcm->dcm_iir & IIR_SELFT) == 0) { 1480 if (++timo == 400000) 1481 goto out; 1482 DELAY(1); 1483 } 1484 DELAY(50000); /* XXX why is this needed ???? */ 1485 if (dcm->dcm_stcon != ST_OK) { 1486 #if 0 1487 if (hd->hp_args->hw_sc != conscode) 1488 aprint_error_dev(sc->sc_dev, "self test failed: %x\n", 1489 dcm->dcm_stcon); 1490 #endif 1491 goto out; 1492 } 1493 dcm->dcm_ic = IC_ID; 1494 rv = 0; 1495 1496 out: 1497 splx(s); 1498 return rv; 1499 } 1500 1501 /* 1502 * Following are all routines needed for DCM to act as console 1503 */ 1504 1505 int 1506 dcmcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode) 1507 { 1508 bus_space_handle_t bsh; 1509 void *va; 1510 struct dcmdevice *dcm; 1511 int maj; 1512 1513 if (bus_space_map(bst, addr, DIOCSIZE, 0, &bsh)) 1514 return 1; 1515 1516 va = bus_space_vaddr(bst, bsh); 1517 dcm = (struct dcmdevice *)va; 1518 1519 switch (dcm->dcm_rsid) { 1520 #ifdef CONSCODE 1521 case DCMID: 1522 #endif 1523 case DCMID|DCMCON: 1524 break; 1525 default: 1526 goto error; 1527 } 1528 1529 dcminit(dcm, DCMCONSPORT, dcmdefaultrate); 1530 dcmconsinit = 1; 1531 dcmconscode = scode; 1532 dcm_cn = dcm; 1533 1534 /* locate the major number */ 1535 maj = cdevsw_lookup_major(&dcm_cdevsw); 1536 1537 /* initialize required fields */ 1538 cn_tab = &dcm_cons; 1539 cn_tab->cn_dev = makedev(maj, 0); 1540 1541 #ifdef KGDB_CHEAT 1542 /* XXX this needs to be fixed. */ 1543 /* 1544 * This doesn't currently work, at least not with ite consoles; 1545 * the console hasn't been initialized yet. 1546 */ 1547 if (major(kgdb_dev) == maj && 1548 DCMBOARD(DCMUNIT(kgdb_dev)) == DCMBOARD(unit)) { 1549 dcminit(dcm_cn, DCMPORT(DCMUNIT(kgdb_dev)), kgdb_rate); 1550 if (kgdb_debug_init) { 1551 /* 1552 * We assume that console is ready for us... 1553 * this assumes that a dca or ite console 1554 * has been selected already and will init 1555 * on the first putc. 1556 */ 1557 printf("dcm%d: ", DCMUNIT(kgdb_dev)); 1558 kgdb_connect(1); 1559 } 1560 } 1561 #endif 1562 1563 1564 return 0; 1565 1566 error: 1567 bus_space_unmap(bst, bsh, DIOCSIZE); 1568 return 1; 1569 } 1570 1571 /* ARGSUSED */ 1572 static int 1573 dcmcngetc(dev_t dev) 1574 { 1575 struct dcmrfifo *fifo; 1576 struct dcmpreg *pp; 1577 u_int head; 1578 int s, c, stat; 1579 1580 pp = dcm_preg(dcm_cn, DCMCONSPORT); 1581 1582 s = splhigh(); 1583 head = pp->r_head & RX_MASK; 1584 fifo = &dcm_cn->dcm_rfifos[3-DCMCONSPORT][head>>1]; 1585 while (head == (pp->r_tail & RX_MASK)) 1586 ; 1587 /* 1588 * If board interrupts are enabled, just let our received char 1589 * interrupt through in case some other port on the board was 1590 * busy. Otherwise we must clear the interrupt. 1591 */ 1592 SEM_LOCK(dcm_cn); 1593 if ((dcm_cn->dcm_ic & IC_IE) == 0) 1594 stat = dcm_cn->dcm_iir; 1595 SEM_UNLOCK(dcm_cn); 1596 c = fifo->data_char; 1597 stat = fifo->data_stat; 1598 pp->r_head = (head + 2) & RX_MASK; 1599 __USE(stat); 1600 splx(s); 1601 return c; 1602 } 1603 1604 /* 1605 * Console kernel output character routine. 1606 */ 1607 /* ARGSUSED */ 1608 static void 1609 dcmcnputc(dev_t dev, int c) 1610 { 1611 struct dcmpreg *pp; 1612 unsigned tail; 1613 int s, stat; 1614 1615 pp = dcm_preg(dcm_cn, DCMCONSPORT); 1616 1617 s = splhigh(); 1618 #ifdef KGDB 1619 if (dev != kgdb_dev) 1620 #endif 1621 if (dcmconsinit == 0) { 1622 dcminit(dcm_cn, DCMCONSPORT, dcmdefaultrate); 1623 dcmconsinit = 1; 1624 } 1625 tail = pp->t_tail & TX_MASK; 1626 while (tail != (pp->t_head & TX_MASK)) 1627 continue; 1628 dcm_cn->dcm_tfifos[3-DCMCONSPORT][tail].data_char = c; 1629 pp->t_tail = tail = (tail + 1) & TX_MASK; 1630 SEM_LOCK(dcm_cn); 1631 dcm_cn->dcm_cmdtab[DCMCONSPORT].dcm_data |= CT_TX; 1632 dcm_cn->dcm_cr |= (1 << DCMCONSPORT); 1633 SEM_UNLOCK(dcm_cn); 1634 while (tail != (pp->t_head & TX_MASK)) 1635 continue; 1636 /* 1637 * If board interrupts are enabled, just let our completion 1638 * interrupt through in case some other port on the board 1639 * was busy. Otherwise we must clear the interrupt. 1640 */ 1641 if ((dcm_cn->dcm_ic & IC_IE) == 0) { 1642 SEM_LOCK(dcm_cn); 1643 stat = dcm_cn->dcm_iir; 1644 SEM_UNLOCK(dcm_cn); 1645 } 1646 __USE(stat); 1647 splx(s); 1648 } 1649