1 /* $NetBSD: footbridge_com.c,v 1.2 2001/09/05 16:17:35 matt Exp $ */ 2 3 /*- 4 * Copyright (c) 1997 Mark Brinicombe 5 * Copyright (c) 1997 Causality Limited 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Mark Brinicombe 18 * for the NetBSD Project. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * COM driver, using the footbridge UART 36 */ 37 38 #include "opt_ddb.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/ioctl.h> 43 #include <sys/select.h> 44 #include <sys/tty.h> 45 #include <sys/proc.h> 46 #include <sys/conf.h> 47 #include <sys/syslog.h> 48 #include <sys/device.h> 49 #include <sys/malloc.h> 50 #include <sys/termios.h> 51 #include <machine/bus.h> 52 #include <machine/intr.h> 53 #include <arm/footbridge/dc21285mem.h> 54 #include <arm/footbridge/dc21285reg.h> 55 #include <arm/footbridge/footbridgevar.h> 56 57 #include <dev/cons.h> 58 59 #include "fcom.h" 60 61 extern u_int dc21285_fclk; 62 63 #ifdef DDB 64 /* 65 * Define the keycode recognised as a request to call the debugger 66 * A value of 0 disables the feature when DDB is built in 67 */ 68 #ifndef DDB_KEYCODE 69 #define DDB_KEYCODE 0 70 #endif /* DDB_KEYCODE */ 71 #endif /* DDB */ 72 73 struct fcom_softc { 74 struct device sc_dev; 75 bus_space_tag_t sc_iot; 76 bus_space_handle_t sc_ioh; 77 void *sc_ih; 78 struct callout sc_softintr_ch; 79 int sc_rx_irq; 80 int sc_tx_irq; 81 int sc_hwflags; 82 #define HW_FLAG_CONSOLE 0x01 83 int sc_swflags; 84 int sc_l_ubrlcr; 85 int sc_m_ubrlcr; 86 int sc_h_ubrlcr; 87 char *sc_rxbuffer[2]; 88 char *sc_rxbuf; 89 int sc_rxpos; 90 int sc_rxcur; 91 struct tty *sc_tty; 92 }; 93 94 #define RX_BUFFER_SIZE 0x100 95 96 /* Macros to clear/set/test flags. */ 97 #define SET(t, f) (t) |= (f) 98 #define CLR(t, f) (t) &= ~(f) 99 #define ISSET(t, f) ((t) & (f)) 100 101 static int fcom_probe __P((struct device *, struct cfdata *, void *)); 102 static void fcom_attach __P((struct device *, struct device *, void *)); 103 104 int fcomopen __P((dev_t dev, int flag, int mode, struct proc *p)); 105 static int fcom_rxintr __P((void *)); 106 /*static int fcom_txintr __P((void *));*/ 107 108 /*struct consdev;*/ 109 /*void fcomcnprobe __P((struct consdev *)); 110 void fcomcninit __P((struct consdev *));*/ 111 int fcomcngetc __P((dev_t)); 112 void fcomcnputc __P((dev_t, int)); 113 void fcomcnpollc __P((dev_t, int)); 114 115 struct cfattach fcom_ca = { 116 sizeof(struct fcom_softc), fcom_probe, fcom_attach 117 }; 118 119 extern struct cfdriver fcom_cd; 120 121 void fcominit __P((bus_space_tag_t, bus_space_handle_t, int, int)); 122 void fcominitcons __P((bus_space_tag_t, bus_space_handle_t)); 123 124 bus_space_tag_t fcomconstag; 125 bus_space_handle_t fcomconsioh; 126 extern int comcnmode; 127 extern int comcnspeed; 128 129 #define COMUNIT(x) (minor(x)) 130 #ifndef CONUNIT 131 #define CONUNIT 0 132 #endif 133 134 /* 135 * The console is set up at init time, well in advance of the reset of the 136 * system and thus we have a private bus space tag for the console. 137 * 138 * The tag is provided by fcom_io.c and fcom_io_asm.S 139 */ 140 extern struct bus_space fcomcons_bs_tag; 141 142 /* 143 * int fcom_probe(struct device *parent, struct cfdata *cf, void *aux) 144 * 145 * Make sure we are trying to attach a com device and then 146 * probe for one. 147 */ 148 149 static int 150 fcom_probe(parent, cf, aux) 151 struct device *parent; 152 struct cfdata *cf; 153 void *aux; 154 { 155 union footbridge_attach_args *fba = aux; 156 157 if (strcmp(fba->fba_name, "fcom") == 0) 158 return(1); 159 return(0); 160 } 161 162 /* 163 * void fcom_attach(struct device *parent, struct device *self, void *aux) 164 * 165 * attach the com device 166 */ 167 168 static void 169 fcom_attach(parent, self, aux) 170 struct device *parent, *self; 171 void *aux; 172 { 173 union footbridge_attach_args *fba = aux; 174 struct fcom_softc *sc = (struct fcom_softc *)self; 175 176 /* Set up the softc */ 177 sc->sc_iot = fba->fba_fca.fca_iot; 178 sc->sc_ioh = fba->fba_fca.fca_ioh; 179 callout_init(&sc->sc_softintr_ch); 180 sc->sc_rx_irq = fba->fba_fca.fca_rx_irq; 181 sc->sc_tx_irq = fba->fba_fca.fca_tx_irq; 182 sc->sc_hwflags = 0; 183 sc->sc_swflags = 0; 184 185 /* If we have a console tag then make a note of it */ 186 if (fcomconstag) 187 sc->sc_hwflags |= HW_FLAG_CONSOLE; 188 189 if (sc->sc_hwflags & HW_FLAG_CONSOLE) { 190 int major; 191 192 /* locate the major number */ 193 for (major = 0; major < nchrdev; ++major) 194 if (cdevsw[major].d_open == fcomopen) 195 break; 196 197 cn_tab->cn_dev = makedev(major, sc->sc_dev.dv_unit); 198 printf(": console"); 199 } 200 printf("\n"); 201 202 sc->sc_ih = intr_claim(sc->sc_rx_irq, IPL_SERIAL, "serial rx", 203 fcom_rxintr, sc); 204 if (sc->sc_ih == NULL) 205 panic("%s: Cannot install rx interrupt handler\n", 206 sc->sc_dev.dv_xname); 207 } 208 209 static void fcomstart __P((struct tty *)); 210 static int fcomparam __P((struct tty *, struct termios *)); 211 212 int 213 fcomopen(dev, flag, mode, p) 214 dev_t dev; 215 int flag, mode; 216 struct proc *p; 217 { 218 struct fcom_softc *sc; 219 int unit = minor(dev); 220 struct tty *tp; 221 222 if (unit >= fcom_cd.cd_ndevs) 223 return ENXIO; 224 sc = fcom_cd.cd_devs[unit]; 225 if (!sc) 226 return ENXIO; 227 if (!(tp = sc->sc_tty)) 228 sc->sc_tty = tp = ttymalloc(); 229 if (!sc->sc_rxbuffer[0]) { 230 sc->sc_rxbuffer[0] = malloc(RX_BUFFER_SIZE, M_DEVBUF, M_WAITOK); 231 sc->sc_rxbuffer[1] = malloc(RX_BUFFER_SIZE, M_DEVBUF, M_WAITOK); 232 sc->sc_rxpos = 0; 233 sc->sc_rxcur = 0; 234 sc->sc_rxbuf = sc->sc_rxbuffer[sc->sc_rxcur]; 235 if (!sc->sc_rxbuf) 236 panic("%s: Cannot allocate rx buffer memory", 237 sc->sc_dev.dv_xname); 238 } 239 tp->t_oproc = fcomstart; 240 tp->t_param = fcomparam; 241 tp->t_dev = dev; 242 if (!(tp->t_state & TS_ISOPEN && tp->t_wopen == 0)) { 243 ttychars(tp); 244 tp->t_cflag = TTYDEF_CFLAG; 245 tp->t_iflag = TTYDEF_IFLAG; 246 tp->t_oflag = TTYDEF_OFLAG; 247 tp->t_lflag = TTYDEF_LFLAG; 248 249 /* 250 * Initialize the termios status to the defaults. Add in the 251 * sticky bits from TIOCSFLAGS. 252 */ 253 tp->t_ispeed = 0; 254 if (ISSET(sc->sc_hwflags, HW_FLAG_CONSOLE)) 255 tp->t_ospeed = comcnspeed; 256 else 257 tp->t_ospeed = TTYDEF_SPEED; 258 259 fcomparam(tp, &tp->t_termios); 260 ttsetwater(tp); 261 } else if ((tp->t_state&TS_XCLUDE) && suser(p->p_ucred, &p->p_acflag)) 262 return EBUSY; 263 tp->t_state |= TS_CARR_ON; 264 265 return (*tp->t_linesw->l_open)(dev, tp); 266 } 267 268 int 269 fcomclose(dev, flag, mode, p) 270 dev_t dev; 271 int flag, mode; 272 struct proc *p; 273 { 274 struct fcom_softc *sc = fcom_cd.cd_devs[minor(dev)]; 275 struct tty *tp = sc->sc_tty; 276 /* XXX This is for cons.c. */ 277 if (!ISSET(tp->t_state, TS_ISOPEN)) 278 return (0); 279 280 (*tp->t_linesw->l_close)(tp, flag); 281 ttyclose(tp); 282 #ifdef DIAGNOSTIC 283 if (sc->sc_rxbuffer[0] == NULL) 284 panic("fcomclose: rx buffers not allocated\n"); 285 #endif /* DIAGNOSTIC */ 286 free(sc->sc_rxbuffer[0], M_DEVBUF); 287 free(sc->sc_rxbuffer[1], M_DEVBUF); 288 sc->sc_rxbuffer[0] = NULL; 289 sc->sc_rxbuffer[1] = NULL; 290 291 return 0; 292 } 293 294 int 295 fcomread(dev, uio, flag) 296 dev_t dev; 297 struct uio *uio; 298 int flag; 299 { 300 struct fcom_softc *sc = fcom_cd.cd_devs[minor(dev)]; 301 struct tty *tp = sc->sc_tty; 302 303 return (*tp->t_linesw->l_read)(tp, uio, flag); 304 } 305 306 int 307 fcomwrite(dev, uio, flag) 308 dev_t dev; 309 struct uio *uio; 310 int flag; 311 { 312 struct fcom_softc *sc = fcom_cd.cd_devs[minor(dev)]; 313 struct tty *tp = sc->sc_tty; 314 315 return (*tp->t_linesw->l_write)(tp, uio, flag); 316 } 317 318 int 319 fcompoll(dev, events, p) 320 dev_t dev; 321 int events; 322 struct proc *p; 323 { 324 struct fcom_softc *sc = fcom_cd.cd_devs[minor(dev)]; 325 struct tty *tp = sc->sc_tty; 326 327 return ((*tp->t_linesw->l_poll)(tp, events, p)); 328 } 329 330 int 331 fcomioctl(dev, cmd, data, flag, p) 332 dev_t dev; 333 u_long cmd; 334 caddr_t data; 335 int flag; 336 struct proc *p; 337 { 338 struct fcom_softc *sc = fcom_cd.cd_devs[minor(dev)]; 339 struct tty *tp = sc->sc_tty; 340 int error; 341 342 if ((error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p)) >= 0) 343 return error; 344 if ((error = ttioctl(tp, cmd, data, flag, p)) >= 0) 345 return error; 346 347 switch (cmd) { 348 case TIOCGFLAGS: 349 *(int *)data = sc->sc_swflags; 350 break; 351 352 case TIOCSFLAGS: 353 error = suser(p->p_ucred, &p->p_acflag); 354 if (error) 355 return (error); 356 sc->sc_swflags = *(int *)data; 357 break; 358 } 359 360 return ENOTTY; 361 } 362 363 struct tty * 364 fcomtty(dev) 365 dev_t dev; 366 { 367 struct fcom_softc *sc = fcom_cd.cd_devs[minor(dev)]; 368 369 return sc->sc_tty; 370 } 371 372 void 373 fcomstop(tp, flag) 374 struct tty *tp; 375 int flag; 376 { 377 } 378 379 static void 380 fcomstart(tp) 381 struct tty *tp; 382 { 383 struct clist *cl; 384 int s, len; 385 u_char buf[64]; 386 int loop; 387 struct fcom_softc *sc = fcom_cd.cd_devs[minor(tp->t_dev)]; 388 bus_space_tag_t iot = sc->sc_iot; 389 bus_space_handle_t ioh = sc->sc_ioh; 390 int timo; 391 392 s = spltty(); 393 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { 394 (void)splx(s); 395 return; 396 } 397 tp->t_state |= TS_BUSY; 398 (void)splx(s); 399 400 /* s = splserial();*/ 401 /* wait for any pending transmission to finish */ 402 timo = 100000; 403 while ((bus_space_read_4(iot, ioh, UART_FLAGS) & UART_TX_BUSY) && --timo) 404 ; 405 406 s = splserial(); 407 if (bus_space_read_4(iot, ioh, UART_FLAGS) & UART_TX_BUSY) { 408 tp->t_state |= TS_TIMEOUT; 409 callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, tp); 410 (void)splx(s); 411 return; 412 } 413 414 (void)splx(s); 415 416 cl = &tp->t_outq; 417 len = q_to_b(cl, buf, 64); 418 for (loop = 0; loop < len; ++loop) { 419 /* s = splserial();*/ 420 421 bus_space_write_4(iot, ioh, UART_DATA, buf[loop]); 422 423 /* wait for this transmission to complete */ 424 timo = 100000; 425 while ((bus_space_read_4(iot, ioh, UART_FLAGS) & UART_TX_BUSY) && --timo) 426 ; 427 /* (void)splx(s);*/ 428 } 429 s = spltty(); 430 tp->t_state &= ~TS_BUSY; 431 if (cl->c_cc) { 432 tp->t_state |= TS_TIMEOUT; 433 callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, tp); 434 } 435 if (cl->c_cc <= tp->t_lowat) { 436 if (tp->t_state & TS_ASLEEP) { 437 tp->t_state &= ~TS_ASLEEP; 438 wakeup(cl); 439 } 440 selwakeup(&tp->t_wsel); 441 } 442 (void)splx(s); 443 } 444 445 static int 446 fcomparam(tp, t) 447 struct tty *tp; 448 struct termios *t; 449 { 450 struct fcom_softc *sc = fcom_cd.cd_devs[minor(tp->t_dev)]; 451 bus_space_tag_t iot = sc->sc_iot; 452 bus_space_handle_t ioh = sc->sc_ioh; 453 int baudrate; 454 int h_ubrlcr; 455 int m_ubrlcr; 456 int l_ubrlcr; 457 int s; 458 459 /* check requested parameters */ 460 if (t->c_ospeed < 0) 461 return (EINVAL); 462 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 463 return (EINVAL); 464 465 switch (t->c_ospeed) { 466 case B1200: 467 case B2400: 468 case B4800: 469 case B9600: 470 case B19200: 471 case B38400: 472 baudrate = UART_BRD(dc21285_fclk, t->c_ospeed); 473 break; 474 default: 475 baudrate = UART_BRD(dc21285_fclk, 9600); 476 break; 477 } 478 479 l_ubrlcr = baudrate & 0xff; 480 m_ubrlcr = (baudrate >> 8) & 0xf; 481 h_ubrlcr = 0; 482 483 switch (ISSET(t->c_cflag, CSIZE)) { 484 case CS5: 485 h_ubrlcr |= UART_DATA_BITS_5; 486 break; 487 case CS6: 488 h_ubrlcr |= UART_DATA_BITS_6; 489 break; 490 case CS7: 491 h_ubrlcr |= UART_DATA_BITS_7; 492 break; 493 case CS8: 494 h_ubrlcr |= UART_DATA_BITS_8; 495 break; 496 } 497 498 if (ISSET(t->c_cflag, PARENB)) { 499 h_ubrlcr |= UART_PARITY_ENABLE; 500 if (ISSET(t->c_cflag, PARODD)) 501 h_ubrlcr |= UART_ODD_PARITY; 502 else 503 h_ubrlcr |= UART_EVEN_PARITY; 504 } 505 506 if (ISSET(t->c_cflag, CSTOPB)) 507 h_ubrlcr |= UART_STOP_BITS_2; 508 509 bus_space_write_4(iot, ioh, UART_L_UBRLCR, l_ubrlcr); 510 bus_space_write_4(iot, ioh, UART_M_UBRLCR, m_ubrlcr); 511 bus_space_write_4(iot, ioh, UART_H_UBRLCR, h_ubrlcr); 512 513 s = splserial(); 514 515 sc->sc_l_ubrlcr = l_ubrlcr; 516 sc->sc_m_ubrlcr = m_ubrlcr; 517 sc->sc_h_ubrlcr = h_ubrlcr; 518 519 /* 520 * For the console, always force CLOCAL and !HUPCL, so that the port 521 * is always active. 522 */ 523 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || 524 ISSET(sc->sc_hwflags, HW_FLAG_CONSOLE)) { 525 SET(t->c_cflag, CLOCAL); 526 CLR(t->c_cflag, HUPCL); 527 } 528 529 /* and copy to tty */ 530 tp->t_ispeed = 0; 531 tp->t_ospeed = t->c_ospeed; 532 tp->t_cflag = t->c_cflag; 533 534 bus_space_write_4(iot, ioh, UART_L_UBRLCR, l_ubrlcr); 535 bus_space_write_4(iot, ioh, UART_M_UBRLCR, m_ubrlcr); 536 bus_space_write_4(iot, ioh, UART_H_UBRLCR, h_ubrlcr); 537 538 (void)splx(s); 539 540 return (0); 541 } 542 543 static int softint_scheduled = 0; 544 545 static void 546 fcom_softintr(sc) 547 struct fcom_softc *sc; 548 { 549 struct tty *tp = sc->sc_tty; 550 int s; 551 int loop; 552 int len; 553 char *ptr; 554 555 s = spltty(); 556 ptr = sc->sc_rxbuf; 557 len = sc->sc_rxpos; 558 sc->sc_rxcur ^= 1; 559 sc->sc_rxbuf = sc->sc_rxbuffer[sc->sc_rxcur]; 560 sc->sc_rxpos = 0; 561 (void)splx(s); 562 563 for (loop = 0; loop < len; ++loop) 564 (*tp->t_linesw->l_rint)(ptr[loop], tp); 565 softint_scheduled = 0; 566 } 567 568 #if 0 569 static int 570 fcom_txintr(arg) 571 void *arg; 572 { 573 /* struct fcom_softc *sc = arg;*/ 574 575 printf("fcom_txintr()\n"); 576 return(0); 577 } 578 #endif 579 580 static int 581 fcom_rxintr(arg) 582 void *arg; 583 { 584 struct fcom_softc *sc = arg; 585 bus_space_tag_t iot = sc->sc_iot; 586 bus_space_handle_t ioh = sc->sc_ioh; 587 struct tty *tp = sc->sc_tty; 588 int status; 589 int byte; 590 591 do { 592 status = bus_space_read_4(iot, ioh, UART_FLAGS); 593 if ((status & UART_RX_FULL)) 594 break; 595 byte = bus_space_read_4(iot, ioh, UART_DATA); 596 status = bus_space_read_4(iot, ioh, UART_RX_STAT); 597 #if DDB_KEYCODE > 0 598 /* 599 * Temporary hack so that I can force the kernel into 600 * the debugger via the serial port 601 */ 602 if (byte == DDB_KEYCODE) Debugger(); 603 #endif 604 if (tp && (tp->t_state & TS_ISOPEN)) 605 if (sc->sc_rxpos < RX_BUFFER_SIZE) { 606 sc->sc_rxbuf[sc->sc_rxpos++] = byte; 607 if (!softint_scheduled) { 608 softint_scheduled = 1; 609 callout_reset(&sc->sc_softintr_ch, 610 1, fcom_softintr, sc); 611 } 612 } 613 } while (1); 614 return(0); 615 } 616 617 #if 0 618 void 619 fcom_iflush(sc) 620 struct fcom_softc *sc; 621 { 622 bus_space_tag_t iot = sc->sc_iot; 623 bus_space_handle_t ioh = sc->sc_ioh; 624 625 /* flush any pending I/O */ 626 while (!ISSET(bus_space_read_4(iot, ioh, UART_FLAGS), UART_RX_FULL)) 627 (void) bus_space_read_4(iot, ioh, UART_DATA); 628 } 629 #endif 630 631 /* 632 * Following are all routines needed for COM to act as console 633 */ 634 635 #if 0 636 void 637 fcomcnprobe(cp) 638 struct consdev *cp; 639 { 640 int major; 641 642 /* Serial console is always present so no probe */ 643 644 /* locate the major number */ 645 for (major = 0; major < nchrdev; major++) 646 if (cdevsw[major].d_open == fcomopen) 647 break; 648 649 /* initialize required fields */ 650 cp->cn_dev = makedev(major, CONUNIT); 651 cp->cn_pri = CN_REMOTE; /* Force a serial port console */ 652 } 653 654 void 655 fcomcninit(cp) 656 struct consdev *cp; 657 { 658 fcomconstag = &fcomcons_bs_tag; 659 660 if (bus_space_map(fcomconstag, DC21285_ARMCSR_BASE, DC21285_ARMCSR_SIZE, 0, &fcomconsioh)) 661 panic("fcomcninit: mapping failed"); 662 663 fcominitcons(fcomconstag, fcomconsioh); 664 } 665 #endif 666 667 int 668 fcomcnattach(iobase, rate, cflag) 669 u_int iobase; 670 int rate; 671 tcflag_t cflag; 672 { 673 static struct consdev fcomcons = { 674 NULL, NULL, fcomcngetc, fcomcnputc, fcomcnpollc, NULL, 675 NODEV, CN_NORMAL 676 }; 677 678 fcomconstag = &fcomcons_bs_tag; 679 680 if (bus_space_map(fcomconstag, iobase, DC21285_ARMCSR_SIZE, 681 0, &fcomconsioh)) 682 panic("fcomcninit: mapping failed"); 683 684 fcominit(fcomconstag, fcomconsioh, rate, cflag); 685 686 cn_tab = &fcomcons; 687 688 /* comcnspeed = rate; 689 comcnmode = cflag;*/ 690 return (0); 691 } 692 693 int 694 fcomcndetach(void) 695 { 696 bus_space_unmap(fcomconstag, fcomconsioh, DC21285_ARMCSR_SIZE); 697 698 cn_tab = NULL; 699 return (0); 700 } 701 702 /* 703 * Initialize UART to known state. 704 */ 705 void 706 fcominit(iot, ioh, rate, mode) 707 bus_space_tag_t iot; 708 bus_space_handle_t ioh; 709 int rate; 710 int mode; 711 { 712 int baudrate; 713 int h_ubrlcr; 714 int m_ubrlcr; 715 int l_ubrlcr; 716 717 switch (rate) { 718 case B1200: 719 case B2400: 720 case B4800: 721 case B9600: 722 case B19200: 723 case B38400: 724 baudrate = UART_BRD(dc21285_fclk, rate); 725 break; 726 default: 727 baudrate = UART_BRD(dc21285_fclk, 9600); 728 break; 729 } 730 731 h_ubrlcr = 0; 732 switch (mode & CSIZE) { 733 case CS5: 734 h_ubrlcr |= UART_DATA_BITS_5; 735 break; 736 case CS6: 737 h_ubrlcr |= UART_DATA_BITS_6; 738 break; 739 case CS7: 740 h_ubrlcr |= UART_DATA_BITS_7; 741 break; 742 case CS8: 743 h_ubrlcr |= UART_DATA_BITS_8; 744 break; 745 } 746 747 if (mode & PARENB) 748 h_ubrlcr |= UART_PARITY_ENABLE; 749 if (mode & PARODD) 750 h_ubrlcr |= UART_ODD_PARITY; 751 else 752 h_ubrlcr |= UART_EVEN_PARITY; 753 754 if (mode & CSTOPB) 755 h_ubrlcr |= UART_STOP_BITS_2; 756 757 m_ubrlcr = (baudrate >> 8) & 0xf; 758 l_ubrlcr = baudrate & 0xff; 759 760 bus_space_write_4(iot, ioh, UART_L_UBRLCR, l_ubrlcr); 761 bus_space_write_4(iot, ioh, UART_M_UBRLCR, m_ubrlcr); 762 bus_space_write_4(iot, ioh, UART_H_UBRLCR, h_ubrlcr); 763 } 764 #if 0 765 /* 766 * Set UART for console use. Do normal init, then enable interrupts. 767 */ 768 void 769 fcominitcons(iot, ioh) 770 bus_space_tag_t iot; 771 bus_space_handle_t ioh; 772 { 773 int s = splserial(); 774 775 fcominit(iot, ioh, comcnspeed, comcnmode); 776 777 delay(10000); 778 779 (void)splx(s); 780 } 781 #endif 782 783 int 784 fcomcngetc(dev) 785 dev_t dev; 786 { 787 int s = splserial(); 788 bus_space_tag_t iot = fcomconstag; 789 bus_space_handle_t ioh = fcomconsioh; 790 u_char stat, c; 791 792 while ((bus_space_read_4(iot, ioh, UART_FLAGS) & UART_RX_FULL) != 0) 793 ; 794 c = bus_space_read_4(iot, ioh, UART_DATA); 795 stat = bus_space_read_4(iot, ioh, UART_RX_STAT); 796 (void)splx(s); 797 #if DDB_KEYCODE > 0 798 /* 799 * Temporary hack so that I can force the kernel into 800 * the debugger via the serial port 801 */ 802 if (c == DDB_KEYCODE) Debugger(); 803 #endif 804 805 return (c); 806 } 807 808 /* 809 * Console kernel output character routine. 810 */ 811 void 812 fcomcnputc(dev, c) 813 dev_t dev; 814 int c; 815 { 816 int s = splserial(); 817 bus_space_tag_t iot = fcomconstag; 818 bus_space_handle_t ioh = fcomconsioh; 819 int timo; 820 821 /* wait for any pending transmission to finish */ 822 timo = 50000; 823 while ((bus_space_read_4(iot, ioh, UART_FLAGS) & UART_TX_BUSY) && --timo) 824 ; 825 bus_space_write_4(iot, ioh, UART_DATA, c); 826 827 /* wait for this transmission to complete */ 828 timo = 1500000; 829 while ((bus_space_read_4(iot, ioh, UART_FLAGS) & UART_TX_BUSY) && --timo) 830 ; 831 /* Clear interrupt status here */ 832 (void)splx(s); 833 } 834 835 void 836 fcomcnpollc(dev, on) 837 dev_t dev; 838 int on; 839 { 840 } 841