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.5 (Berkeley) 06/22/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 if ((tp->t_state & TS_ISOPEN) == 0) { 492 #ifdef KGDB 493 if (unit == UNIT(kgdb_dev) && 494 (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) && 495 dcm->dcm_rfifos[3-port][head>>1].data_char == '!') { 496 pp->r_head = (head + 2) & RX_MASK; 497 printf("kgdb trap from dcm%d\n", unit); 498 /* trap into kgdb */ 499 asm("trap #15;"); 500 return; 501 } 502 #endif 503 pp->r_head = pp->r_tail & RX_MASK; 504 return; 505 } 506 507 head = pp->r_head & RX_MASK; 508 fifo = &dcm->dcm_rfifos[3-port][head>>1]; 509 /* 510 * XXX upper bound on how many chars we will take in one swallow? 511 */ 512 while (head != (pp->r_tail & RX_MASK)) { 513 /* 514 * Get character/status and update head pointer as fast 515 * as possible to make room for more characters. 516 */ 517 c = fifo->data_char; 518 stat = fifo->data_stat; 519 head = (head + 2) & RX_MASK; 520 pp->r_head = head; 521 fifo = head ? fifo+1 : &dcm->dcm_rfifos[3-port][0]; 522 nch++; 523 524 #ifdef DEBUG 525 if (dcmdebug & DDB_INPUT) 526 printf("dcmreadbuf(%d): c%x('%c') s%x f%x h%x t%x\n", 527 unit, c&0xFF, c, stat&0xFF, 528 tp->t_flags, head, pp->r_tail); 529 #endif 530 /* 531 * Check for and handle errors 532 */ 533 if (stat & RD_MASK) { 534 #ifdef DEBUG 535 if (dcmdebug & (DDB_INPUT|DDB_SIOERR)) 536 printf("dcmreadbuf(%d): err: c%x('%c') s%x\n", 537 unit, stat, c&0xFF, c); 538 #endif 539 if (stat & (RD_BD | RD_FE)) 540 c |= TTY_FE; 541 else if (stat & RD_PE) 542 c |= TTY_PE; 543 else if (stat & RD_OVF) 544 log(LOG_WARNING, 545 "dcm%d: silo overflow\n", unit); 546 else if (stat & RD_OE) 547 log(LOG_WARNING, 548 "dcm%d: uart overflow\n", unit); 549 } 550 (*linesw[tp->t_line].l_rint)(c, tp); 551 } 552 dcmischeme[BOARD(unit)].dis_char += nch; 553 #ifdef IOSTATS 554 dsp->rchars += nch; 555 if (nch <= DCMRBSIZE) 556 dsp->rsilo[nch]++; 557 else 558 dsp->rsilo[DCMRBSIZE+1]++; 559 #endif 560 } 561 562 dcmxint(unit, dcm, tp) 563 int unit; 564 struct dcmdevice *dcm; 565 register struct tty *tp; 566 { 567 tp->t_state &= ~TS_BUSY; 568 if (tp->t_state & TS_FLUSH) 569 tp->t_state &= ~TS_FLUSH; 570 if (tp->t_line) 571 (*linesw[tp->t_line].l_start)(tp); 572 else 573 dcmstart(tp); 574 } 575 576 dcmmint(unit, mcnd, dcm) 577 register int unit; 578 register struct dcmdevice *dcm; 579 int mcnd; 580 { 581 register struct tty *tp; 582 583 #ifdef DEBUG 584 if (dcmdebug & DDB_MODEM) 585 printf("dcmmint: unit %x mcnd %x\n", unit, mcnd); 586 #endif 587 tp = &dcm_tty[unit]; 588 if ((dcmsoftCAR[BOARD(unit)] & (1 << PORT(unit))) == 0) { 589 if (mcnd & MI_CD) 590 (void) (*linesw[tp->t_line].l_modem)(tp, 1); 591 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 592 dcm->dcm_mdmout &= ~(MO_DTR | MO_RTS); 593 SEM_LOCK(dcm); 594 dcm->dcm_cr |= CR_MODM; 595 SEM_UNLOCK(dcm); 596 DELAY(10); /* time to change lines */ 597 } 598 } 599 } 600 601 dcmioctl(dev, cmd, data, flag) 602 dev_t dev; 603 caddr_t data; 604 { 605 register struct tty *tp; 606 register int unit = UNIT(dev); 607 register struct dcmdevice *dcm; 608 register int port; 609 int error, s; 610 611 #ifdef DEBUG 612 if (dcmdebug & DDB_IOCTL) 613 printf("dcmioctl: unit %d cmd %x data %x flag %x\n", 614 unit, cmd, *data, flag); 615 #endif 616 tp = &dcm_tty[unit]; 617 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 618 if (error >= 0) 619 return (error); 620 error = ttioctl(tp, cmd, data, flag); 621 if (error >= 0) 622 return (error); 623 624 port = PORT(unit); 625 dcm = dcm_addr[BOARD(unit)]; 626 switch (cmd) { 627 case TIOCSBRK: 628 /* 629 * Wait for transmitter buffer to empty 630 */ 631 s = spltty(); 632 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 633 DELAY(DCM_USPERCH(tp->t_ospeed)); 634 SEM_LOCK(dcm); 635 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK; 636 dcm->dcm_cr |= (1 << port); /* start break */ 637 SEM_UNLOCK(dcm); 638 splx(s); 639 break; 640 641 case TIOCCBRK: 642 SEM_LOCK(dcm); 643 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK; 644 dcm->dcm_cr |= (1 << port); /* end break */ 645 SEM_UNLOCK(dcm); 646 break; 647 648 case TIOCSDTR: 649 (void) dcmmctl(dev, MO_ON, DMBIS); 650 break; 651 652 case TIOCCDTR: 653 (void) dcmmctl(dev, MO_ON, DMBIC); 654 break; 655 656 case TIOCMSET: 657 (void) dcmmctl(dev, *(int *)data, DMSET); 658 break; 659 660 case TIOCMBIS: 661 (void) dcmmctl(dev, *(int *)data, DMBIS); 662 break; 663 664 case TIOCMBIC: 665 (void) dcmmctl(dev, *(int *)data, DMBIC); 666 break; 667 668 case TIOCMGET: 669 *(int *)data = dcmmctl(dev, 0, DMGET); 670 break; 671 672 default: 673 return (ENOTTY); 674 } 675 return (0); 676 } 677 678 dcmparam(tp, t) 679 register struct tty *tp; 680 register struct termios *t; 681 { 682 register struct dcmdevice *dcm; 683 register int port, mode, cflag = t->c_cflag; 684 int ospeed = ttspeedtab(t->c_ospeed, dcmspeedtab); 685 686 /* check requested parameters */ 687 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 688 return(EINVAL); 689 /* and copy to tty */ 690 tp->t_ispeed = t->c_ispeed; 691 tp->t_ospeed = t->c_ospeed; 692 tp->t_cflag = cflag; 693 if (ospeed == 0) { 694 (void) dcmmctl(UNIT(tp->t_dev), MO_OFF, DMSET); 695 return(0); 696 } 697 698 mode = 0; 699 switch (cflag&CSIZE) { 700 case CS5: 701 mode = LC_5BITS; break; 702 case CS6: 703 mode = LC_6BITS; break; 704 case CS7: 705 mode = LC_7BITS; break; 706 case CS8: 707 mode = LC_8BITS; break; 708 } 709 if (cflag&PARENB) { 710 if (cflag&PARODD) 711 mode |= LC_PODD; 712 else 713 mode |= LC_PEVEN; 714 } 715 if (cflag&CSTOPB) 716 mode |= LC_2STOP; 717 else 718 mode |= LC_1STOP; 719 #ifdef DEBUG 720 if (dcmdebug & DDB_PARAM) 721 printf("dcmparam(%d): cflag %x mode %x speed %d uperch %d\n", 722 UNIT(tp->t_dev), cflag, mode, tp->t_ospeed, 723 DCM_USPERCH(tp->t_ospeed)); 724 #endif 725 726 port = PORT(tp->t_dev); 727 dcm = dcm_addr[BOARD(tp->t_dev)]; 728 /* 729 * Wait for transmitter buffer to empty. 730 */ 731 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 732 DELAY(DCM_USPERCH(tp->t_ospeed)); 733 /* 734 * Make changes known to hardware. 735 */ 736 dcm->dcm_data[port].dcm_baud = ospeed; 737 dcm->dcm_data[port].dcm_conf = mode; 738 SEM_LOCK(dcm); 739 dcm->dcm_cmdtab[port].dcm_data |= CT_CON; 740 dcm->dcm_cr |= (1 << port); 741 SEM_UNLOCK(dcm); 742 /* 743 * Delay for config change to take place. Weighted by buad. 744 * XXX why do we do this? 745 */ 746 DELAY(16 * DCM_USPERCH(tp->t_ospeed)); 747 return(0); 748 } 749 750 dcmstart(tp) 751 register struct tty *tp; 752 { 753 register struct dcmdevice *dcm; 754 register struct dcmpreg *pp; 755 register struct dcmtfifo *fifo; 756 register char *bp; 757 register unsigned tail, next; 758 register int port, nch; 759 unsigned head; 760 char buf[16]; 761 int s; 762 #ifdef IOSTATS 763 struct dcmstats *dsp = &dcmstats[BOARD(tp->t_dev)]; 764 int tch = 0; 765 #endif 766 767 s = spltty(); 768 #ifdef IOSTATS 769 dsp->xints++; 770 #endif 771 #ifdef DEBUG 772 if (dcmdebug & DDB_OUTPUT) 773 printf("dcmstart(%d): state %x flags %x outcc %d\n", 774 UNIT(tp->t_dev), tp->t_state, tp->t_flags, 775 tp->t_outq.c_cc); 776 #endif 777 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 778 goto out; 779 if (tp->t_outq.c_cc <= tp->t_lowat) { 780 if (tp->t_state&TS_ASLEEP) { 781 tp->t_state &= ~TS_ASLEEP; 782 wakeup((caddr_t)&tp->t_outq); 783 } 784 if (tp->t_wsel) { 785 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 786 tp->t_wsel = 0; 787 tp->t_state &= ~TS_WCOLL; 788 } 789 } 790 if (tp->t_outq.c_cc == 0) { 791 #ifdef IOSTATS 792 dsp->xempty++; 793 #endif 794 goto out; 795 } 796 797 dcm = dcm_addr[BOARD(tp->t_dev)]; 798 port = PORT(tp->t_dev); 799 pp = dcm_preg(dcm, port); 800 tail = pp->t_tail & TX_MASK; 801 next = (tail + 1) & TX_MASK; 802 head = pp->t_head & TX_MASK; 803 if (head == next) 804 goto out; 805 fifo = &dcm->dcm_tfifos[3-port][tail]; 806 again: 807 nch = q_to_b(&tp->t_outq, buf, (head - next) & TX_MASK); 808 #ifdef IOSTATS 809 tch += nch; 810 #endif 811 #ifdef DEBUG 812 if (dcmdebug & DDB_OUTPUT) 813 printf("\thead %x tail %x nch %d\n", head, tail, nch); 814 #endif 815 /* 816 * Loop transmitting all the characters we can. 817 */ 818 for (bp = buf; --nch >= 0; bp++) { 819 fifo->data_char = *bp; 820 pp->t_tail = next; 821 /* 822 * If this is the first character, 823 * get the hardware moving right now. 824 */ 825 if (bp == buf) { 826 tp->t_state |= TS_BUSY; 827 SEM_LOCK(dcm); 828 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 829 dcm->dcm_cr |= (1 << port); 830 SEM_UNLOCK(dcm); 831 } 832 tail = next; 833 fifo = tail ? fifo+1 : &dcm->dcm_tfifos[3-port][0]; 834 next = (next + 1) & TX_MASK; 835 } 836 /* 837 * Head changed while we were loading the buffer, 838 * go back and load some more if we can. 839 */ 840 if (tp->t_outq.c_cc && head != (pp->t_head & TX_MASK)) { 841 #ifdef IOSTATS 842 dsp->xrestarts++; 843 #endif 844 head = pp->t_head & TX_MASK; 845 goto again; 846 } 847 /* 848 * Kick it one last time in case it finished while we were 849 * loading the last time. 850 */ 851 if (bp > &buf[1]) { 852 tp->t_state |= TS_BUSY; 853 SEM_LOCK(dcm); 854 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 855 dcm->dcm_cr |= (1 << port); 856 SEM_UNLOCK(dcm); 857 } 858 #ifdef DEBUG 859 if (dcmdebug & DDB_INTR) 860 printf("dcmstart(%d): head %x tail %x outqcc %d\n", 861 UNIT(tp->t_dev), head, tail, tp->t_outq.c_cc); 862 #endif 863 out: 864 #ifdef IOSTATS 865 dsp->xchars += tch; 866 if (tch <= DCMXBSIZE) 867 dsp->xsilo[tch]++; 868 else 869 dsp->xsilo[DCMXBSIZE+1]++; 870 #endif 871 splx(s); 872 } 873 874 /* 875 * Stop output on a line. 876 */ 877 dcmstop(tp, flag) 878 register struct tty *tp; 879 { 880 int s; 881 882 s = spltty(); 883 if (tp->t_state & TS_BUSY) { 884 /* XXX is there some way to safely stop transmission? */ 885 if ((tp->t_state&TS_TTSTOP)==0) 886 tp->t_state |= TS_FLUSH; 887 } 888 splx(s); 889 } 890 891 /* Modem control */ 892 893 dcmmctl(dev, bits, how) 894 dev_t dev; 895 int bits, how; 896 { 897 register struct dcmdevice *dcm; 898 int s, hit = 0; 899 900 /* 901 * Only port 0 has modem control lines. 902 * XXX ok for now but needs to changed for the 8 port board. 903 */ 904 if (PORT(UNIT(dev)) != 0) 905 return(bits); 906 907 dcm = dcm_addr[BOARD(UNIT(dev))]; 908 s = spltty(); 909 switch (how) { 910 911 case DMSET: 912 dcm->dcm_mdmout = bits; 913 hit++; 914 break; 915 916 case DMBIS: 917 dcm->dcm_mdmout |= bits; 918 hit++; 919 break; 920 921 case DMBIC: 922 dcm->dcm_mdmout &= ~bits; 923 hit++; 924 break; 925 926 case DMGET: 927 bits = dcm->dcm_mdmin; 928 break; 929 } 930 if (hit) { 931 SEM_LOCK(dcm); 932 dcm->dcm_cr |= CR_MODM; 933 SEM_UNLOCK(dcm); 934 DELAY(10); /* delay until done */ 935 (void) splx(s); 936 } 937 return(bits); 938 } 939 940 /* 941 * Set board to either interrupt per-character or at a fixed interval. 942 */ 943 dcmsetischeme(brd, flags) 944 int brd, flags; 945 { 946 register struct dcmdevice *dcm = dcm_addr[brd]; 947 register struct dcmischeme *dis = &dcmischeme[brd]; 948 register int i; 949 u_char mask; 950 int perchar = flags & DIS_PERCHAR; 951 952 #ifdef DEBUG 953 if (dcmdebug & DDB_INTSCHM) 954 printf("dcmsetischeme(%d, %d): cur %d, ints %d, chars %d\n", 955 brd, perchar, dis->dis_perchar, 956 dis->dis_intr, dis->dis_char); 957 if ((flags & DIS_RESET) == 0 && perchar == dis->dis_perchar) { 958 printf("dcmsetischeme(%d): redundent request %d\n", 959 brd, perchar); 960 return; 961 } 962 #endif 963 /* 964 * If perchar is non-zero, we enable interrupts on all characters 965 * otherwise we disable perchar interrupts and use periodic 966 * polling interrupts. 967 */ 968 dis->dis_perchar = perchar; 969 mask = perchar ? 0xf : 0x0; 970 for (i = 0; i < 256; i++) 971 dcm->dcm_bmap[i].data_data = mask; 972 /* 973 * Don't slow down tandem mode, interrupt on flow control 974 * chars for any port on the board. 975 */ 976 if (!perchar) { 977 register struct tty *tp = &dcm_tty[MKUNIT(brd, 0)]; 978 int c; 979 980 for (i = 0; i < 4; i++, tp++) { 981 if ((c = tp->t_cc[VSTART]) != _POSIX_VDISABLE) 982 dcm->dcm_bmap[c].data_data |= (1 << i); 983 if ((c = tp->t_cc[VSTOP]) != _POSIX_VDISABLE) 984 dcm->dcm_bmap[c].data_data |= (1 << i); 985 } 986 } 987 /* 988 * Board starts with timer disabled so if first call is to 989 * set perchar mode then we don't want to toggle the timer. 990 */ 991 if (flags == (DIS_RESET|DIS_PERCHAR)) 992 return; 993 /* 994 * Toggle card 16.7ms interrupts (we first make sure that card 995 * has cleared the bit so it will see the toggle). 996 */ 997 while (dcm->dcm_cr & CR_TIMER) 998 ; 999 SEM_LOCK(dcm); 1000 dcm->dcm_cr |= CR_TIMER; 1001 SEM_UNLOCK(dcm); 1002 } 1003 1004 /* 1005 * Following are all routines needed for DCM to act as console 1006 */ 1007 #include "machine/cons.h" 1008 1009 dcmcnprobe(cp) 1010 struct consdev *cp; 1011 { 1012 register struct hp_hw *hw; 1013 int unit, i; 1014 extern int dcmopen(); 1015 1016 /* 1017 * Implicitly assigns the lowest select code DCM card found to be 1018 * logical unit 0 (actually CONUNIT). If your config file does 1019 * anything different, you're screwed. 1020 */ 1021 for (hw = sc_table; hw->hw_type; hw++) 1022 if (hw->hw_type == COMMDCM && !badaddr((short *)hw->hw_addr)) 1023 break; 1024 if (hw->hw_type != COMMDCM) { 1025 cp->cn_pri = CN_DEAD; 1026 return; 1027 } 1028 unit = CONUNIT; 1029 dcm_addr[BOARD(CONUNIT)] = (struct dcmdevice *)hw->hw_addr; 1030 1031 /* locate the major number */ 1032 for (i = 0; i < nchrdev; i++) 1033 if (cdevsw[i].d_open == dcmopen) 1034 break; 1035 1036 /* initialize required fields */ 1037 cp->cn_dev = makedev(i, unit); 1038 cp->cn_tp = &dcm_tty[unit]; 1039 switch (dcm_addr[BOARD(unit)]->dcm_rsid) { 1040 case DCMID: 1041 cp->cn_pri = CN_NORMAL; 1042 break; 1043 case DCMID|DCMCON: 1044 cp->cn_pri = CN_REMOTE; 1045 break; 1046 default: 1047 cp->cn_pri = CN_DEAD; 1048 break; 1049 } 1050 } 1051 1052 dcmcninit(cp) 1053 struct consdev *cp; 1054 { 1055 dcminit(cp->cn_dev, dcmdefaultrate); 1056 dcmconsole = UNIT(cp->cn_dev); 1057 } 1058 1059 dcminit(dev, rate) 1060 dev_t dev; 1061 int rate; 1062 { 1063 register struct dcmdevice *dcm = dcm_addr[BOARD(dev)]; 1064 int s, mode, port; 1065 1066 port = PORT(dev); 1067 mode = LC_8BITS | LC_1STOP; 1068 s = splhigh(); 1069 /* 1070 * Wait for transmitter buffer to empty. 1071 */ 1072 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr) 1073 DELAY(DCM_USPERCH(rate)); 1074 /* 1075 * Make changes known to hardware. 1076 */ 1077 dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab); 1078 dcm->dcm_data[port].dcm_conf = mode; 1079 SEM_LOCK(dcm); 1080 dcm->dcm_cmdtab[port].dcm_data |= CT_CON; 1081 dcm->dcm_cr |= (1 << port); 1082 SEM_UNLOCK(dcm); 1083 /* 1084 * Delay for config change to take place. Weighted by buad. 1085 * XXX why do we do this? 1086 */ 1087 DELAY(16 * DCM_USPERCH(rate)); 1088 splx(s); 1089 } 1090 1091 dcmcngetc(dev) 1092 dev_t dev; 1093 { 1094 register struct dcmdevice *dcm = dcm_addr[BOARD(dev)]; 1095 register struct dcmrfifo *fifo; 1096 register struct dcmpreg *pp; 1097 register unsigned head; 1098 int s, c, stat, port; 1099 1100 port = PORT(dev); 1101 pp = dcm_preg(dcm, port); 1102 s = splhigh(); 1103 head = pp->r_head & RX_MASK; 1104 fifo = &dcm->dcm_rfifos[3-port][head>>1]; 1105 while (head == (pp->r_tail & RX_MASK)) 1106 ; 1107 /* 1108 * If board interrupts are enabled, just let our received char 1109 * interrupt through in case some other port on the board was 1110 * busy. Otherwise we must clear the interrupt. 1111 */ 1112 SEM_LOCK(dcm); 1113 if ((dcm->dcm_ic & IC_IE) == 0) 1114 stat = dcm->dcm_iir; 1115 SEM_UNLOCK(dcm); 1116 c = fifo->data_char; 1117 stat = fifo->data_stat; 1118 pp->r_head = (head + 2) & RX_MASK; 1119 splx(s); 1120 return(c); 1121 } 1122 1123 /* 1124 * Console kernel output character routine. 1125 */ 1126 dcmcnputc(dev, c) 1127 dev_t dev; 1128 int c; 1129 { 1130 register struct dcmdevice *dcm = dcm_addr[BOARD(dev)]; 1131 register struct dcmpreg *pp; 1132 unsigned tail; 1133 int s, port, stat; 1134 1135 port = PORT(dev); 1136 pp = dcm_preg(dcm, port); 1137 s = splhigh(); 1138 #ifdef KGDB 1139 if (dev != kgdb_dev) 1140 #endif 1141 if (dcmconsole == -1) { 1142 (void) dcminit(dev, dcmdefaultrate); 1143 dcmconsole = UNIT(dev); 1144 } 1145 tail = pp->t_tail & TX_MASK; 1146 while (tail != (pp->t_head & TX_MASK)) 1147 ; 1148 dcm->dcm_tfifos[3-port][tail].data_char = c; 1149 pp->t_tail = tail = (tail + 1) & TX_MASK; 1150 SEM_LOCK(dcm); 1151 dcm->dcm_cmdtab[port].dcm_data |= CT_TX; 1152 dcm->dcm_cr |= (1 << port); 1153 SEM_UNLOCK(dcm); 1154 while (tail != (pp->t_head & TX_MASK)) 1155 ; 1156 /* 1157 * If board interrupts are enabled, just let our completion 1158 * interrupt through in case some other port on the board 1159 * was busy. Otherwise we must clear the interrupt. 1160 */ 1161 if ((dcm->dcm_ic & IC_IE) == 0) { 1162 SEM_LOCK(dcm); 1163 stat = dcm->dcm_iir; 1164 SEM_UNLOCK(dcm); 1165 } 1166 splx(s); 1167 } 1168 #endif 1169