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