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