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