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