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