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