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