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