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