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