1 /* $NetBSD: dz_ebus.c,v 1.5 2011/06/12 05:22:30 tsutsui 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.5 2011/06/12 05:22:30 tsutsui 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, mcc; 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 if (csr & USI_RXBRK) 527 mcc = CNC_BREAK; 528 else 529 mcc = cc; 530 531 /* clear errors before we print or bail out */ 532 if (csr & (USI_OVRE|USI_FRAME|USI_PARE)) 533 dzr->Control = USC_RSTSTA; 534 535 if (!(tp->t_state & TS_ISOPEN)) { 536 wakeup(&tp->t_rawq); 537 return; 538 } 539 540 if (csr & USI_OVRE) { 541 log(LOG_WARNING, "%s: silo overflow, line %d\n", 542 device_xname(sc->sc_dev), 0); 543 } 544 545 if (csr & USI_FRAME) 546 cc |= TTY_FE; 547 if (csr & USI_PARE) 548 cc |= TTY_PE; 549 550 #if defined(DDB) 551 /* ^P drops into DDB */ 552 if (dz_ddb && (cc == 0x10)) 553 Debugger(); 554 #endif 555 (*tp->t_linesw->l_rint)(cc, tp); 556 } 557 558 /* Transmitter Interrupt */ 559 560 void 561 dzxint(struct dz_softc *sc, uint32_t csr) 562 { 563 struct tty *tp; 564 struct clist *cl; 565 int ch; 566 struct _Usart *dzr; 567 568 dzr = sc->sc_dr; 569 570 tp = sc->sc_dz.dz_tty; 571 cl = &tp->t_outq; 572 tp->t_state &= ~TS_BUSY; 573 574 /* Just send out a char if we have one */ 575 if (cl->c_cc) { 576 tp->t_state |= TS_BUSY; 577 ch = getc(cl); 578 dzr->TxData = ch; 579 dzr->IntrEnable = USI_TXRDY; 580 return; 581 } 582 583 /* Nothing to send; turn off intr */ 584 dzr->IntrDisable = USI_TXRDY; 585 586 if (tp->t_state & TS_FLUSH) 587 tp->t_state &= ~TS_FLUSH; 588 else 589 ndflush(&tp->t_outq, cl->c_cc); 590 591 (*tp->t_linesw->l_start)(tp); 592 } 593 594 /* 595 * Machdep part of the driver 596 */ 597 int dz_ebus_match(device_t, cfdata_t, void *); 598 void dz_ebus_attach(device_t, device_t, void *); 599 int dz_ebus_intr(void *, void *); 600 601 void dz_ebus_cnsetup(paddr_t); 602 void dz_ebus_cninit(struct consdev *); 603 int dz_ebus_cngetc(dev_t); 604 void dz_ebus_cnputc(dev_t, int); 605 void dz_ebus_cnpollc(dev_t, int); 606 607 static int dz_ebus_getmajor(void); 608 609 CFATTACH_DECL_NEW(dz_ebus, sizeof(struct dz_softc), 610 dz_ebus_match, dz_ebus_attach, NULL, NULL); 611 612 struct consdev dz_ebus_consdev = { 613 NULL, dz_ebus_cninit, dz_ebus_cngetc, dz_ebus_cnputc, 614 dz_ebus_cnpollc, NULL, NULL, NULL, NODEV, CN_NORMAL, 615 }; 616 617 /* 618 * Points to the console regs. Special mapping until VM is turned on. 619 */ 620 struct _Usart *dzcn; 621 622 int 623 dz_ebus_match(device_t parent, cfdata_t cf, void *aux) 624 { 625 struct ebus_attach_args *iba; 626 struct _Usart *us; 627 628 iba = aux; 629 630 if (strcmp(iba->ia_name, "dz") != 0) 631 return 0; 632 633 us = (struct _Usart *)iba->ia_vaddr; 634 if ((us == NULL) || 635 (us->Tag != PMTTAG_USART)) 636 return 0; 637 638 return 1; 639 } 640 641 void 642 dz_ebus_attach(device_t parent, device_t self, void *aux) 643 { 644 struct ebus_attach_args *iba; 645 struct dz_softc *sc; 646 647 sc = device_private(self); 648 iba = aux; 649 650 sc->sc_dev = self; 651 sc->sc_dr = (struct _Usart *)iba->ia_vaddr; 652 #if DEBUG 653 printf(" virt=%p ", (void *)sc->sc_dr); 654 #endif 655 656 printf(": neilsart 1 line"); 657 ebus_intr_establish(parent, (void *)iba->ia_cookie, IPL_TTY, 658 dz_ebus_intr, sc); 659 660 sc->sc_rxint = sc->sc_brk = 0; 661 sc->sc_consline = 0; 662 663 /* Initialize our softc structure. Should be done in open? */ 664 665 sc->sc_dz.dz_sc = sc; 666 sc->sc_dz.dz_line = 0; 667 sc->sc_dz.dz_tty = tty_alloc(); 668 669 evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, NULL, 670 device_xname(self), "rintr"); 671 evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, NULL, 672 device_xname(self), "tintr"); 673 674 /* Initialize hw regs */ 675 #if 0 676 DZ_WRITE_WORD(dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE); 677 DZ_WRITE_BYTE(dr_dtr, 0); 678 DZ_WRITE_BYTE(dr_break, 0); 679 #endif 680 681 /* Switch the console to virtual mode */ 682 dzcn = sc->sc_dr; 683 /* And test it */ 684 printf("\n"); 685 } 686 687 static int 688 dz_ebus_getmajor(void) 689 { 690 extern const struct cdevsw dz_cdevsw; 691 static int cache = -1; 692 693 if (cache != -1) 694 return cache; 695 696 return cache = cdevsw_lookup_major(&dz_cdevsw); 697 } 698 699 int 700 dz_ebus_intr(void *cookie, void *f) 701 { 702 struct dz_softc *sc; 703 struct _Usart *dzr; 704 uint32_t csr; 705 706 sc = cookie; 707 dzr = sc->sc_dr; 708 709 #define USI_INTERRUPTS (USI_INTRS|USI_TXRDY) 710 711 for (; ((csr = (dzr->ChannelStatus & dzr->IntrMask)) & 712 USI_INTERRUPTS) != 0;) { 713 if ((csr & USI_INTRS) != 0) 714 dzrint(sc, csr); 715 if ((csr & USI_TXRDY) != 0) 716 dzxint(sc, csr); 717 } 718 719 return 0; 720 } 721 722 void 723 dz_ebus_cnsetup(paddr_t addr) 724 { 725 726 dzcn = (struct _Usart *)addr; 727 728 #if 0 729 /* 730 * Initialize enough to xmit/recv via polling. 731 * Bootloader might or might not have done it. 732 */ 733 dzcn->Control = 734 USC_RXEN | 735 USC_TXEN | 736 USC_BPC_8 | 737 USC_NONE | 738 USC_1STOP | 739 USC_CLKDIV_4; 740 dzcn->Baud = 0x29; /* 38400 */ 741 #endif 742 743 /* 744 * Point the console at us 745 */ 746 cn_tab = &dz_ebus_consdev; 747 cn_tab->cn_pri = CN_NORMAL;/*CN_REMOTE?*/ 748 cn_tab->cn_dev = makedev(dz_ebus_getmajor(), 0); 749 } 750 751 void 752 dz_ebus_cninit(struct consdev *cn) 753 { 754 } 755 756 int 757 dz_ebus_cngetc(dev_t dev) 758 { 759 int c, s; 760 761 c = 0; 762 s = spltty(); 763 764 while ((dzcn->ChannelStatus & USI_RXRDY) == 0) 765 DELAY(10); 766 c = dzcn->RxData; 767 768 splx(s); 769 if (c == 13) /* map cr->ln */ 770 c = 10; 771 return c; 772 } 773 774 int dzflipped = 0; 775 void 776 dz_ebus_cnputc(dev_t dev, int ch) 777 { 778 int timeout, s; 779 780 /* Don't hang the machine! */ 781 timeout = 1 << 15; 782 783 s = spltty(); 784 785 #if 1 786 /* Keep wired to hunt for a bug */ 787 if (dzcn && (dzcn != (struct _Usart *)0xfff90000)) { 788 dzcn = (struct _Usart *)0xfff90000; 789 dzflipped++; 790 } 791 #endif 792 793 /* Wait until ready */ 794 while ((dzcn->ChannelStatus & USI_TXRDY) == 0) 795 if (--timeout < 0) 796 break; 797 798 /* Put the character */ 799 dzcn->TxData = ch; 800 801 splx(s); 802 } 803 804 /* 805 * Called before/after going into poll mode 806 */ 807 void 808 dz_ebus_cnpollc(dev_t dev, int on) 809 { 810 } 811