1 /* $NetBSD: dz_ebus.c,v 1.10 2019/12/27 06:52:43 msaitoh 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.10 2019/12/27 06:52:43 msaitoh 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; /* receive 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 .d_open = dzopen, 115 .d_close = dzclose, 116 .d_read = dzread, 117 .d_write = dzwrite, 118 .d_ioctl = dzioctl, 119 .d_stop = dzstop, 120 .d_tty = dztty, 121 .d_poll = dzpoll, 122 .d_mmap = nommap, 123 .d_kqfilter = ttykqfilter, 124 .d_discard = nodiscard, 125 .d_flag = D_TTY 126 }; 127 128 int 129 dzopen(dev_t dev, int flag, int mode, struct lwp *l) 130 { 131 struct tty *tp; 132 int unit, line; 133 struct dz_softc *sc; 134 int s, error = 0; 135 136 unit = DZ_I2C(minor(dev)); 137 sc = device_lookup_private(&dz_cd, unit); 138 if (sc == NULL) 139 return ENXIO; 140 141 line = DZ_PORT(minor(dev)); 142 if (line > 0) /* FIXME for more than one line */ 143 return ENXIO; 144 145 tp = sc->sc_dz.dz_tty; 146 if (tp == NULL) 147 return ENODEV; 148 tp->t_oproc = dzstart; 149 tp->t_param = dzparam; 150 tp->t_dev = dev; 151 152 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 153 return (EBUSY); 154 155 if ((tp->t_state & TS_ISOPEN) == 0) { 156 ttychars(tp); 157 if (tp->t_ispeed == 0) { 158 tp->t_iflag = TTYDEF_IFLAG; 159 tp->t_oflag = TTYDEF_OFLAG; 160 tp->t_cflag = TTYDEF_CFLAG; 161 tp->t_lflag = TTYDEF_LFLAG; 162 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 163 } 164 (void)dzparam(tp, &tp->t_termios); 165 ttsetwater(tp); 166 } 167 /* we have no modem control but..*/ 168 if (dzmctl(sc, line, TIOCM_DTR, DMBIS) & TIOCM_CD) 169 tp->t_state |= TS_CARR_ON; 170 s = spltty(); 171 while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 172 !(tp->t_state & TS_CARR_ON)) { 173 tp->t_wopen++; 174 error = ttysleep(tp, &tp->t_rawcv, true, 0); 175 tp->t_wopen--; 176 if (error) 177 break; 178 } 179 (void)splx(s); 180 if (error) 181 return error; 182 return (*tp->t_linesw->l_open)(dev, tp); 183 } 184 185 int 186 dzclose(dev_t dev, int flag, int mode, struct lwp *l) 187 { 188 struct dz_softc *sc; 189 struct tty *tp; 190 int unit, line; 191 192 unit = DZ_I2C(minor(dev)); 193 sc = device_lookup_private(&dz_cd, unit); 194 line = DZ_PORT(minor(dev)); 195 196 tp = sc->sc_dz.dz_tty; 197 198 (*tp->t_linesw->l_close)(tp, flag); 199 200 /* Make sure a BREAK state is not left enabled. */ 201 (void)dzmctl(sc, line, TIOCM_BRK, DMBIC); 202 203 /* Do a hangup if so required. */ 204 if ((tp->t_cflag & HUPCL) || tp->t_wopen || !(tp->t_state & TS_ISOPEN)) 205 (void)dzmctl(sc, line, 0, DMSET); 206 207 return ttyclose(tp); 208 } 209 210 int 211 dzread(dev_t dev, struct uio *uio, int flag) 212 { 213 struct tty *tp; 214 struct dz_softc *sc; 215 216 sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev))); 217 218 tp = sc->sc_dz.dz_tty; 219 return (*tp->t_linesw->l_read)(tp, uio, flag); 220 } 221 222 int 223 dzwrite(dev_t dev, struct uio *uio, int flag) 224 { 225 struct tty *tp; 226 struct dz_softc *sc; 227 228 sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev))); 229 230 tp = sc->sc_dz.dz_tty; 231 return (*tp->t_linesw->l_write)(tp, uio, flag); 232 } 233 234 /*ARGSUSED*/ 235 int 236 dzioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 237 { 238 struct dz_softc *sc; 239 struct tty *tp; 240 int unit, line; 241 int error; 242 243 unit = DZ_I2C(minor(dev)); 244 line = 0; 245 sc = device_lookup_private(&dz_cd, unit); 246 tp = sc->sc_dz.dz_tty; 247 248 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 249 if (error >= 0) 250 return error; 251 252 error = ttioctl(tp, cmd, data, flag, l); 253 if (error >= 0) 254 return error; 255 256 switch (cmd) { 257 258 case TIOCSBRK: 259 (void)dzmctl(sc, line, TIOCM_BRK, DMBIS); 260 break; 261 262 case TIOCCBRK: 263 (void)dzmctl(sc, line, TIOCM_BRK, DMBIC); 264 break; 265 266 case TIOCSDTR: 267 (void)dzmctl(sc, line, TIOCM_DTR, DMBIS); 268 break; 269 270 case TIOCCDTR: 271 (void)dzmctl(sc, line, TIOCM_DTR, DMBIC); 272 break; 273 274 case TIOCMSET: 275 (void)dzmctl(sc, line, *(int *)data, DMSET); 276 break; 277 278 case TIOCMBIS: 279 (void)dzmctl(sc, line, *(int *)data, DMBIS); 280 break; 281 282 case TIOCMBIC: 283 (void)dzmctl(sc, line, *(int *)data, DMBIC); 284 break; 285 286 case TIOCMGET: 287 *(int *)data = dzmctl(sc, line, 0, DMGET) & ~TIOCM_BRK; 288 break; 289 290 default: 291 return EPASSTHROUGH; 292 } 293 return 0; 294 } 295 296 /*ARGSUSED*/ 297 void 298 dzstop(struct tty *tp, int flag) 299 { 300 301 if (tp->t_state & TS_BUSY) 302 if (!(tp->t_state & TS_TTSTOP)) 303 tp->t_state |= TS_FLUSH; 304 } 305 306 struct tty * 307 dztty(dev_t dev) 308 { 309 struct dz_softc *sc; 310 struct tty *tp; 311 312 sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev))); 313 tp = sc->sc_dz.dz_tty; 314 315 return tp; 316 } 317 318 int 319 dzpoll(dev_t dev, int events, struct lwp *l) 320 { 321 struct dz_softc *sc; 322 struct tty *tp; 323 324 sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev))); 325 326 tp = sc->sc_dz.dz_tty; 327 return (*tp->t_linesw->l_poll)(tp, events, l); 328 } 329 330 void 331 dzstart(struct tty *tp) 332 { 333 struct dz_softc *sc; 334 struct clist *cl; 335 int unit, s; 336 337 unit = DZ_I2C(minor(tp->t_dev)); 338 sc = device_lookup_private(&dz_cd, unit); 339 340 s = spltty(); 341 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) { 342 splx(s); 343 return; 344 } 345 cl = &tp->t_outq; 346 ttypull(tp); 347 if (cl->c_cc == 0) { 348 splx(s); 349 return; 350 } 351 352 tp->t_state |= TS_BUSY; 353 354 /* was idle, get it started */ 355 dzxint(sc,USI_TXRDY); 356 splx(s); 357 } 358 359 static int rclk = 25000000; /* BUGBUGBUGBUG */ 360 361 static int 362 dzdivisor(int baudrate) 363 { 364 int act_baud, divisor, error; 365 366 if (baudrate <= 0) 367 return 0; 368 369 divisor = (rclk / 8) / (baudrate); 370 divisor = (divisor / 2) + (divisor & 1); 371 372 if (divisor <= 0) 373 return -1; 374 act_baud = rclk / (divisor * 16); 375 376 /* 10 times error in percent: */ 377 error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1; 378 379 /* 3.0% maximum error tolerance: */ 380 if (error < -30 || error > 30) 381 return -1; 382 383 return divisor; 384 } 385 386 static int 387 dzparam(struct tty *tp, struct termios *t) 388 { 389 struct dz_softc *sc; 390 int cflag = t->c_cflag; 391 int unit, line; 392 int speed; 393 unsigned lpr; 394 int s; 395 struct _Usart *dzr; 396 397 unit = DZ_I2C(minor(tp->t_dev)); 398 line = DZ_PORT(minor(tp->t_dev)); 399 sc = device_lookup_private(&dz_cd, unit); 400 401 /* check requested parameters */ 402 if (t->c_ispeed != t->c_ospeed) 403 return EINVAL; 404 speed = dzdivisor(t->c_ispeed); 405 if (speed < 0) 406 return EINVAL; 407 408 tp->t_ispeed = t->c_ispeed; 409 tp->t_ospeed = t->c_ospeed; 410 tp->t_cflag = cflag; 411 412 { 413 /* XXX */ 414 static int didit = 0; 415 if (!didit && t->c_ispeed != 38400) 416 printf("dzparam: c_ispeed %d ignored, keeping 38400\n", 417 t->c_ispeed); 418 didit = 1; 419 } 420 speed = dzdivisor(38400); 421 422 if (speed == 0) { 423 (void)dzmctl(sc, line, 0, DMSET); /* hang up line */ 424 return 0; 425 } 426 427 switch (cflag & CSIZE) { 428 case CS5: 429 lpr = USC_BPC_5; 430 break; 431 case CS6: 432 lpr = USC_BPC_6; 433 break; 434 case CS7: 435 lpr = USC_BPC_7; 436 break; 437 default: 438 lpr = USC_BPC_8; 439 break; 440 } 441 if (cflag & CSTOPB) 442 lpr |= USC_2STOP; 443 444 if (cflag & PARENB) { 445 if (cflag & PARODD) 446 lpr |= USC_ODD; 447 else 448 lpr |= USC_EVEN; 449 } else 450 lpr |= USC_NONE; 451 452 s = spltty(); 453 454 dzr = sc->sc_dr; 455 456 dzr->Baud = speed; 457 dzr->Control = USC_CLKDIV_4 | USC_TXEN | USC_RXEN | lpr; 458 #define USI_INTRS (USI_RXRDY|USI_RXBRK|USI_OVRE|USI_FRAME|USI_PARE) 459 dzr->IntrEnable = USI_INTRS; 460 461 (void)splx(s); 462 return 0; 463 } 464 465 static unsigned 466 dzmctl(struct dz_softc *sc, int line, int bits, int how) 467 { 468 unsigned int mbits; 469 int s; 470 struct _Usart *dzr; 471 472 mbits = 0; 473 474 s = spltty(); 475 476 dzr = sc->sc_dr; 477 478 /* we have no modem control bits (CD,RI,DTR,DSR,..) */ 479 mbits |= TIOCM_CD; 480 mbits |= TIOCM_DTR; 481 482 if (dzr->ChannelStatus & USI_RXBRK) 483 mbits |= TIOCM_BRK; 484 485 switch (how) { 486 case DMSET: 487 mbits = bits; 488 break; 489 490 case DMBIS: 491 mbits |= bits; 492 break; 493 494 case DMBIC: 495 mbits &= ~bits; 496 break; 497 498 case DMGET: 499 (void)splx(s); 500 return mbits; 501 } 502 503 /* BUGBUG work in progress */ 504 if (mbits & TIOCM_BRK) { 505 sc->sc_brk |= (1 << line); 506 dzr->Control |= USC_STTBRK; 507 } else { 508 sc->sc_brk &= ~(1 << line); 509 dzr->Control |= USC_STPBRK; 510 } 511 512 (void)splx(s); 513 return mbits; 514 } 515 516 517 #if defined(DDB) 518 int dz_ddb = 0; 519 #endif 520 521 /* Receiver Interrupt */ 522 523 void 524 dzrint(struct dz_softc *sc, uint32_t csr) 525 { 526 struct tty *tp; 527 int cc; 528 struct _Usart *dzr; 529 530 sc->sc_rxint++; 531 dzr = sc->sc_dr; 532 533 cc = dzr->RxData; 534 tp = sc->sc_dz.dz_tty; 535 536 /* clear errors before we print or bail out */ 537 if (csr & (USI_OVRE|USI_FRAME|USI_PARE)) 538 dzr->Control = USC_RSTSTA; 539 540 if (!(tp->t_state & TS_ISOPEN)) { 541 wakeup(&tp->t_rawq); 542 return; 543 } 544 545 if (csr & USI_OVRE) { 546 log(LOG_WARNING, "%s: silo overflow, line %d\n", 547 device_xname(sc->sc_dev), 0); 548 } 549 550 if (csr & USI_FRAME) 551 cc |= TTY_FE; 552 if (csr & USI_PARE) 553 cc |= TTY_PE; 554 555 #if defined(DDB) 556 /* ^P drops into DDB */ 557 if (dz_ddb && (cc == 0x10)) 558 Debugger(); 559 #endif 560 (*tp->t_linesw->l_rint)(cc, tp); 561 } 562 563 /* Transmitter Interrupt */ 564 565 void 566 dzxint(struct dz_softc *sc, uint32_t csr) 567 { 568 struct tty *tp; 569 struct clist *cl; 570 int ch; 571 struct _Usart *dzr; 572 573 dzr = sc->sc_dr; 574 575 tp = sc->sc_dz.dz_tty; 576 cl = &tp->t_outq; 577 tp->t_state &= ~TS_BUSY; 578 579 /* Just send out a char if we have one */ 580 if (cl->c_cc) { 581 tp->t_state |= TS_BUSY; 582 ch = getc(cl); 583 dzr->TxData = ch; 584 dzr->IntrEnable = USI_TXRDY; 585 return; 586 } 587 588 /* Nothing to send; turn off intr */ 589 dzr->IntrDisable = USI_TXRDY; 590 591 if (tp->t_state & TS_FLUSH) 592 tp->t_state &= ~TS_FLUSH; 593 else 594 ndflush(&tp->t_outq, cl->c_cc); 595 596 (*tp->t_linesw->l_start)(tp); 597 } 598 599 /* 600 * Machdep part of the driver 601 */ 602 int dz_ebus_match(device_t, cfdata_t, void *); 603 void dz_ebus_attach(device_t, device_t, void *); 604 int dz_ebus_intr(void *, void *); 605 606 void dz_ebus_cnsetup(paddr_t); 607 void dz_ebus_cninit(struct consdev *); 608 int dz_ebus_cngetc(dev_t); 609 void dz_ebus_cnputc(dev_t, int); 610 void dz_ebus_cnpollc(dev_t, int); 611 612 static int dz_ebus_getmajor(void); 613 614 CFATTACH_DECL_NEW(dz_ebus, sizeof(struct dz_softc), 615 dz_ebus_match, dz_ebus_attach, NULL, NULL); 616 617 struct consdev dz_ebus_consdev = { 618 NULL, dz_ebus_cninit, dz_ebus_cngetc, dz_ebus_cnputc, 619 dz_ebus_cnpollc, NULL, NULL, NULL, NODEV, CN_NORMAL, 620 }; 621 622 /* 623 * Points to the console regs. Special mapping until VM is turned on. 624 */ 625 struct _Usart *dzcn; 626 627 int 628 dz_ebus_match(device_t parent, cfdata_t cf, void *aux) 629 { 630 struct ebus_attach_args *iba; 631 struct _Usart *us; 632 633 iba = aux; 634 635 if (strcmp(iba->ia_name, "dz") != 0) 636 return 0; 637 638 us = (struct _Usart *)iba->ia_vaddr; 639 if ((us == NULL) || 640 (us->Tag != PMTTAG_USART)) 641 return 0; 642 643 return 1; 644 } 645 646 void 647 dz_ebus_attach(device_t parent, device_t self, void *aux) 648 { 649 struct ebus_attach_args *iba; 650 struct dz_softc *sc; 651 652 sc = device_private(self); 653 iba = aux; 654 655 sc->sc_dev = self; 656 sc->sc_dr = (struct _Usart *)iba->ia_vaddr; 657 #if DEBUG 658 printf(" virt=%p ", (void *)sc->sc_dr); 659 #endif 660 661 printf(": neilsart 1 line"); 662 ebus_intr_establish(parent, (void *)iba->ia_cookie, IPL_TTY, 663 dz_ebus_intr, sc); 664 665 sc->sc_rxint = sc->sc_brk = 0; 666 sc->sc_consline = 0; 667 668 /* Initialize our softc structure. Should be done in open? */ 669 670 sc->sc_dz.dz_sc = sc; 671 sc->sc_dz.dz_line = 0; 672 sc->sc_dz.dz_tty = tty_alloc(); 673 674 evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, NULL, 675 device_xname(self), "rintr"); 676 evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, NULL, 677 device_xname(self), "tintr"); 678 679 /* Initialize hw regs */ 680 #if 0 681 DZ_WRITE_WORD(dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE); 682 DZ_WRITE_BYTE(dr_dtr, 0); 683 DZ_WRITE_BYTE(dr_break, 0); 684 #endif 685 686 /* Switch the console to virtual mode */ 687 dzcn = sc->sc_dr; 688 /* And test it */ 689 printf("\n"); 690 } 691 692 static int 693 dz_ebus_getmajor(void) 694 { 695 extern const struct cdevsw dz_cdevsw; 696 static int cache = -1; 697 698 if (cache != -1) 699 return cache; 700 701 return cache = cdevsw_lookup_major(&dz_cdevsw); 702 } 703 704 int 705 dz_ebus_intr(void *cookie, void *f) 706 { 707 struct dz_softc *sc; 708 struct _Usart *dzr; 709 uint32_t csr; 710 711 sc = cookie; 712 dzr = sc->sc_dr; 713 714 #define USI_INTERRUPTS (USI_INTRS|USI_TXRDY) 715 716 for (; ((csr = (dzr->ChannelStatus & dzr->IntrMask)) & 717 USI_INTERRUPTS) != 0;) { 718 if ((csr & USI_INTRS) != 0) 719 dzrint(sc, csr); 720 if ((csr & USI_TXRDY) != 0) 721 dzxint(sc, csr); 722 } 723 724 return 0; 725 } 726 727 void 728 dz_ebus_cnsetup(paddr_t addr) 729 { 730 731 dzcn = (struct _Usart *)addr; 732 733 #if 0 734 /* 735 * Initialize enough to xmit/recv via polling. 736 * Bootloader might or might not have done it. 737 */ 738 dzcn->Control = 739 USC_RXEN | 740 USC_TXEN | 741 USC_BPC_8 | 742 USC_NONE | 743 USC_1STOP | 744 USC_CLKDIV_4; 745 dzcn->Baud = 0x29; /* 38400 */ 746 #endif 747 748 /* 749 * Point the console at us 750 */ 751 cn_tab = &dz_ebus_consdev; 752 cn_tab->cn_pri = CN_NORMAL;/*CN_REMOTE?*/ 753 cn_tab->cn_dev = makedev(dz_ebus_getmajor(), 0); 754 } 755 756 void 757 dz_ebus_cninit(struct consdev *cn) 758 { 759 } 760 761 int 762 dz_ebus_cngetc(dev_t dev) 763 { 764 int c, s; 765 766 c = 0; 767 s = spltty(); 768 769 while ((dzcn->ChannelStatus & USI_RXRDY) == 0) 770 DELAY(10); 771 c = dzcn->RxData; 772 773 splx(s); 774 if (c == 13) /* map cr->ln */ 775 c = 10; 776 return c; 777 } 778 779 int dzflipped = 0; 780 void 781 dz_ebus_cnputc(dev_t dev, int ch) 782 { 783 int timeout, s; 784 785 /* Don't hang the machine! */ 786 timeout = 1 << 15; 787 788 s = spltty(); 789 790 #if 1 791 /* Keep wired to hunt for a bug */ 792 if (dzcn && (dzcn != (struct _Usart *)0xfff90000)) { 793 dzcn = (struct _Usart *)0xfff90000; 794 dzflipped++; 795 } 796 #endif 797 798 /* Wait until ready */ 799 while ((dzcn->ChannelStatus & USI_TXRDY) == 0) 800 if (--timeout < 0) 801 break; 802 803 /* Put the character */ 804 dzcn->TxData = ch; 805 806 splx(s); 807 } 808 809 /* 810 * Called before/after going into poll mode 811 */ 812 void 813 dz_ebus_cnpollc(dev_t dev, int on) 814 { 815 } 816