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