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