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