1 /* $NetBSD: dz_ebus.c,v 1.6 2013/11/10 18:27:15 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code was written by Alessandro Forin and Neil Pittman 8 * at Microsoft Research and contributed to The NetBSD Foundation 9 * by Microsoft Corporation. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: dz_ebus.c,v 1.6 2013/11/10 18:27:15 christos Exp $"); 35 36 #include "opt_ddb.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/callout.h> 41 #include <sys/ioctl.h> 42 #include <sys/tty.h> 43 #include <sys/proc.h> 44 #include <sys/buf.h> 45 #include <sys/conf.h> 46 #include <sys/file.h> 47 #include <sys/uio.h> 48 #include <sys/kernel.h> 49 #include <sys/syslog.h> 50 #include <sys/device.h> 51 #include <sys/kauth.h> 52 53 #include <machine/bus.h> 54 #include <machine/emipsreg.h> 55 56 #include <dev/cons.h> 57 58 59 #include <emips/ebus/ebusvar.h> 60 #include <emips/emips/cons.h> 61 #if 0 62 #include <emips/emips/machdep.h> 63 #endif 64 65 #include "ioconf.h" /* for dz_cd */ 66 67 #define DZ_C2I(c) ((c) << 3) /* convert controller # to index */ 68 #define DZ_I2C(c) ((c) >> 3) /* convert minor to controller # */ 69 #define DZ_PORT(u) ((u) & 07) /* extract the port # */ 70 71 struct dz_softc { 72 device_t sc_dev; /* Autoconf blaha */ 73 struct evcnt sc_rintrcnt; /* recevive interrupt counts */ 74 struct evcnt sc_tintrcnt; /* transmit interrupt counts */ 75 struct _Usart *sc_dr; /* reg pointers */ 76 bus_space_tag_t sc_iot; 77 bus_space_handle_t sc_ioh; 78 int sc_consline; /* console line, or -1 */ 79 int sc_rxint; /* Receive interrupt count XXX */ 80 u_char sc_brk; /* Break asserted on some lines */ 81 u_char sc_dsr; /* DSR set bits if no mdm ctrl */ 82 struct dz_linestate { 83 struct dz_softc *dz_sc; /* backpointer to softc */ 84 int dz_line; /* channel number */ 85 struct tty *dz_tty; /* what we work on */ 86 } sc_dz; 87 }; 88 89 void dzrint(struct dz_softc *, uint32_t); 90 void dzxint(struct dz_softc *, uint32_t); 91 92 #ifndef TIOCM_BRK 93 #define TIOCM_BRK 0100000 /* no equivalent */ 94 95 static void dzstart(struct tty *); 96 static int dzparam(struct tty *, struct termios *); 97 static unsigned dzmctl(struct dz_softc *sc, int line, 98 int bits, /* one of the TIOCM_xx */ 99 int how); /* one of the DMSET/BIS.. */ 100 101 #include <dev/dec/dzkbdvar.h> 102 #endif 103 104 dev_type_open(dzopen); 105 dev_type_close(dzclose); 106 dev_type_read(dzread); 107 dev_type_write(dzwrite); 108 dev_type_ioctl(dzioctl); 109 dev_type_stop(dzstop); 110 dev_type_tty(dztty); 111 dev_type_poll(dzpoll); 112 113 const struct cdevsw dz_cdevsw = { 114 dzopen, dzclose, dzread, dzwrite, dzioctl, 115 dzstop, dztty, dzpoll, nommap, ttykqfilter, D_TTY 116 }; 117 118 int 119 dzopen(dev_t dev, int flag, int mode, struct lwp *l) 120 { 121 struct tty *tp; 122 int unit, line; 123 struct dz_softc *sc; 124 int s, error = 0; 125 126 unit = DZ_I2C(minor(dev)); 127 sc = device_lookup_private(&dz_cd, unit); 128 if (sc == NULL) 129 return ENXIO; 130 131 line = DZ_PORT(minor(dev)); 132 if (line > 0) /* FIXME for more than one line */ 133 return ENXIO; 134 135 tp = sc->sc_dz.dz_tty; 136 if (tp == NULL) 137 return ENODEV; 138 tp->t_oproc = dzstart; 139 tp->t_param = dzparam; 140 tp->t_dev = dev; 141 142 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 143 return (EBUSY); 144 145 if ((tp->t_state & TS_ISOPEN) == 0) { 146 ttychars(tp); 147 if (tp->t_ispeed == 0) { 148 tp->t_iflag = TTYDEF_IFLAG; 149 tp->t_oflag = TTYDEF_OFLAG; 150 tp->t_cflag = TTYDEF_CFLAG; 151 tp->t_lflag = TTYDEF_LFLAG; 152 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 153 } 154 (void)dzparam(tp, &tp->t_termios); 155 ttsetwater(tp); 156 } 157 /* we have no modem control but..*/ 158 if (dzmctl(sc, line, TIOCM_DTR, DMBIS) & TIOCM_CD) 159 tp->t_state |= TS_CARR_ON; 160 s = spltty(); 161 while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 162 !(tp->t_state & TS_CARR_ON)) { 163 tp->t_wopen++; 164 error = ttysleep(tp, &tp->t_rawcv, true, 0); 165 tp->t_wopen--; 166 if (error) 167 break; 168 } 169 (void)splx(s); 170 if (error) 171 return error; 172 return (*tp->t_linesw->l_open)(dev, tp); 173 } 174 175 int 176 dzclose(dev_t dev, int flag, int mode, struct lwp *l) 177 { 178 struct dz_softc *sc; 179 struct tty *tp; 180 int unit, line; 181 182 unit = DZ_I2C(minor(dev)); 183 sc = device_lookup_private(&dz_cd, unit); 184 line = DZ_PORT(minor(dev)); 185 186 tp = sc->sc_dz.dz_tty; 187 188 (*tp->t_linesw->l_close)(tp, flag); 189 190 /* Make sure a BREAK state is not left enabled. */ 191 (void)dzmctl(sc, line, TIOCM_BRK, DMBIC); 192 193 /* Do a hangup if so required. */ 194 if ((tp->t_cflag & HUPCL) || tp->t_wopen || !(tp->t_state & TS_ISOPEN)) 195 (void)dzmctl(sc, line, 0, DMSET); 196 197 return ttyclose(tp); 198 } 199 200 int 201 dzread(dev_t dev, struct uio *uio, int flag) 202 { 203 struct tty *tp; 204 struct dz_softc *sc; 205 206 sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev))); 207 208 tp = sc->sc_dz.dz_tty; 209 return (*tp->t_linesw->l_read)(tp, uio, flag); 210 } 211 212 int 213 dzwrite(dev_t dev, struct uio *uio, int flag) 214 { 215 struct tty *tp; 216 struct dz_softc *sc; 217 218 sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev))); 219 220 tp = sc->sc_dz.dz_tty; 221 return (*tp->t_linesw->l_write)(tp, uio, flag); 222 } 223 224 /*ARGSUSED*/ 225 int 226 dzioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 227 { 228 struct dz_softc *sc; 229 struct tty *tp; 230 int unit, line; 231 int error; 232 233 unit = DZ_I2C(minor(dev)); 234 line = 0; 235 sc = device_lookup_private(&dz_cd, unit); 236 tp = sc->sc_dz.dz_tty; 237 238 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 239 if (error >= 0) 240 return error; 241 242 error = ttioctl(tp, cmd, data, flag, l); 243 if (error >= 0) 244 return error; 245 246 switch (cmd) { 247 248 case TIOCSBRK: 249 (void)dzmctl(sc, line, TIOCM_BRK, DMBIS); 250 break; 251 252 case TIOCCBRK: 253 (void)dzmctl(sc, line, TIOCM_BRK, DMBIC); 254 break; 255 256 case TIOCSDTR: 257 (void)dzmctl(sc, line, TIOCM_DTR, DMBIS); 258 break; 259 260 case TIOCCDTR: 261 (void)dzmctl(sc, line, TIOCM_DTR, DMBIC); 262 break; 263 264 case TIOCMSET: 265 (void)dzmctl(sc, line, *(int *)data, DMSET); 266 break; 267 268 case TIOCMBIS: 269 (void)dzmctl(sc, line, *(int *)data, DMBIS); 270 break; 271 272 case TIOCMBIC: 273 (void)dzmctl(sc, line, *(int *)data, DMBIC); 274 break; 275 276 case TIOCMGET: 277 *(int *)data = dzmctl(sc, line, 0, DMGET) & ~TIOCM_BRK; 278 break; 279 280 default: 281 return EPASSTHROUGH; 282 } 283 return 0; 284 } 285 286 /*ARGSUSED*/ 287 void 288 dzstop(struct tty *tp, int flag) 289 { 290 291 if (tp->t_state & TS_BUSY) 292 if (!(tp->t_state & TS_TTSTOP)) 293 tp->t_state |= TS_FLUSH; 294 } 295 296 struct tty * 297 dztty(dev_t dev) 298 { 299 struct dz_softc *sc; 300 struct tty *tp; 301 302 sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev))); 303 tp = sc->sc_dz.dz_tty; 304 305 return tp; 306 } 307 308 int 309 dzpoll(dev_t dev, int events, struct lwp *l) 310 { 311 struct dz_softc *sc; 312 struct tty *tp; 313 314 sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev))); 315 316 tp = sc->sc_dz.dz_tty; 317 return (*tp->t_linesw->l_poll)(tp, events, l); 318 } 319 320 void 321 dzstart(struct tty *tp) 322 { 323 struct dz_softc *sc; 324 struct clist *cl; 325 int unit, s; 326 327 unit = DZ_I2C(minor(tp->t_dev)); 328 sc = device_lookup_private(&dz_cd, unit); 329 330 s = spltty(); 331 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) { 332 splx(s); 333 return; 334 } 335 cl = &tp->t_outq; 336 ttypull(tp); 337 if (cl->c_cc == 0) { 338 splx(s); 339 return; 340 } 341 342 tp->t_state |= TS_BUSY; 343 344 /* was idle, get it started */ 345 dzxint(sc,USI_TXRDY); 346 splx(s); 347 } 348 349 static int rclk = 25000000; /* BUGBUGBUGBUG */ 350 351 static int 352 dzdivisor(int baudrate) 353 { 354 int act_baud, divisor, error; 355 356 if (baudrate <= 0) 357 return 0; 358 359 divisor = (rclk / 8) / (baudrate); 360 divisor = (divisor / 2) + (divisor & 1); 361 362 if (divisor <= 0) 363 return -1; 364 act_baud = rclk / (divisor * 16); 365 366 /* 10 times error in percent: */ 367 error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1; 368 369 /* 3.0% maximum error tolerance: */ 370 if (error < -30 || error > 30) 371 return -1; 372 373 return divisor; 374 } 375 376 static int 377 dzparam(struct tty *tp, struct termios *t) 378 { 379 struct dz_softc *sc; 380 int cflag = t->c_cflag; 381 int unit, line; 382 int speed; 383 unsigned lpr; 384 int s; 385 struct _Usart *dzr; 386 387 unit = DZ_I2C(minor(tp->t_dev)); 388 line = DZ_PORT(minor(tp->t_dev)); 389 sc = device_lookup_private(&dz_cd, unit); 390 391 /* check requested parameters */ 392 if (t->c_ispeed != t->c_ospeed) 393 return EINVAL; 394 speed = dzdivisor(t->c_ispeed); 395 if (speed < 0) 396 return EINVAL; 397 398 tp->t_ispeed = t->c_ispeed; 399 tp->t_ospeed = t->c_ospeed; 400 tp->t_cflag = cflag; 401 402 { 403 /* XXX */ 404 static int didit = 0; 405 if (!didit && t->c_ispeed != 38400) 406 printf("dzparam: c_ispeed %d ignored, keeping 38400\n", 407 t->c_ispeed); 408 didit = 1; 409 } 410 speed = dzdivisor(38400); 411 412 if (speed == 0) { 413 (void)dzmctl(sc, line, 0, DMSET); /* hang up line */ 414 return 0; 415 } 416 417 switch (cflag & CSIZE) { 418 case CS5: 419 lpr = USC_BPC_5; 420 break; 421 case CS6: 422 lpr = USC_BPC_6; 423 break; 424 case CS7: 425 lpr = USC_BPC_7; 426 break; 427 default: 428 lpr = USC_BPC_8; 429 break; 430 } 431 if (cflag & CSTOPB) 432 lpr |= USC_2STOP; 433 434 if (cflag & PARENB) { 435 if (cflag & PARODD) 436 lpr |= USC_ODD; 437 else 438 lpr |= USC_EVEN; 439 } else 440 lpr |= USC_NONE; 441 442 s = spltty(); 443 444 dzr = sc->sc_dr; 445 446 dzr->Baud = speed; 447 dzr->Control = USC_CLKDIV_4 | USC_TXEN | USC_RXEN | lpr; 448 #define USI_INTRS (USI_RXRDY|USI_RXBRK|USI_OVRE|USI_FRAME|USI_PARE) 449 dzr->IntrEnable = USI_INTRS; 450 451 (void)splx(s); 452 return 0; 453 } 454 455 static unsigned 456 dzmctl(struct dz_softc *sc, int line, int bits, int how) 457 { 458 unsigned int mbits; 459 int s; 460 struct _Usart *dzr; 461 462 mbits = 0; 463 464 s = spltty(); 465 466 dzr = sc->sc_dr; 467 468 /* we have no modem control bits (CD,RI,DTR,DSR,..) */ 469 mbits |= TIOCM_CD; 470 mbits |= TIOCM_DTR; 471 472 if (dzr->ChannelStatus & USI_RXBRK) 473 mbits |= TIOCM_BRK; 474 475 switch (how) { 476 case DMSET: 477 mbits = bits; 478 break; 479 480 case DMBIS: 481 mbits |= bits; 482 break; 483 484 case DMBIC: 485 mbits &= ~bits; 486 break; 487 488 case DMGET: 489 (void)splx(s); 490 return mbits; 491 } 492 493 /* BUGBUG work in progress */ 494 if (mbits & TIOCM_BRK) { 495 sc->sc_brk |= (1 << line); 496 dzr->Control |= USC_STTBRK; 497 } else { 498 sc->sc_brk &= ~(1 << line); 499 dzr->Control |= USC_STPBRK; 500 } 501 502 (void)splx(s); 503 return mbits; 504 } 505 506 507 #if defined(DDB) 508 int dz_ddb = 0; 509 #endif 510 511 /* Receiver Interrupt */ 512 513 void 514 dzrint(struct dz_softc *sc, uint32_t csr) 515 { 516 struct tty *tp; 517 int cc; 518 struct _Usart *dzr; 519 520 sc->sc_rxint++; 521 dzr = sc->sc_dr; 522 523 cc = dzr->RxData; 524 tp = sc->sc_dz.dz_tty; 525 526 /* clear errors before we print or bail out */ 527 if (csr & (USI_OVRE|USI_FRAME|USI_PARE)) 528 dzr->Control = USC_RSTSTA; 529 530 if (!(tp->t_state & TS_ISOPEN)) { 531 wakeup(&tp->t_rawq); 532 return; 533 } 534 535 if (csr & USI_OVRE) { 536 log(LOG_WARNING, "%s: silo overflow, line %d\n", 537 device_xname(sc->sc_dev), 0); 538 } 539 540 if (csr & USI_FRAME) 541 cc |= TTY_FE; 542 if (csr & USI_PARE) 543 cc |= TTY_PE; 544 545 #if defined(DDB) 546 /* ^P drops into DDB */ 547 if (dz_ddb && (cc == 0x10)) 548 Debugger(); 549 #endif 550 (*tp->t_linesw->l_rint)(cc, tp); 551 } 552 553 /* Transmitter Interrupt */ 554 555 void 556 dzxint(struct dz_softc *sc, uint32_t csr) 557 { 558 struct tty *tp; 559 struct clist *cl; 560 int ch; 561 struct _Usart *dzr; 562 563 dzr = sc->sc_dr; 564 565 tp = sc->sc_dz.dz_tty; 566 cl = &tp->t_outq; 567 tp->t_state &= ~TS_BUSY; 568 569 /* Just send out a char if we have one */ 570 if (cl->c_cc) { 571 tp->t_state |= TS_BUSY; 572 ch = getc(cl); 573 dzr->TxData = ch; 574 dzr->IntrEnable = USI_TXRDY; 575 return; 576 } 577 578 /* Nothing to send; turn off intr */ 579 dzr->IntrDisable = USI_TXRDY; 580 581 if (tp->t_state & TS_FLUSH) 582 tp->t_state &= ~TS_FLUSH; 583 else 584 ndflush(&tp->t_outq, cl->c_cc); 585 586 (*tp->t_linesw->l_start)(tp); 587 } 588 589 /* 590 * Machdep part of the driver 591 */ 592 int dz_ebus_match(device_t, cfdata_t, void *); 593 void dz_ebus_attach(device_t, device_t, void *); 594 int dz_ebus_intr(void *, void *); 595 596 void dz_ebus_cnsetup(paddr_t); 597 void dz_ebus_cninit(struct consdev *); 598 int dz_ebus_cngetc(dev_t); 599 void dz_ebus_cnputc(dev_t, int); 600 void dz_ebus_cnpollc(dev_t, int); 601 602 static int dz_ebus_getmajor(void); 603 604 CFATTACH_DECL_NEW(dz_ebus, sizeof(struct dz_softc), 605 dz_ebus_match, dz_ebus_attach, NULL, NULL); 606 607 struct consdev dz_ebus_consdev = { 608 NULL, dz_ebus_cninit, dz_ebus_cngetc, dz_ebus_cnputc, 609 dz_ebus_cnpollc, NULL, NULL, NULL, NODEV, CN_NORMAL, 610 }; 611 612 /* 613 * Points to the console regs. Special mapping until VM is turned on. 614 */ 615 struct _Usart *dzcn; 616 617 int 618 dz_ebus_match(device_t parent, cfdata_t cf, void *aux) 619 { 620 struct ebus_attach_args *iba; 621 struct _Usart *us; 622 623 iba = aux; 624 625 if (strcmp(iba->ia_name, "dz") != 0) 626 return 0; 627 628 us = (struct _Usart *)iba->ia_vaddr; 629 if ((us == NULL) || 630 (us->Tag != PMTTAG_USART)) 631 return 0; 632 633 return 1; 634 } 635 636 void 637 dz_ebus_attach(device_t parent, device_t self, void *aux) 638 { 639 struct ebus_attach_args *iba; 640 struct dz_softc *sc; 641 642 sc = device_private(self); 643 iba = aux; 644 645 sc->sc_dev = self; 646 sc->sc_dr = (struct _Usart *)iba->ia_vaddr; 647 #if DEBUG 648 printf(" virt=%p ", (void *)sc->sc_dr); 649 #endif 650 651 printf(": neilsart 1 line"); 652 ebus_intr_establish(parent, (void *)iba->ia_cookie, IPL_TTY, 653 dz_ebus_intr, sc); 654 655 sc->sc_rxint = sc->sc_brk = 0; 656 sc->sc_consline = 0; 657 658 /* Initialize our softc structure. Should be done in open? */ 659 660 sc->sc_dz.dz_sc = sc; 661 sc->sc_dz.dz_line = 0; 662 sc->sc_dz.dz_tty = tty_alloc(); 663 664 evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, NULL, 665 device_xname(self), "rintr"); 666 evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, NULL, 667 device_xname(self), "tintr"); 668 669 /* Initialize hw regs */ 670 #if 0 671 DZ_WRITE_WORD(dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE); 672 DZ_WRITE_BYTE(dr_dtr, 0); 673 DZ_WRITE_BYTE(dr_break, 0); 674 #endif 675 676 /* Switch the console to virtual mode */ 677 dzcn = sc->sc_dr; 678 /* And test it */ 679 printf("\n"); 680 } 681 682 static int 683 dz_ebus_getmajor(void) 684 { 685 extern const struct cdevsw dz_cdevsw; 686 static int cache = -1; 687 688 if (cache != -1) 689 return cache; 690 691 return cache = cdevsw_lookup_major(&dz_cdevsw); 692 } 693 694 int 695 dz_ebus_intr(void *cookie, void *f) 696 { 697 struct dz_softc *sc; 698 struct _Usart *dzr; 699 uint32_t csr; 700 701 sc = cookie; 702 dzr = sc->sc_dr; 703 704 #define USI_INTERRUPTS (USI_INTRS|USI_TXRDY) 705 706 for (; ((csr = (dzr->ChannelStatus & dzr->IntrMask)) & 707 USI_INTERRUPTS) != 0;) { 708 if ((csr & USI_INTRS) != 0) 709 dzrint(sc, csr); 710 if ((csr & USI_TXRDY) != 0) 711 dzxint(sc, csr); 712 } 713 714 return 0; 715 } 716 717 void 718 dz_ebus_cnsetup(paddr_t addr) 719 { 720 721 dzcn = (struct _Usart *)addr; 722 723 #if 0 724 /* 725 * Initialize enough to xmit/recv via polling. 726 * Bootloader might or might not have done it. 727 */ 728 dzcn->Control = 729 USC_RXEN | 730 USC_TXEN | 731 USC_BPC_8 | 732 USC_NONE | 733 USC_1STOP | 734 USC_CLKDIV_4; 735 dzcn->Baud = 0x29; /* 38400 */ 736 #endif 737 738 /* 739 * Point the console at us 740 */ 741 cn_tab = &dz_ebus_consdev; 742 cn_tab->cn_pri = CN_NORMAL;/*CN_REMOTE?*/ 743 cn_tab->cn_dev = makedev(dz_ebus_getmajor(), 0); 744 } 745 746 void 747 dz_ebus_cninit(struct consdev *cn) 748 { 749 } 750 751 int 752 dz_ebus_cngetc(dev_t dev) 753 { 754 int c, s; 755 756 c = 0; 757 s = spltty(); 758 759 while ((dzcn->ChannelStatus & USI_RXRDY) == 0) 760 DELAY(10); 761 c = dzcn->RxData; 762 763 splx(s); 764 if (c == 13) /* map cr->ln */ 765 c = 10; 766 return c; 767 } 768 769 int dzflipped = 0; 770 void 771 dz_ebus_cnputc(dev_t dev, int ch) 772 { 773 int timeout, s; 774 775 /* Don't hang the machine! */ 776 timeout = 1 << 15; 777 778 s = spltty(); 779 780 #if 1 781 /* Keep wired to hunt for a bug */ 782 if (dzcn && (dzcn != (struct _Usart *)0xfff90000)) { 783 dzcn = (struct _Usart *)0xfff90000; 784 dzflipped++; 785 } 786 #endif 787 788 /* Wait until ready */ 789 while ((dzcn->ChannelStatus & USI_TXRDY) == 0) 790 if (--timeout < 0) 791 break; 792 793 /* Put the character */ 794 dzcn->TxData = ch; 795 796 splx(s); 797 } 798 799 /* 800 * Called before/after going into poll mode 801 */ 802 void 803 dz_ebus_cnpollc(dev_t dev, int on) 804 { 805 } 806