1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1982, 1986, 1990, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from Utah: $Hdr: dcm.c 1.29 92/01/21$ 13 * 14 * @(#)dcm.c 8.5 (Berkeley) 01/09/95 15 */ 16 17 /* 18 * TODO: 19 * Timeouts 20 * Test console support. 21 */ 22 23 #include "dcm.h" 24 #if NDCM > 0 25 /* 26 * 98642/MUX 27 */ 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/ioctl.h> 31 #include <sys/proc.h> 32 #include <sys/tty.h> 33 #include <sys/conf.h> 34 #include <sys/file.h> 35 #include <sys/uio.h> 36 #include <sys/kernel.h> 37 #include <sys/syslog.h> 38 #include <sys/time.h> 39 40 #include <hp/dev/device.h> 41 42 #include <hp300/dev/dcmreg.h> 43 #include <machine/cpu.h> 44 #include <hp300/hp300/isr.h> 45 46 #ifndef DEFAULT_BAUD_RATE 47 #define DEFAULT_BAUD_RATE 9600 48 #endif 49 50 int dcmprobe(), dcmintr(), dcmparam(); 51 void dcmstart(); 52 struct driver dcmdriver = { 53 dcmprobe, "dcm", 54 }; 55 56 #define NDCMLINE (NDCM*4) 57 58 struct tty dcm_tty[NDCMLINE]; 59 struct modemreg *dcm_modem[NDCMLINE]; 60 char mcndlast[NDCMLINE]; /* XXX last modem status for line */ 61 int ndcm = NDCMLINE; 62 63 int dcm_active; 64 int dcmsoftCAR[NDCM]; 65 struct dcmdevice *dcm_addr[NDCM]; 66 struct isr dcmisr[NDCM]; 67 68 struct speedtab dcmspeedtab[] = { 69 0, BR_0, 70 50, BR_50, 71 75, BR_75, 72 110, BR_110, 73 134, BR_134, 74 150, BR_150, 75 300, BR_300, 76 600, BR_600, 77 1200, BR_1200, 78 1800, BR_1800, 79 2400, BR_2400, 80 4800, BR_4800, 81 9600, BR_9600, 82 19200, BR_19200, 83 38400, BR_38400, 84 -1, -1 85 }; 86 87 /* u-sec per character based on baudrate (assumes 1 start/8 data/1 stop bit) */ 88 #define DCM_USPERCH(s) (10000000 / (s)) 89 90 /* 91 * Per board interrupt scheme. 16.7ms is the polling interrupt rate 92 * (16.7ms is about 550 baud, 38.4k is 72 chars in 16.7ms). 93 */ 94 #define DIS_TIMER 0 95 #define DIS_PERCHAR 1 96 #define DIS_RESET 2 97 98 int dcmistype = -1; /* -1 == dynamic, 0 == timer, 1 == perchar */ 99 int dcminterval = 5; /* interval (secs) between checks */ 100 struct dcmischeme { 101 int dis_perchar; /* non-zero if interrupting per char */ 102 long dis_time; /* last time examined */ 103 int dis_intr; /* recv interrupts during last interval */ 104 int dis_char; /* characters read during last interval */ 105 } dcmischeme[NDCM]; 106 107 /* 108 * Console support 109 */ 110 #ifdef DCMCONSOLE 111 int dcmconsole = DCMCONSOLE; 112 #else 113 int dcmconsole = -1; 114 #endif 115 int dcmconsinit; 116 int dcmdefaultrate = DEFAULT_BAUD_RATE; 117 int dcmconbrdbusy = 0; 118 int dcmmajor; 119 extern struct tty *constty; 120 121 #ifdef KGDB 122 /* 123 * Kernel GDB support 124 */ 125 #include <machine/remote-sl.h> 126 127 extern dev_t kgdb_dev; 128 extern int kgdb_rate; 129 extern int kgdb_debug_init; 130 #endif 131 132 /* #define DCMSTATS */ 133 134 #ifdef DEBUG 135 int dcmdebug = 0x0; 136 #define DDB_SIOERR 0x01 137 #define DDB_PARAM 0x02 138 #define DDB_INPUT 0x04 139 #define DDB_OUTPUT 0x08 140 #define DDB_INTR 0x10 141 #define DDB_IOCTL 0x20 142 #define DDB_INTSCHM 0x40 143 #define DDB_MODEM 0x80 144 #define DDB_OPENCLOSE 0x100 145 #endif 146 147 #ifdef DCMSTATS 148 #define DCMRBSIZE 94 149 #define DCMXBSIZE 24 150 151 struct dcmstats { 152 long xints; /* # of xmit ints */ 153 long xchars; /* # of xmit chars */ 154 long xempty; /* times outq is empty in dcmstart */ 155 long xrestarts; /* times completed while xmitting */ 156 long rints; /* # of recv ints */ 157 long rchars; /* # of recv chars */ 158 long xsilo[DCMXBSIZE+2]; /* times this many chars xmit on one int */ 159 long rsilo[DCMRBSIZE+2]; /* times this many chars read on one int */ 160 } dcmstats[NDCM]; 161 #endif 162 163 #define UNIT(x) minor(x) 164 #define BOARD(x) (((x) >> 2) & 0x3f) 165 #define PORT(x) ((x) & 3) 166 #define MKUNIT(b,p) (((b) << 2) | (p)) 167 168 /* 169 * Conversion from "HP DCE" to almost-normal DCE: on the 638 8-port mux, 170 * the distribution panel uses "HP DCE" conventions. If requested via 171 * the device flags, we swap the inputs to something closer to normal DCE, 172 * allowing a straight-through cable to a DTE or a reversed cable 173 * to a DCE (reversing 2-3, 4-5, 8-20 and leaving 6 unconnected; 174 * this gets "DCD" on pin 20 and "CTS" on 4, but doesn't connect 175 * DSR or make RTS work, though). The following gives the full 176 * details of a cable from this mux panel to a modem: 177 * 178 * HP modem 179 * name pin pin name 180 * HP inputs: 181 * "Rx" 2 3 Tx 182 * CTS 4 5 CTS (only needed for CCTS_OFLOW) 183 * DCD 20 8 DCD 184 * "DSR" 9 6 DSR (unneeded) 185 * RI 22 22 RI (unneeded) 186 * 187 * HP outputs: 188 * "Tx" 3 2 Rx 189 * "DTR" 6 not connected 190 * "RTS" 8 20 DTR 191 * "SR" 23 4 RTS (often not needed) 192 */ 193 #define FLAG_STDDCE 0x10 /* map inputs if this bit is set in flags */ 194 #define hp2dce_in(ibits) (iconv[(ibits) & 0xf]) 195 static char iconv[16] = { 196 0, MI_DM, MI_CTS, MI_CTS|MI_DM, 197 MI_CD, MI_CD|MI_DM, MI_CD|MI_CTS, MI_CD|MI_CTS|MI_DM, 198 MI_RI, MI_RI|MI_DM, MI_RI|MI_CTS, MI_RI|MI_CTS|MI_DM, 199 MI_RI|MI_CD, MI_RI|MI_CD|MI_DM, MI_RI|MI_CD|MI_CTS, 200 MI_RI|MI_CD|MI_CTS|MI_DM 201 }; 202 203 dcmprobe(hd) 204 register struct hp_device *hd; 205 { 206 register struct dcmdevice *dcm; 207 register int i; 208 register int timo = 0; 209 int s, brd, isconsole, mbits; 210 211 dcm = (struct dcmdevice *)hd->hp_addr; 212 if ((dcm->dcm_rsid & 0x1f) != DCMID) 213 return (0); 214 brd = hd->hp_unit; 215 isconsole = (brd == BOARD(dcmconsole)); 216 /* 217 * XXX selected console device (CONSUNIT) as determined by 218 * dcmcnprobe does not agree with logical numbering imposed 219 * by the config file (i.e. lowest address DCM is not unit 220 * CONSUNIT). Don't recognize this card. 221 */ 222 if (isconsole && dcm != dcm_addr[BOARD(dcmconsole)]) 223 return (0); 224 225 /* 226 * Empirically derived self-test magic 227 */ 228 s = spltty(); 229 dcm->dcm_rsid = DCMRS; 230 DELAY(50000); /* 5000 is not long enough */ 231 dcm->dcm_rsid = 0; 232 dcm->dcm_ic = IC_IE; 233 dcm->dcm_cr = CR_SELFT; 234 while ((dcm->dcm_ic & IC_IR) == 0) 235 if (++timo == 20000) 236 return (0); 237 DELAY(50000) /* XXX why is this needed ???? */ 238 while ((dcm->dcm_iir & IIR_SELFT) == 0) 239 if (++timo == 400000) 240 return (0); 241 DELAY(50000) /* XXX why is this needed ???? */ 242 if (dcm->dcm_stcon != ST_OK) { 243 if (!isconsole) 244 printf("dcm%d: self test failed: %x\n", 245 brd, dcm->dcm_stcon); 246 return (0); 247 } 248 dcm->dcm_ic = IC_ID; 249 splx(s); 250 251 hd->hp_ipl = DCMIPL(dcm->dcm_ic); 252 dcm_addr[brd] = dcm; 253 dcm_active |= 1 << brd; 254 dcmsoftCAR[brd] = hd->hp_flags; 255 dcmisr[brd].isr_ipl = hd->hp_ipl; 256 dcmisr[brd].isr_arg = brd; 257 dcmisr[brd].isr_intr = dcmintr; 258 isrlink(&dcmisr[brd]); 259 #ifdef KGDB 260 if (major(kgdb_dev) == dcmmajor && BOARD(kgdb_dev) == brd) { 261 if (dcmconsole == UNIT(kgdb_dev)) 262 kgdb_dev = NODEV; /* can't debug over console port */ 263 #ifndef KGDB_CHEAT 264 /* 265 * The following could potentially be replaced 266 * by the corresponding code in dcmcnprobe. 267 */ 268 else { 269 (void) dcminit(kgdb_dev, kgdb_rate); 270 if (kgdb_debug_init) { 271 printf("dcm%d: ", UNIT(kgdb_dev)); 272 kgdb_connect(1); 273 } else 274 printf("dcm%d: kgdb enabled\n", UNIT(kgdb_dev)); 275 } 276 /* end could be replaced */ 277 #endif 278 } 279 #endif 280 if (dcmistype == DIS_TIMER) 281 dcmsetischeme(brd, DIS_RESET|DIS_TIMER); 282 else 283 dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR); 284 285 /* load pointers to modem control */ 286 dcm_modem[MKUNIT(brd, 0)] = &dcm->dcm_modem0; 287 dcm_modem[MKUNIT(brd, 1)] = &dcm->dcm_modem1; 288 dcm_modem[MKUNIT(brd, 2)] = &dcm->dcm_modem2; 289 dcm_modem[MKUNIT(brd, 3)] = &dcm->dcm_modem3; 290 /* set DCD (modem) and CTS (flow control) on all ports */ 291 if (dcmsoftCAR[brd] & FLAG_STDDCE) 292 mbits = hp2dce_in(MI_CD|MI_CTS); 293 else 294 mbits = MI_CD|MI_CTS; 295 for (i = 0; i < 4; i++) 296 dcm_modem[MKUNIT(brd, i)]->mdmmsk = mbits; 297 298 dcm->dcm_ic = IC_IE; /* turn all interrupts on */ 299 /* 300 * Need to reset baud rate, etc. of next print so reset dcmconsole. 301 * Also make sure console is always "hardwired" 302 */ 303 if (isconsole) { 304 dcmconsinit = 0; 305 dcmsoftCAR[brd] |= (1 << PORT(dcmconsole)); 306 } 307 return (1); 308 } 309 310 /* ARGSUSED */ 311 #ifdef __STDC__ 312 dcmopen(dev_t dev, int flag, int mode, struct proc *p) 313 #else 314 dcmopen(dev, flag, mode, p) 315 dev_t dev; 316 int flag, mode; 317 struct proc *p; 318 #endif 319 { 320 register struct tty *tp; 321 register int unit, brd; 322 int error = 0, mbits; 323 324 unit = UNIT(dev); 325 brd = BOARD(unit); 326 if (unit >= NDCMLINE || (dcm_active & (1 << brd)) == 0) 327 return (ENXIO); 328 tp = &dcm_tty[unit]; 329 tp->t_oproc = dcmstart; 330 tp->t_param = dcmparam; 331 tp->t_dev = dev; 332 if ((tp->t_state & TS_ISOPEN) == 0) { 333 tp->t_state |= TS_WOPEN; 334 ttychars(tp); 335 if (tp->t_ispeed == 0) { 336 tp->t_iflag = TTYDEF_IFLAG; 337 tp->t_oflag = TTYDEF_OFLAG; 338 tp->t_cflag = TTYDEF_CFLAG; 339 tp->t_lflag = TTYDEF_LFLAG; 340 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 341 } 342 (void) dcmparam(tp, &tp->t_termios); 343 ttsetwater(tp); 344 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 345 return (EBUSY); 346 mbits = MO_ON; 347 if (dcmsoftCAR[brd] & FLAG_STDDCE) 348 mbits |= MO_SR; /* pin 23, could be used as RTS */ 349 (void) dcmmctl(dev, mbits, DMSET); /* enable port */ 350 if ((dcmsoftCAR[brd] & (1 << PORT(unit))) || 351 (dcmmctl(dev, MO_OFF, DMGET) & MI_CD)) 352 tp->t_state |= TS_CARR_ON; 353 #ifdef DEBUG 354 if (dcmdebug & DDB_MODEM) 355 printf("dcm%d: dcmopen port %d softcarr %c\n", 356 brd, unit, (tp->t_state & TS_CARR_ON) ? '1' : '0'); 357 #endif 358 (void) spltty(); 359 while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 360 (tp->t_state & TS_CARR_ON) == 0) { 361 tp->t_state |= TS_WOPEN; 362 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 363 ttopen, 0)) 364 break; 365 } 366 (void) spl0(); 367 368 #ifdef DEBUG 369 if (dcmdebug & DDB_OPENCLOSE) 370 printf("dcmopen: u %x st %x fl %x\n", 371 unit, tp->t_state, tp->t_flags); 372 #endif 373 if (error == 0) 374 error = (*linesw[tp->t_line].l_open)(dev, tp); 375 return (error); 376 } 377 378 /*ARGSUSED*/ 379 dcmclose(dev, flag, mode, p) 380 dev_t dev; 381 int flag, mode; 382 struct proc *p; 383 { 384 register struct tty *tp; 385 int unit; 386 387 unit = UNIT(dev); 388 tp = &dcm_tty[unit]; 389 (*linesw[tp->t_line].l_close)(tp, flag); 390 if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 391 (tp->t_state&TS_ISOPEN) == 0) 392 (void) dcmmctl(dev, MO_OFF, DMSET); 393 #ifdef DEBUG 394 if (dcmdebug & DDB_OPENCLOSE) 395 printf("dcmclose: u %x st %x fl %x\n", 396 unit, tp->t_state, tp->t_flags); 397 #endif 398 ttyclose(tp); 399 return (0); 400 } 401 402 dcmread(dev, uio, flag) 403 dev_t dev; 404 struct uio *uio; 405 int flag; 406 { 407 register struct tty *tp; 408 409 tp = &dcm_tty[UNIT(dev)]; 410 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 411 } 412 413 dcmwrite(dev, uio, flag) 414 dev_t dev; 415 struct uio *uio; 416 int flag; 417 { 418 int unit = UNIT(dev); 419 register struct tty *tp; 420 421 tp = &dcm_tty[unit]; 422 /* 423 * XXX we disallow virtual consoles if the physical console is 424 * a serial port. This is in case there is a display attached that 425 * is not the console. In that situation we don't need/want the X 426 * server taking over the console. 427 */ 428 if (constty && unit == dcmconsole) 429 constty = NULL; 430 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 431 } 432 433 dcmintr(brd) 434 register int brd; 435 { 436 register struct dcmdevice *dcm = dcm_addr[brd]; 437 register struct dcmischeme *dis; 438 register int unit = MKUNIT(brd, 0); 439 register int code, i; 440 int pcnd[4], mcode, mcnd[4]; 441 442 /* 443 * Do all guarded register accesses right off to minimize 444 * block out of hardware. 445 */ 446 SEM_LOCK(dcm); 447 if ((dcm->dcm_ic & IC_IR) == 0) { 448 SEM_UNLOCK(dcm); 449 return (0); 450 } 451 for (i = 0; i < 4; i++) { 452 pcnd[i] = dcm->dcm_icrtab[i].dcm_data; 453 dcm->dcm_icrtab[i].dcm_data = 0; 454 code = dcm_modem[unit+i]->mdmin; 455 if (dcmsoftCAR[brd] & FLAG_STDDCE) 456 code = hp2dce_in(code); 457 mcnd[i] = code; 458 } 459 code = dcm->dcm_iir & IIR_MASK; 460 dcm->dcm_iir = 0; /* XXX doc claims read clears interrupt?! */ 461 mcode = dcm->dcm_modemintr; 462 dcm->dcm_modemintr = 0; 463 SEM_UNLOCK(dcm); 464 465 #ifdef DEBUG 466 if (dcmdebug & DDB_INTR) { 467 printf("dcmintr(%d): iir %x pc %x/%x/%x/%x ", 468 brd, code, pcnd[0], pcnd[1], pcnd[2], pcnd[3]); 469 printf("miir %x mc %x/%x/%x/%x\n", 470 mcode, mcnd[0], mcnd[1], mcnd[2], mcnd[3]); 471 } 472 #endif 473 if (code & IIR_TIMEO) 474 dcmrint(brd, dcm); 475 if (code & IIR_PORT0) 476 dcmpint(unit+0, pcnd[0], dcm); 477 if (code & IIR_PORT1) 478 dcmpint(unit+1, pcnd[1], dcm); 479 if (code & IIR_PORT2) 480 dcmpint(unit+2, pcnd[2], dcm); 481 if (code & IIR_PORT3) 482 dcmpint(unit+3, pcnd[3], dcm); 483 if (code & IIR_MODM) { 484 if (mcode == 0 || mcode & 0x1) /* mcode==0 -> 98642 board */ 485 dcmmint(unit+0, mcnd[0], dcm); 486 if (mcode & 0x2) 487 dcmmint(unit+1, mcnd[1], dcm); 488 if (mcode & 0x4) 489 dcmmint(unit+2, mcnd[2], dcm); 490 if (mcode & 0x8) 491 dcmmint(unit+3, mcnd[3], dcm); 492 } 493 494 dis = &dcmischeme[brd]; 495 /* 496 * Chalk up a receiver interrupt if the timer running or one of 497 * the ports reports a special character interrupt. 498 */ 499 if ((code & IIR_TIMEO) || 500 ((pcnd[0]|pcnd[1]|pcnd[2]|pcnd[3]) & IT_SPEC)) 501 dis->dis_intr++; 502 /* 503 * See if it is time to check/change the interrupt rate. 504 */ 505 if (dcmistype < 0 && 506 (i = time.tv_sec - dis->dis_time) >= dcminterval) { 507 /* 508 * If currently per-character and averaged over 70 interrupts 509 * per-second (66 is threshold of 600 baud) in last interval, 510 * switch to timer mode. 511 * 512 * XXX decay counts ala load average to avoid spikes? 513 */ 514 if (dis->dis_perchar && dis->dis_intr > 70 * i) 515 dcmsetischeme(brd, DIS_TIMER); 516 /* 517 * If currently using timer and had more interrupts than 518 * received characters in the last interval, switch back 519 * to per-character. Note that after changing to per-char 520 * we must process any characters already in the queue 521 * since they may have arrived before the bitmap was setup. 522 * 523 * XXX decay counts? 524 */ 525 else if (!dis->dis_perchar && dis->dis_intr > dis->dis_char) { 526 dcmsetischeme(brd, DIS_PERCHAR); 527 dcmrint(brd, dcm); 528 } 529 dis->dis_intr = dis->dis_char = 0; 530 dis->dis_time = time.tv_sec; 531 } 532 return (1); 533 } 534 535 /* 536 * Port interrupt. Can be two things: 537 * First, it might be a special character (exception interrupt); 538 * Second, it may be a buffer empty (transmit interrupt); 539 */ 540 dcmpint(unit, code, dcm) 541 int unit, code; 542 struct dcmdevice *dcm; 543 { 544 struct tty *tp = &dcm_tty[unit]; 545 546 if (code & IT_SPEC) 547 dcmreadbuf(unit, dcm, tp); 548 if (code & IT_TX) 549 dcmxint(unit, dcm, tp); 550 } 551 552 dcmrint(brd, dcm) 553 int brd; 554 register struct dcmdevice *dcm; 555 { 556 register int i, unit; 557 register struct tty *tp; 558 559 unit = MKUNIT(brd, 0); 560 tp = &dcm_tty[unit]; 561 for (i = 0; i < 4; i++, tp++, unit++) 562 dcmreadbuf(unit, dcm, tp); 563 } 564 565 dcmreadbuf(unit, dcm, tp) 566 int unit; 567 register struct dcmdevice *dcm; 568 register struct tty *tp; 569 { 570 int port = PORT(unit); 571 register struct dcmpreg *pp = dcm_preg(dcm, port); 572 register struct dcmrfifo *fifo; 573 register int c, stat; 574 register unsigned head; 575 int nch = 0; 576 #ifdef DCMSTATS 577 struct dcmstats *dsp = &dcmstats[BOARD(unit)]; 578 579 dsp->rints++; 580 #endif 581 if ((tp->t_state & TS_ISOPEN) == 0) { 582 #ifdef KGDB 583 if ((makedev(dcmmajor, unit) == kgdb_dev) && 584 (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) && 585 dcm->dcm_rfifos[3-port][head>>1].data_char == FRAME_START) { 586 pp->r_head = (head + 2) & RX_MASK; 587 kgdb_connect(0); /* trap into kgdb */ 588 return; 589 } 590 #endif /* KGDB */ 591 pp->r_head = pp->r_tail & RX_MASK; 592 return; 593 } 594 595 head = pp->r_head & RX_MASK; 596 fifo = &dcm->dcm_rfifos[3-port][head>>1]; 597 /* 598 * XXX upper bound on how many chars we will take in one swallow? 599 */ 600 while (head != (pp->r_tail & RX_MASK)) { 601 /* 602 * Get character/status and update head pointer as fast 603 * as possible to make room for more characters. 604 */ 605 c = fifo->data_char; 606 stat = fifo->data_stat; 607 head = (head + 2) & RX_MASK; 608 pp->r_head = head; 609 fifo = head ? fifo+1 : &dcm->dcm_rfifos[3-port][0]; 610 nch++; 611 612 #ifdef DEBUG 613 if (dcmdebug & DDB_INPUT) 614 printf("dcmreadbuf(%d): c%x('%c') s%x f%x h%x t%x\n", 615 unit, c&0xFF, c, stat&0xFF, 616 tp->t_flags, head, pp->r_tail); 617 #endif 618 /* 619 * Check for and handle errors 620 */ 621 if (stat & RD_MASK) { 622 #ifdef DEBUG 623 if (dcmdebug & (DDB_INPUT|DDB_SIOERR)) 624 printf("dcmreadbuf(%d): err: c%x('%c') s%x\n", 625 unit, stat, c&0xFF, c); 626 #endif 627 if (stat & (RD_BD | RD_FE)) 628 c |= TTY_FE; 629 else if (stat & RD_PE) 630 c |= TTY_PE; 631 else if (stat & RD_OVF) 632 log(LOG_WARNING, 633 "dcm%d: silo overflow\n", unit); 634 else if (stat & RD_OE) 635 log(LOG_WARNING, 636 "dcm%d: uart overflow\n", unit); 637 } 638 (*linesw[tp->t_line].l_rint)(c, tp); 639 } 640 dcmischeme[BOARD(unit)].dis_char += nch; 641 #ifdef DCMSTATS 642 dsp->rchars += nch; 643 if (nch <= DCMRBSIZE) 644 dsp->rsilo[nch]++; 645 else 646 dsp->rsilo[DCMRBSIZE+1]++; 647 #endif 648 } 649 650 dcmxint(unit, dcm, tp) 651 int unit; 652 struct dcmdevice *dcm; 653 register struct tty *tp; 654 { 655 tp->t_state &= ~TS_BUSY; 656 if (tp->t_state & TS_FLUSH) 657 tp->t_state &= ~TS_FLUSH; 658 (*linesw[tp->t_line].l_start)(tp); 659 } 660 661 dcmmint(unit, mcnd, dcm) 662 register int unit; 663 register struct dcmdevice *dcm; 664 int mcnd; 665 { 666 register struct tty *tp; 667 int delta; 668 669 #ifdef DEBUG 670 if (dcmdebug & DDB_MODEM) 671 printf("dcmmint: port %d mcnd %x mcndlast %x\n", 672 unit, mcnd, mcndlast[unit]); 673 #endif 674 tp = &dcm_tty[unit]; 675 delta = mcnd ^ mcndlast[unit]; 676 mcndlast[unit] = mcnd; 677 if ((delta & MI_CTS) && (tp->t_state & TS_ISOPEN) && 678 (tp->t_flags & CCTS_OFLOW)) { 679 if (mcnd & MI_CTS) { 680 tp->t_state &= ~TS_TTSTOP; 681 ttstart(tp); 682 } else 683 tp->t_state |= TS_TTSTOP; /* inline dcmstop */ 684 } 685 if (delta & MI_CD) { 686 if (mcnd & MI_CD) 687 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 688 else if ((dcmsoftCAR[BOARD(unit)] & (1 << PORT(unit))) == 0 && 689 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 690 dcm_modem[unit]->mdmout = MO_OFF; 691 SEM_LOCK(dcm); 692 dcm->dcm_modemchng |= 1<<(unit & 3); 693 dcm->dcm_cr |= CR_MODM; 694 SEM_UNLOCK(dcm); 695 DELAY(10); /* time to change lines */ 696 } 697 } 698 } 699 700 dcmioctl(dev, cmd, data, flag, p) 701 dev_t dev; 702 u_long cmd; 703 caddr_t data; 704 int flag; 705 struct proc *p; 706 { 707 register struct tty *tp; 708 register int unit = UNIT(dev); 709 register struct dcmdevice *dcm; 710 register int port; 711 int error, s; 712 713 #ifdef DEBUG 714 if (dcmdebug & DDB_IOCTL) 715 printf("dcmioctl: unit %d cmd %x data %x flag %x\n", 716 unit, cmd, *data, flag); 717 #endif 718 tp = &dcm_tty[unit]; 719 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 720 if (error >= 0) 721 return (error); 722 error = ttioctl(tp, cmd, data, flag); 723 if (error >= 0) 724 return (error); 725 726 port = PORT(unit); 727 dcm = dcm_addr[BOARD(unit)]; 728 switch (cmd) { 729 case TIOCSBRK: 730 /* 731 * Wait for transmitter buffer to empty 732 */ 733 s = spltty(); 734 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 735 DELAY(DCM_USPERCH(tp->t_ospeed)); 736 SEM_LOCK(dcm); 737 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK; 738 dcm->dcm_cr |= (1 << port); /* start break */ 739 SEM_UNLOCK(dcm); 740 splx(s); 741 break; 742 743 case TIOCCBRK: 744 SEM_LOCK(dcm); 745 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK; 746 dcm->dcm_cr |= (1 << port); /* end break */ 747 SEM_UNLOCK(dcm); 748 break; 749 750 case TIOCSDTR: 751 (void) dcmmctl(dev, MO_ON, DMBIS); 752 break; 753 754 case TIOCCDTR: 755 (void) dcmmctl(dev, MO_ON, DMBIC); 756 break; 757 758 case TIOCMSET: 759 (void) dcmmctl(dev, *(int *)data, DMSET); 760 break; 761 762 case TIOCMBIS: 763 (void) dcmmctl(dev, *(int *)data, DMBIS); 764 break; 765 766 case TIOCMBIC: 767 (void) dcmmctl(dev, *(int *)data, DMBIC); 768 break; 769 770 case TIOCMGET: 771 *(int *)data = dcmmctl(dev, 0, DMGET); 772 break; 773 774 default: 775 return (ENOTTY); 776 } 777 return (0); 778 } 779 780 dcmparam(tp, t) 781 register struct tty *tp; 782 register struct termios *t; 783 { 784 register struct dcmdevice *dcm; 785 register int port, mode, cflag = t->c_cflag; 786 int ospeed = ttspeedtab(t->c_ospeed, dcmspeedtab); 787 788 /* check requested parameters */ 789 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 790 return (EINVAL); 791 /* and copy to tty */ 792 tp->t_ispeed = t->c_ispeed; 793 tp->t_ospeed = t->c_ospeed; 794 tp->t_cflag = cflag; 795 if (ospeed == 0) { 796 (void) dcmmctl(UNIT(tp->t_dev), MO_OFF, DMSET); 797 return (0); 798 } 799 800 mode = 0; 801 switch (cflag&CSIZE) { 802 case CS5: 803 mode = LC_5BITS; break; 804 case CS6: 805 mode = LC_6BITS; break; 806 case CS7: 807 mode = LC_7BITS; break; 808 case CS8: 809 mode = LC_8BITS; break; 810 } 811 if (cflag&PARENB) { 812 if (cflag&PARODD) 813 mode |= LC_PODD; 814 else 815 mode |= LC_PEVEN; 816 } 817 if (cflag&CSTOPB) 818 mode |= LC_2STOP; 819 else 820 mode |= LC_1STOP; 821 #ifdef DEBUG 822 if (dcmdebug & DDB_PARAM) 823 printf("dcmparam(%d): cflag %x mode %x speed %d uperch %d\n", 824 UNIT(tp->t_dev), cflag, mode, tp->t_ospeed, 825 DCM_USPERCH(tp->t_ospeed)); 826 #endif 827 828 port = PORT(tp->t_dev); 829 dcm = dcm_addr[BOARD(tp->t_dev)]; 830 /* 831 * Wait for transmitter buffer to empty. 832 */ 833 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 834 DELAY(DCM_USPERCH(tp->t_ospeed)); 835 /* 836 * Make changes known to hardware. 837 */ 838 dcm->dcm_data[port].dcm_baud = ospeed; 839 dcm->dcm_data[port].dcm_conf = mode; 840 SEM_LOCK(dcm); 841 dcm->dcm_cmdtab[port].dcm_data |= CT_CON; 842 dcm->dcm_cr |= (1 << port); 843 SEM_UNLOCK(dcm); 844 /* 845 * Delay for config change to take place. Weighted by baud. 846 * XXX why do we do this? 847 */ 848 DELAY(16 * DCM_USPERCH(tp->t_ospeed)); 849 return (0); 850 } 851 852 void 853 dcmstart(tp) 854 register struct tty *tp; 855 { 856 register struct dcmdevice *dcm; 857 register struct dcmpreg *pp; 858 register struct dcmtfifo *fifo; 859 register char *bp; 860 register unsigned tail, next; 861 register int port, nch; 862 unsigned head; 863 char buf[16]; 864 int s; 865 #ifdef DCMSTATS 866 struct dcmstats *dsp = &dcmstats[BOARD(tp->t_dev)]; 867 int tch = 0; 868 #endif 869 870 s = spltty(); 871 #ifdef DCMSTATS 872 dsp->xints++; 873 #endif 874 #ifdef DEBUG 875 if (dcmdebug & DDB_OUTPUT) 876 printf("dcmstart(%d): state %x flags %x outcc %d\n", 877 UNIT(tp->t_dev), tp->t_state, tp->t_flags, 878 tp->t_outq.c_cc); 879 #endif 880 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 881 goto out; 882 if (tp->t_outq.c_cc <= tp->t_lowat) { 883 if (tp->t_state&TS_ASLEEP) { 884 tp->t_state &= ~TS_ASLEEP; 885 wakeup((caddr_t)&tp->t_outq); 886 } 887 selwakeup(&tp->t_wsel); 888 } 889 if (tp->t_outq.c_cc == 0) { 890 #ifdef DCMSTATS 891 dsp->xempty++; 892 #endif 893 goto out; 894 } 895 896 dcm = dcm_addr[BOARD(tp->t_dev)]; 897 port = PORT(tp->t_dev); 898 pp = dcm_preg(dcm, port); 899 tail = pp->t_tail & TX_MASK; 900 next = (tail + 1) & TX_MASK; 901 head = pp->t_head & TX_MASK; 902 if (head == next) 903 goto out; 904 fifo = &dcm->dcm_tfifos[3-port][tail]; 905 again: 906 nch = q_to_b(&tp->t_outq, buf, (head - next) & TX_MASK); 907 #ifdef DCMSTATS 908 tch += nch; 909 #endif 910 #ifdef DEBUG 911 if (dcmdebug & DDB_OUTPUT) 912 printf("\thead %x tail %x nch %d\n", head, tail, nch); 913 #endif 914 /* 915 * Loop transmitting all the characters we can. 916 */ 917 for (bp = buf; --nch >= 0; bp++) { 918 fifo->data_char = *bp; 919 pp->t_tail = next; 920 /* 921 * If this is the first character, 922 * get the hardware moving right now. 923 */ 924 if (bp == buf) { 925 tp->t_state |= TS_BUSY; 926 SEM_LOCK(dcm); 927 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 928 dcm->dcm_cr |= (1 << port); 929 SEM_UNLOCK(dcm); 930 } 931 tail = next; 932 fifo = tail ? fifo+1 : &dcm->dcm_tfifos[3-port][0]; 933 next = (next + 1) & TX_MASK; 934 } 935 /* 936 * Head changed while we were loading the buffer, 937 * go back and load some more if we can. 938 */ 939 if (tp->t_outq.c_cc && head != (pp->t_head & TX_MASK)) { 940 #ifdef DCMSTATS 941 dsp->xrestarts++; 942 #endif 943 head = pp->t_head & TX_MASK; 944 goto again; 945 } 946 947 /* 948 * Kick it one last time in case it finished while we were 949 * loading the last bunch. 950 */ 951 if (bp > &buf[1]) { 952 tp->t_state |= TS_BUSY; 953 SEM_LOCK(dcm); 954 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 955 dcm->dcm_cr |= (1 << port); 956 SEM_UNLOCK(dcm); 957 } 958 #ifdef DEBUG 959 if (dcmdebug & DDB_INTR) 960 printf("dcmstart(%d): head %x tail %x outqcc %d\n", 961 UNIT(tp->t_dev), head, tail, tp->t_outq.c_cc); 962 #endif 963 out: 964 #ifdef DCMSTATS 965 dsp->xchars += tch; 966 if (tch <= DCMXBSIZE) 967 dsp->xsilo[tch]++; 968 else 969 dsp->xsilo[DCMXBSIZE+1]++; 970 #endif 971 splx(s); 972 } 973 974 /* 975 * Stop output on a line. 976 */ 977 dcmstop(tp, flag) 978 register struct tty *tp; 979 int flag; 980 { 981 int s; 982 983 s = spltty(); 984 if (tp->t_state & TS_BUSY) { 985 /* XXX is there some way to safely stop transmission? */ 986 if ((tp->t_state&TS_TTSTOP) == 0) 987 tp->t_state |= TS_FLUSH; 988 } 989 splx(s); 990 } 991 992 /* 993 * Modem control 994 */ 995 dcmmctl(dev, bits, how) 996 dev_t dev; 997 int bits, how; 998 { 999 register struct dcmdevice *dcm; 1000 int s, unit, brd, hit = 0; 1001 1002 unit = UNIT(dev); 1003 #ifdef DEBUG 1004 if (dcmdebug & DDB_MODEM) 1005 printf("dcmmctl(%d) unit %d bits 0x%x how %x\n", 1006 BOARD(unit), unit, bits, how); 1007 #endif 1008 1009 brd = BOARD(unit); 1010 dcm = dcm_addr[brd]; 1011 s = spltty(); 1012 switch (how) { 1013 1014 case DMSET: 1015 dcm_modem[unit]->mdmout = bits; 1016 hit++; 1017 break; 1018 1019 case DMBIS: 1020 dcm_modem[unit]->mdmout |= bits; 1021 hit++; 1022 break; 1023 1024 case DMBIC: 1025 dcm_modem[unit]->mdmout &= ~bits; 1026 hit++; 1027 break; 1028 1029 case DMGET: 1030 bits = dcm_modem[unit]->mdmin; 1031 if (dcmsoftCAR[brd] & FLAG_STDDCE) 1032 bits = hp2dce_in(bits); 1033 break; 1034 } 1035 if (hit) { 1036 SEM_LOCK(dcm); 1037 dcm->dcm_modemchng |= 1<<(unit & 3); 1038 dcm->dcm_cr |= CR_MODM; 1039 SEM_UNLOCK(dcm); 1040 DELAY(10); /* delay until done */ 1041 (void) splx(s); 1042 } 1043 return (bits); 1044 } 1045 1046 /* 1047 * Set board to either interrupt per-character or at a fixed interval. 1048 */ 1049 dcmsetischeme(brd, flags) 1050 int brd, flags; 1051 { 1052 register struct dcmdevice *dcm = dcm_addr[brd]; 1053 register struct dcmischeme *dis = &dcmischeme[brd]; 1054 register int i; 1055 u_char mask; 1056 int perchar = flags & DIS_PERCHAR; 1057 1058 #ifdef DEBUG 1059 if (dcmdebug & DDB_INTSCHM) 1060 printf("dcmsetischeme(%d, %d): cur %d, ints %d, chars %d\n", 1061 brd, perchar, dis->dis_perchar, 1062 dis->dis_intr, dis->dis_char); 1063 if ((flags & DIS_RESET) == 0 && perchar == dis->dis_perchar) { 1064 printf("dcmsetischeme(%d): redundent request %d\n", 1065 brd, perchar); 1066 return; 1067 } 1068 #endif 1069 /* 1070 * If perchar is non-zero, we enable interrupts on all characters 1071 * otherwise we disable perchar interrupts and use periodic 1072 * polling interrupts. 1073 */ 1074 dis->dis_perchar = perchar; 1075 mask = perchar ? 0xf : 0x0; 1076 for (i = 0; i < 256; i++) 1077 dcm->dcm_bmap[i].data_data = mask; 1078 /* 1079 * Don't slow down tandem mode, interrupt on flow control 1080 * chars for any port on the board. 1081 */ 1082 if (!perchar) { 1083 register struct tty *tp = &dcm_tty[MKUNIT(brd, 0)]; 1084 int c; 1085 1086 for (i = 0; i < 4; i++, tp++) { 1087 if ((c = tp->t_cc[VSTART]) != _POSIX_VDISABLE) 1088 dcm->dcm_bmap[c].data_data |= (1 << i); 1089 if ((c = tp->t_cc[VSTOP]) != _POSIX_VDISABLE) 1090 dcm->dcm_bmap[c].data_data |= (1 << i); 1091 } 1092 } 1093 /* 1094 * Board starts with timer disabled so if first call is to 1095 * set perchar mode then we don't want to toggle the timer. 1096 */ 1097 if (flags == (DIS_RESET|DIS_PERCHAR)) 1098 return; 1099 /* 1100 * Toggle card 16.7ms interrupts (we first make sure that card 1101 * has cleared the bit so it will see the toggle). 1102 */ 1103 while (dcm->dcm_cr & CR_TIMER) 1104 ; 1105 SEM_LOCK(dcm); 1106 dcm->dcm_cr |= CR_TIMER; 1107 SEM_UNLOCK(dcm); 1108 } 1109 1110 /* 1111 * Following are all routines needed for DCM to act as console 1112 */ 1113 #include <hp/dev/cons.h> 1114 1115 dcmcnprobe(cp) 1116 struct consdev *cp; 1117 { 1118 register struct hp_hw *hw; 1119 int unit; 1120 1121 /* locate the major number */ 1122 for (dcmmajor = 0; dcmmajor < nchrdev; dcmmajor++) 1123 if (cdevsw[dcmmajor].d_open == dcmopen) 1124 break; 1125 1126 /* 1127 * Implicitly assigns the lowest select code DCM card found to be 1128 * logical unit 0 (actually CONUNIT). If your config file does 1129 * anything different, you're screwed. 1130 */ 1131 for (hw = sc_table; hw->hw_type; hw++) 1132 if (HW_ISDEV(hw, D_COMMDCM) && !badaddr((short *)hw->hw_kva)) 1133 break; 1134 if (!HW_ISDEV(hw, D_COMMDCM)) { 1135 cp->cn_pri = CN_DEAD; 1136 return; 1137 } 1138 unit = CONUNIT; 1139 dcm_addr[BOARD(CONUNIT)] = (struct dcmdevice *)hw->hw_kva; 1140 1141 /* initialize required fields */ 1142 cp->cn_dev = makedev(dcmmajor, unit); 1143 cp->cn_tp = &dcm_tty[unit]; 1144 switch (dcm_addr[BOARD(unit)]->dcm_rsid) { 1145 case DCMID: 1146 cp->cn_pri = CN_NORMAL; 1147 break; 1148 case DCMID|DCMCON: 1149 cp->cn_pri = CN_REMOTE; 1150 break; 1151 default: 1152 cp->cn_pri = CN_DEAD; 1153 return; 1154 } 1155 /* 1156 * If dcmconsole is initialized, raise our priority. 1157 */ 1158 if (dcmconsole == UNIT(unit)) 1159 cp->cn_pri = CN_REMOTE; 1160 #ifdef KGDB_CHEAT 1161 /* 1162 * This doesn't currently work, at least not with ite consoles; 1163 * the console hasn't been initialized yet. 1164 */ 1165 if (major(kgdb_dev) == dcmmajor && BOARD(kgdb_dev) == BOARD(unit)) { 1166 (void) dcminit(kgdb_dev, kgdb_rate); 1167 if (kgdb_debug_init) { 1168 /* 1169 * We assume that console is ready for us... 1170 * this assumes that a dca or ite console 1171 * has been selected already and will init 1172 * on the first putc. 1173 */ 1174 printf("dcm%d: ", UNIT(kgdb_dev)); 1175 kgdb_connect(1); 1176 } 1177 } 1178 #endif 1179 } 1180 1181 dcmcninit(cp) 1182 struct consdev *cp; 1183 { 1184 dcminit(cp->cn_dev, dcmdefaultrate); 1185 dcmconsinit = 1; 1186 dcmconsole = UNIT(cp->cn_dev); 1187 } 1188 1189 dcminit(dev, rate) 1190 dev_t dev; 1191 int rate; 1192 { 1193 register struct dcmdevice *dcm = dcm_addr[BOARD(dev)]; 1194 int s, mode, port; 1195 1196 port = PORT(dev); 1197 mode = LC_8BITS | LC_1STOP; 1198 s = splhigh(); 1199 /* 1200 * Wait for transmitter buffer to empty. 1201 */ 1202 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 1203 DELAY(DCM_USPERCH(rate)); 1204 /* 1205 * Make changes known to hardware. 1206 */ 1207 dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab); 1208 dcm->dcm_data[port].dcm_conf = mode; 1209 SEM_LOCK(dcm); 1210 dcm->dcm_cmdtab[port].dcm_data |= CT_CON; 1211 dcm->dcm_cr |= (1 << port); 1212 SEM_UNLOCK(dcm); 1213 /* 1214 * Delay for config change to take place. Weighted by baud. 1215 * XXX why do we do this? 1216 */ 1217 DELAY(16 * DCM_USPERCH(rate)); 1218 splx(s); 1219 } 1220 1221 dcmcngetc(dev) 1222 dev_t dev; 1223 { 1224 register struct dcmdevice *dcm = dcm_addr[BOARD(dev)]; 1225 register struct dcmrfifo *fifo; 1226 register struct dcmpreg *pp; 1227 register unsigned head; 1228 int s, c, stat, port; 1229 1230 port = PORT(dev); 1231 pp = dcm_preg(dcm, port); 1232 s = splhigh(); 1233 head = pp->r_head & RX_MASK; 1234 fifo = &dcm->dcm_rfifos[3-port][head>>1]; 1235 while (head == (pp->r_tail & RX_MASK)) 1236 ; 1237 /* 1238 * If board interrupts are enabled, just let our received char 1239 * interrupt through in case some other port on the board was 1240 * busy. Otherwise we must clear the interrupt. 1241 */ 1242 SEM_LOCK(dcm); 1243 if ((dcm->dcm_ic & IC_IE) == 0) 1244 stat = dcm->dcm_iir; 1245 SEM_UNLOCK(dcm); 1246 c = fifo->data_char; 1247 stat = fifo->data_stat; 1248 pp->r_head = (head + 2) & RX_MASK; 1249 splx(s); 1250 return (c); 1251 } 1252 1253 /* 1254 * Console kernel output character routine. 1255 */ 1256 dcmcnputc(dev, c) 1257 dev_t dev; 1258 int c; 1259 { 1260 register struct dcmdevice *dcm = dcm_addr[BOARD(dev)]; 1261 register struct dcmpreg *pp; 1262 unsigned tail; 1263 int s, port, stat; 1264 1265 port = PORT(dev); 1266 pp = dcm_preg(dcm, port); 1267 s = splhigh(); 1268 #ifdef KGDB 1269 if (dev != kgdb_dev) 1270 #endif 1271 if (dcmconsinit == 0) { 1272 (void) dcminit(dev, dcmdefaultrate); 1273 dcmconsinit = 1; 1274 } 1275 tail = pp->t_tail & TX_MASK; 1276 while (tail != (pp->t_head & TX_MASK)) 1277 ; 1278 dcm->dcm_tfifos[3-port][tail].data_char = c; 1279 pp->t_tail = tail = (tail + 1) & TX_MASK; 1280 SEM_LOCK(dcm); 1281 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 1282 dcm->dcm_cr |= (1 << port); 1283 SEM_UNLOCK(dcm); 1284 while (tail != (pp->t_head & TX_MASK)) 1285 ; 1286 /* 1287 * If board interrupts are enabled, just let our completion 1288 * interrupt through in case some other port on the board 1289 * was busy. Otherwise we must clear the interrupt. 1290 */ 1291 if ((dcm->dcm_ic & IC_IE) == 0) { 1292 SEM_LOCK(dcm); 1293 stat = dcm->dcm_iir; 1294 SEM_UNLOCK(dcm); 1295 } 1296 splx(s); 1297 } 1298 #endif 1299