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