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