1 /* $NetBSD: dcm.c,v 1.76 2006/10/01 16:50:11 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.76 2006/10/01 16:50:11 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 (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, caddr_t 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 (tp->t_outq.c_cc <= tp->t_lowat) { 1225 if (tp->t_state&TS_ASLEEP) { 1226 tp->t_state &= ~TS_ASLEEP; 1227 wakeup((caddr_t)&tp->t_outq); 1228 } 1229 selwakeup(&tp->t_wsel); 1230 } 1231 if (tp->t_outq.c_cc == 0) { 1232 #ifdef DCMSTATS 1233 dsp->xempty++; 1234 #endif 1235 goto out; 1236 } 1237 1238 pp = dcm_preg(dcm, port); 1239 tail = pp->t_tail & TX_MASK; 1240 next = (tail + 1) & TX_MASK; 1241 head = pp->t_head & TX_MASK; 1242 if (head == next) 1243 goto out; 1244 fifo = &dcm->dcm_tfifos[3-port][tail]; 1245 again: 1246 nch = q_to_b(&tp->t_outq, buf, (head - next) & TX_MASK); 1247 #ifdef DCMSTATS 1248 tch += nch; 1249 #endif 1250 #ifdef DEBUG 1251 if (dcmdebug & DDB_OUTPUT) 1252 printf("\thead %x tail %x nch %d\n", head, tail, nch); 1253 #endif 1254 /* 1255 * Loop transmitting all the characters we can. 1256 */ 1257 for (bp = buf; --nch >= 0; bp++) { 1258 fifo->data_char = *bp; 1259 pp->t_tail = next; 1260 /* 1261 * If this is the first character, 1262 * get the hardware moving right now. 1263 */ 1264 if (bp == buf) { 1265 tp->t_state |= TS_BUSY; 1266 SEM_LOCK(dcm); 1267 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 1268 dcm->dcm_cr |= (1 << port); 1269 SEM_UNLOCK(dcm); 1270 } 1271 tail = next; 1272 fifo = tail ? fifo+1 : &dcm->dcm_tfifos[3-port][0]; 1273 next = (next + 1) & TX_MASK; 1274 } 1275 /* 1276 * Head changed while we were loading the buffer, 1277 * go back and load some more if we can. 1278 */ 1279 if (tp->t_outq.c_cc && head != (pp->t_head & TX_MASK)) { 1280 #ifdef DCMSTATS 1281 dsp->xrestarts++; 1282 #endif 1283 head = pp->t_head & TX_MASK; 1284 goto again; 1285 } 1286 1287 /* 1288 * Kick it one last time in case it finished while we were 1289 * loading the last bunch. 1290 */ 1291 if (bp > &buf[1]) { 1292 tp->t_state |= TS_BUSY; 1293 SEM_LOCK(dcm); 1294 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 1295 dcm->dcm_cr |= (1 << port); 1296 SEM_UNLOCK(dcm); 1297 } 1298 #ifdef DEBUG 1299 if (dcmdebug & DDB_INTR) 1300 printf("%s port %d: dcmstart: head %x tail %x outqcc %d\n", 1301 sc->sc_dev.dv_xname, port, head, tail, tp->t_outq.c_cc); 1302 #endif 1303 out: 1304 #ifdef DCMSTATS 1305 dsp->xchars += tch; 1306 if (tch <= DCMXBSIZE) 1307 dsp->xsilo[tch]++; 1308 else 1309 dsp->xsilo[DCMXBSIZE+1]++; 1310 #endif 1311 splx(s); 1312 } 1313 1314 /* 1315 * Stop output on a line. 1316 */ 1317 static void 1318 dcmstop(struct tty *tp, int flag) 1319 { 1320 int s; 1321 1322 s = spltty(); 1323 if (tp->t_state & TS_BUSY) { 1324 /* XXX is there some way to safely stop transmission? */ 1325 if ((tp->t_state&TS_TTSTOP) == 0) 1326 tp->t_state |= TS_FLUSH; 1327 } 1328 splx(s); 1329 } 1330 1331 /* 1332 * Modem control 1333 */ 1334 int 1335 dcmmctl(dev_t dev, int bits, int how) 1336 { 1337 struct dcm_softc *sc; 1338 struct dcmdevice *dcm; 1339 int s, unit, brd, port, hit = 0; 1340 1341 unit = DCMUNIT(dev); 1342 brd = DCMBOARD(unit); 1343 port = DCMPORT(unit); 1344 1345 sc = dcm_cd.cd_devs[brd]; 1346 dcm = sc->sc_dcm; 1347 1348 #ifdef DEBUG 1349 if (dcmdebug & DDB_MODEM) 1350 printf("%s port %d: dcmmctl: bits 0x%x how %x\n", 1351 sc->sc_dev.dv_xname, port, bits, how); 1352 #endif 1353 1354 s = spltty(); 1355 1356 switch (how) { 1357 case DMSET: 1358 sc->sc_modem[port]->mdmout = bits; 1359 hit++; 1360 break; 1361 1362 case DMBIS: 1363 sc->sc_modem[port]->mdmout |= bits; 1364 hit++; 1365 break; 1366 1367 case DMBIC: 1368 sc->sc_modem[port]->mdmout &= ~bits; 1369 hit++; 1370 break; 1371 1372 case DMGET: 1373 bits = sc->sc_modem[port]->mdmin; 1374 if (sc->sc_flags & DCM_STDDCE) 1375 bits = hp2dce_in(bits); 1376 break; 1377 } 1378 if (hit) { 1379 SEM_LOCK(dcm); 1380 dcm->dcm_modemchng |= 1<<(unit & 3); 1381 dcm->dcm_cr |= CR_MODM; 1382 SEM_UNLOCK(dcm); 1383 DELAY(10); /* delay until done */ 1384 splx(s); 1385 } 1386 return bits; 1387 } 1388 1389 /* 1390 * Set board to either interrupt per-character or at a fixed interval. 1391 */ 1392 static void 1393 dcmsetischeme(int brd, int flags) 1394 { 1395 struct dcm_softc *sc = dcm_cd.cd_devs[brd]; 1396 struct dcmdevice *dcm = sc->sc_dcm; 1397 struct dcmischeme *dis = &sc->sc_scheme; 1398 int i; 1399 u_char mask; 1400 int perchar = flags & DIS_PERCHAR; 1401 1402 #ifdef DEBUG 1403 if (dcmdebug & DDB_INTSCHM) 1404 printf("%s: dcmsetischeme(%d): cur %d, ints %d, chars %d\n", 1405 sc->sc_dev.dv_xname, perchar, dis->dis_perchar, 1406 dis->dis_intr, dis->dis_char); 1407 if ((flags & DIS_RESET) == 0 && perchar == dis->dis_perchar) { 1408 printf("%s: dcmsetischeme: redundent request %d\n", 1409 sc->sc_dev.dv_xname, perchar); 1410 return; 1411 } 1412 #endif 1413 /* 1414 * If perchar is non-zero, we enable interrupts on all characters 1415 * otherwise we disable perchar interrupts and use periodic 1416 * polling interrupts. 1417 */ 1418 dis->dis_perchar = perchar; 1419 mask = perchar ? 0xf : 0x0; 1420 for (i = 0; i < 256; i++) 1421 dcm->dcm_bmap[i].data_data = mask; 1422 /* 1423 * Don't slow down tandem mode, interrupt on flow control 1424 * chars for any port on the board. 1425 */ 1426 if (!perchar) { 1427 struct tty *tp; 1428 int c; 1429 1430 for (i = 0; i < NDCMPORT; i++) { 1431 tp = sc->sc_tty[i]; 1432 1433 if ((c = tp->t_cc[VSTART]) != _POSIX_VDISABLE) 1434 dcm->dcm_bmap[c].data_data |= (1 << i); 1435 if ((c = tp->t_cc[VSTOP]) != _POSIX_VDISABLE) 1436 dcm->dcm_bmap[c].data_data |= (1 << i); 1437 } 1438 } 1439 /* 1440 * Board starts with timer disabled so if first call is to 1441 * set perchar mode then we don't want to toggle the timer. 1442 */ 1443 if (flags == (DIS_RESET|DIS_PERCHAR)) 1444 return; 1445 /* 1446 * Toggle card 16.7ms interrupts (we first make sure that card 1447 * has cleared the bit so it will see the toggle). 1448 */ 1449 while (dcm->dcm_cr & CR_TIMER) 1450 ; 1451 SEM_LOCK(dcm); 1452 dcm->dcm_cr |= CR_TIMER; 1453 SEM_UNLOCK(dcm); 1454 } 1455 1456 static void 1457 dcminit(struct dcmdevice *dcm, int port, int rate) 1458 { 1459 int s, mode; 1460 1461 mode = LC_8BITS | LC_1STOP; 1462 1463 s = splhigh(); 1464 1465 /* 1466 * Wait for transmitter buffer to empty. 1467 */ 1468 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 1469 DELAY(DCM_USPERCH(rate)); 1470 1471 /* 1472 * Make changes known to hardware. 1473 */ 1474 dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab); 1475 dcm->dcm_data[port].dcm_conf = mode; 1476 SEM_LOCK(dcm); 1477 dcm->dcm_cmdtab[port].dcm_data |= CT_CON; 1478 dcm->dcm_cr |= (1 << port); 1479 SEM_UNLOCK(dcm); 1480 1481 /* 1482 * Delay for config change to take place. Weighted by baud. 1483 * XXX why do we do this? 1484 */ 1485 DELAY(16 * DCM_USPERCH(rate)); 1486 splx(s); 1487 } 1488 1489 /* 1490 * Empirically derived self-test magic 1491 */ 1492 static int 1493 dcmselftest(struct dcm_softc *sc) 1494 { 1495 struct dcmdevice *dcm = sc->sc_dcm; 1496 int timo = 0; 1497 int s, rv; 1498 1499 rv = 1; 1500 1501 s = splhigh(); 1502 dcm->dcm_rsid = DCMRS; 1503 DELAY(50000); /* 5000 is not long enough */ 1504 dcm->dcm_rsid = 0; 1505 dcm->dcm_ic = IC_IE; 1506 dcm->dcm_cr = CR_SELFT; 1507 while ((dcm->dcm_ic & IC_IR) == 0) { 1508 if (++timo == 20000) 1509 goto out; 1510 DELAY(1); 1511 } 1512 DELAY(50000); /* XXX why is this needed ???? */ 1513 while ((dcm->dcm_iir & IIR_SELFT) == 0) { 1514 if (++timo == 400000) 1515 goto out; 1516 DELAY(1); 1517 } 1518 DELAY(50000); /* XXX why is this needed ???? */ 1519 if (dcm->dcm_stcon != ST_OK) { 1520 #if 0 1521 if (hd->hp_args->hw_sc != conscode) 1522 printf("dcm%d: self test failed: %x\n", 1523 brd, dcm->dcm_stcon); 1524 #endif 1525 goto out; 1526 } 1527 dcm->dcm_ic = IC_ID; 1528 rv = 0; 1529 1530 out: 1531 splx(s); 1532 return rv; 1533 } 1534 1535 /* 1536 * Following are all routines needed for DCM to act as console 1537 */ 1538 1539 int 1540 dcmcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode) 1541 { 1542 bus_space_handle_t bsh; 1543 caddr_t va; 1544 struct dcmdevice *dcm; 1545 int maj; 1546 1547 if (bus_space_map(bst, addr, DIOCSIZE, 0, &bsh)) 1548 return 1; 1549 1550 va = bus_space_vaddr(bst, bsh); 1551 dcm = (struct dcmdevice *)va; 1552 1553 switch (dcm->dcm_rsid) { 1554 #ifdef CONSCODE 1555 case DCMID: 1556 #endif 1557 case DCMID|DCMCON: 1558 break; 1559 default: 1560 goto error; 1561 } 1562 1563 dcminit(dcm, DCMCONSPORT, dcmdefaultrate); 1564 dcmconsinit = 1; 1565 dcmconscode = scode; 1566 dcm_cn = dcm; 1567 1568 /* locate the major number */ 1569 maj = cdevsw_lookup_major(&dcm_cdevsw); 1570 1571 /* initialize required fields */ 1572 cn_tab = &dcm_cons; 1573 cn_tab->cn_dev = makedev(maj, 0); 1574 1575 #ifdef KGDB_CHEAT 1576 /* XXX this needs to be fixed. */ 1577 /* 1578 * This doesn't currently work, at least not with ite consoles; 1579 * the console hasn't been initialized yet. 1580 */ 1581 if (major(kgdb_dev) == maj && 1582 DCMBOARD(DCMUNIT(kgdb_dev)) == DCMBOARD(unit)) { 1583 dcminit(dcm_cn, DCMPORT(DCMUNIT(kgdb_dev)), kgdb_rate); 1584 if (kgdb_debug_init) { 1585 /* 1586 * We assume that console is ready for us... 1587 * this assumes that a dca or ite console 1588 * has been selected already and will init 1589 * on the first putc. 1590 */ 1591 printf("dcm%d: ", DCMUNIT(kgdb_dev)); 1592 kgdb_connect(1); 1593 } 1594 } 1595 #endif 1596 1597 1598 return 0; 1599 1600 error: 1601 bus_space_unmap(bst, bsh, DIOCSIZE); 1602 return 1; 1603 } 1604 1605 /* ARGSUSED */ 1606 static int 1607 dcmcngetc(dev_t dev) 1608 { 1609 struct dcmrfifo *fifo; 1610 struct dcmpreg *pp; 1611 u_int head; 1612 int s, c, stat; 1613 1614 pp = dcm_preg(dcm_cn, DCMCONSPORT); 1615 1616 s = splhigh(); 1617 head = pp->r_head & RX_MASK; 1618 fifo = &dcm_cn->dcm_rfifos[3-DCMCONSPORT][head>>1]; 1619 while (head == (pp->r_tail & RX_MASK)) 1620 ; 1621 /* 1622 * If board interrupts are enabled, just let our received char 1623 * interrupt through in case some other port on the board was 1624 * busy. Otherwise we must clear the interrupt. 1625 */ 1626 SEM_LOCK(dcm_cn); 1627 if ((dcm_cn->dcm_ic & IC_IE) == 0) 1628 stat = dcm_cn->dcm_iir; 1629 SEM_UNLOCK(dcm_cn); 1630 c = fifo->data_char; 1631 stat = fifo->data_stat; 1632 pp->r_head = (head + 2) & RX_MASK; 1633 splx(s); 1634 return c; 1635 } 1636 1637 /* 1638 * Console kernel output character routine. 1639 */ 1640 /* ARGSUSED */ 1641 static void 1642 dcmcnputc(dev_t dev, int c) 1643 { 1644 struct dcmpreg *pp; 1645 unsigned tail; 1646 int s, stat; 1647 1648 pp = dcm_preg(dcm_cn, DCMCONSPORT); 1649 1650 s = splhigh(); 1651 #ifdef KGDB 1652 if (dev != kgdb_dev) 1653 #endif 1654 if (dcmconsinit == 0) { 1655 dcminit(dcm_cn, DCMCONSPORT, dcmdefaultrate); 1656 dcmconsinit = 1; 1657 } 1658 tail = pp->t_tail & TX_MASK; 1659 while (tail != (pp->t_head & TX_MASK)) 1660 ; 1661 dcm_cn->dcm_tfifos[3-DCMCONSPORT][tail].data_char = c; 1662 pp->t_tail = tail = (tail + 1) & TX_MASK; 1663 SEM_LOCK(dcm_cn); 1664 dcm_cn->dcm_cmdtab[DCMCONSPORT].dcm_data |= CT_TX; 1665 dcm_cn->dcm_cr |= (1 << DCMCONSPORT); 1666 SEM_UNLOCK(dcm_cn); 1667 while (tail != (pp->t_head & TX_MASK)) 1668 ; 1669 /* 1670 * If board interrupts are enabled, just let our completion 1671 * interrupt through in case some other port on the board 1672 * was busy. Otherwise we must clear the interrupt. 1673 */ 1674 if ((dcm_cn->dcm_ic & IC_IE) == 0) { 1675 SEM_LOCK(dcm_cn); 1676 stat = dcm_cn->dcm_iir; 1677 SEM_UNLOCK(dcm_cn); 1678 } 1679 splx(s); 1680 } 1681