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