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