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