1 /* $NetBSD: psc.c,v 1.1 2026/06/27 13:28:35 rkujawa Exp $ */ 2 3 /*- 4 * Copyright (c) 2008, 2026 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Radoslaw Kujawa and Robert Swindells. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Driver for the MPC5200B Programmable Serial Controller (PSC) in UART mode. 34 * 35 * The interrupt-driven ttyback end is adapted from the MPC5200B PSC 36 * driver by Robert Swindells, simplified onto the mpcobio attachment and 37 * reduced to the subset the console needs. 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: psc.c,v 1.1 2026/06/27 13:28:35 rkujawa Exp $"); 42 43 #include <sys/param.h> 44 #include <sys/device.h> 45 #include <sys/systm.h> 46 #include <sys/proc.h> 47 #include <sys/conf.h> 48 #include <sys/tty.h> 49 #include <sys/file.h> 50 #include <sys/kauth.h> 51 #include <sys/intr.h> 52 #include <sys/kmem.h> 53 #include <sys/bus.h> 54 55 #include <dev/cons.h> 56 #include <dev/ofw/openfirm.h> 57 58 #include <machine/autoconf.h> 59 60 #include <powerpc/mpc5200/obiovar.h> 61 #include <powerpc/mpc5200/mpc5200reg.h> 62 #include <powerpc/mpc5200/pscreg.h> 63 #include <powerpc/mpc5200/pscvar.h> 64 #include <powerpc/mpc5200/cdmvar.h> 65 66 #ifndef PSC_CONSOLE_SPEED 67 #define PSC_CONSOLE_SPEED 115200 /* console baud, programmed from IPB */ 68 #endif 69 70 #define PSCUNIT(x) minor(x) 71 72 #define PSC_READ_1(sc, r) bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (r)) 73 #define PSC_READ_2(sc, r) bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, (r)) 74 #define PSC_WRITE_1(sc, r, v) bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (r), (v)) 75 #define PSC_WRITE_2(sc, r, v) bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, (r), (v)) 76 77 static int psc_match(device_t, cfdata_t, void *); 78 static void psc_attach(device_t, device_t, void *); 79 static u_int psc_baud_divisor(uint32_t, int); 80 static void psc_set_baud(bus_space_tag_t, bus_space_handle_t, int); 81 82 static int pscintr(void *); 83 static void pscsoft(void *); 84 static void psc_rxsoft(struct psc_softc *, struct tty *); 85 86 CFATTACH_DECL_NEW(psc, sizeof(struct psc_softc), 87 psc_match, psc_attach, NULL, NULL); 88 89 extern struct cfdriver psc_cd; 90 91 dev_type_open(pscopen); 92 dev_type_close(pscclose); 93 dev_type_read(pscread); 94 dev_type_write(pscwrite); 95 dev_type_ioctl(pscioctl); 96 dev_type_stop(pscstop); 97 dev_type_tty(psctty); 98 dev_type_poll(pscpoll); 99 100 const struct cdevsw psc_cdevsw = { 101 .d_open = pscopen, 102 .d_close = pscclose, 103 .d_read = pscread, 104 .d_write = pscwrite, 105 .d_ioctl = pscioctl, 106 .d_stop = pscstop, 107 .d_tty = psctty, 108 .d_poll = pscpoll, 109 .d_mmap = nommap, 110 .d_kqfilter = ttykqfilter, 111 .d_discard = nodiscard, 112 .d_flag = D_TTY, 113 }; 114 115 static int pscparam(struct tty *, struct termios *); 116 static void pscstart(struct tty *); 117 118 /* 119 * Console state. 120 */ 121 static struct { 122 bool cs_mapped; 123 volatile uint8_t *cs_base; 124 } psc_console; 125 126 #define PSC_CN_SR(cs) (*(volatile uint16_t *)((cs)->cs_base + PSC_SR)) 127 #define PSC_CN_TB(cs) (*((cs)->cs_base + PSC_TB)) 128 #define PSC_CN_RB(cs) (*((cs)->cs_base + PSC_RB)) 129 130 static void psccnprobe(struct consdev *); 131 static void psccninit(struct consdev *); 132 static int psccngetc(dev_t); 133 static void psccnputc(dev_t, int); 134 static void psccnpollc(dev_t, int); 135 136 struct consdev psccons = { 137 .cn_probe = psccnprobe, 138 .cn_init = psccninit, 139 .cn_getc = psccngetc, 140 .cn_putc = psccnputc, 141 .cn_pollc = psccnpollc, 142 .cn_dev = NODEV, 143 .cn_pri = CN_REMOTE, 144 }; 145 146 static bool 147 psc_is_uart(int node) 148 { 149 char compat[64]; 150 int len; 151 152 len = OF_getprop(node, "compatible", compat, sizeof(compat)); 153 if (len > 0 && 154 (strcmp(compat, "mpc5200-psc-uart") == 0 || 155 strcmp(compat, "mpc5200b-psc-uart") == 0)) 156 return true; 157 return false; 158 } 159 160 static int 161 psc_match(device_t parent, cfdata_t cf, void *aux) 162 { 163 struct obio_attach_args *oba = aux; 164 165 if (strcmp(oba->obio_name, "serial") == 0) 166 return 1; 167 if (psc_is_uart(oba->obio_node)) 168 return 1; 169 return 0; 170 } 171 172 static void 173 psc_attach(device_t parent, device_t self, void *aux) 174 { 175 struct psc_softc *sc = device_private(self); 176 struct obio_attach_args *oba = aux; 177 struct tty *tp; 178 bus_size_t size; 179 int ist; 180 181 sc->sc_dev = self; 182 sc->sc_iot = oba->obio_bst; 183 sc->sc_node = oba->obio_node; 184 185 size = oba->obio_size != 0 ? oba->obio_size : MPC5200_PSC_SIZE; 186 if (bus_space_map(sc->sc_iot, oba->obio_addr, size, 0, 187 &sc->sc_ioh) != 0) { 188 aprint_error(": can't map registers\n"); 189 return; 190 } 191 192 sc->sc_console = (sc->sc_node == console_node); 193 194 if (sc->sc_console) { 195 uint32_t ipb = mpc5200_cdm_get_ipb_freq(); 196 u_int div = psc_baud_divisor(ipb, PSC_CONSOLE_SPEED); 197 198 /* 199 * Announce the computed divisor through the firmware-inherited 200 * console *before* reprogramming 201 */ 202 aprint_normal(": console, IPB %u.%u MHz, %d baud (divisor %u)", 203 ipb / 1000000, (ipb / 100000) % 10, PSC_CONSOLE_SPEED, div); 204 psc_set_baud(sc->sc_iot, sc->sc_ioh, PSC_CONSOLE_SPEED); 205 } 206 aprint_normal("\n"); 207 208 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH); 209 210 /* Mask all PSC events and stop the line while reprogramming. */ 211 sc->sc_imr = 0; 212 PSC_WRITE_2(sc, PSC_IMR, sc->sc_imr); 213 PSC_WRITE_1(sc, PSC_CR, CMD_TX_DISABLE | CMD_RX_DISABLE); 214 215 /* 216 * Clear MR1[FFULL] so the RxRDY status 217 */ 218 { 219 uint8_t mr1, mr2; 220 221 PSC_WRITE_1(sc, PSC_CR, CMD_RESET_MR); 222 mr1 = PSC_READ_1(sc, PSC_MR1); 223 mr2 = PSC_READ_1(sc, PSC_MR2); 224 mr1 &= ~MR1_FFULL; 225 PSC_WRITE_1(sc, PSC_CR, CMD_RESET_MR); 226 PSC_WRITE_1(sc, PSC_MR1, mr1); 227 PSC_WRITE_1(sc, PSC_MR2, mr2); 228 } 229 230 /* Clear errors and bring the receiver and transmitter up. */ 231 PSC_WRITE_1(sc, PSC_CR, CMD_RESET_ERR); 232 PSC_WRITE_1(sc, PSC_CR, CMD_TX_ENABLE | CMD_RX_ENABLE); 233 234 sc->sc_si = softint_establish(SOFTINT_SERIAL, pscsoft, sc); 235 if (sc->sc_si == NULL) { 236 aprint_error_dev(self, "can't establish soft interrupt\n"); 237 return; 238 } 239 240 if (obio_decode_interrupt(oba->obio_node, 0, &sc->sc_irq, &ist)) { 241 sc->sc_ih = intr_establish(sc->sc_irq, ist, IPL_HIGH, 242 pscintr, sc); 243 if (sc->sc_ih == NULL) 244 aprint_error_dev(self, "can't establish interrupt\n"); 245 } 246 247 tp = tty_alloc(); 248 tp->t_oproc = pscstart; 249 tp->t_param = pscparam; 250 sc->sc_tty = tp; 251 sc->sc_rbput = sc->sc_rbget = 0; 252 tty_attach(tp); 253 254 /* 255 * Redirect /dev/console opens to this tty: cnopen() follows 256 * cn_tab->cn_dev, which the polled console left as NODEV. 257 */ 258 if (sc->sc_console && cn_tab == &psccons) { 259 int maj = cdevsw_lookup_major(&psc_cdevsw); 260 261 tp->t_dev = cn_tab->cn_dev = 262 makedev(maj, device_unit(self)); 263 } 264 } 265 266 /* 267 * Compute the 16-bit UART baud-rate divisor for a target rate from the IPB 268 * clock. 269 */ 270 static u_int 271 psc_baud_divisor(uint32_t ipb, int baud) 272 { 273 u_int div; 274 275 if (baud <= 0) 276 return 1; 277 278 div = (ipb + (PSC_BAUD_PRESCALE / 2) * baud) / 279 (PSC_BAUD_PRESCALE * baud); 280 if (div < 1) 281 div = 1; 282 if (div > 0xffff) 283 div = 0xffff; 284 return div; 285 } 286 287 /* 288 * Program the UART baud rate 289 */ 290 static void 291 psc_set_baud(bus_space_tag_t iot, bus_space_handle_t ioh, int baud) 292 { 293 u_int div = psc_baud_divisor(mpc5200_cdm_get_ipb_freq(), baud); 294 int timo; 295 296 /* Let any queued console output drain before stopping the line. */ 297 for (timo = 100000; timo > 0; timo--) { 298 if (bus_space_read_2(iot, ioh, PSC_SR) & SR_TXEMP) 299 break; 300 } 301 302 bus_space_write_1(iot, ioh, PSC_CR, CMD_TX_DISABLE | CMD_RX_DISABLE); 303 bus_space_write_2(iot, ioh, PSC_CSR, CSR_UART_CT); 304 bus_space_write_1(iot, ioh, PSC_CTUR, (div >> 8) & 0xff); 305 bus_space_write_1(iot, ioh, PSC_CTLR, div & 0xff); 306 bus_space_write_1(iot, ioh, PSC_CR, CMD_TX_ENABLE | CMD_RX_ENABLE); 307 } 308 309 /* 310 * Hard interrupt 311 */ 312 static int 313 pscintr(void *arg) 314 { 315 struct psc_softc *sc = arg; 316 uint16_t isr, sr; 317 int handled = 0; 318 319 mutex_spin_enter(&sc->sc_lock); 320 isr = PSC_READ_2(sc, PSC_ISR); 321 322 if (isr & (INT_RXRDY | INT_ERROR | INT_ORERR)) { 323 sr = PSC_READ_2(sc, PSC_SR); 324 while (sr & SR_RXRDY) { 325 uint8_t c = PSC_READ_1(sc, PSC_RB); 326 u_int next = (sc->sc_rbput + 1) & PSC_RING_MASK; 327 328 if (next != sc->sc_rbget) { 329 sc->sc_rbuf[sc->sc_rbput] = c; 330 sc->sc_rbput = next; 331 } 332 /* else ring full: drop, mirroring a silo overflow */ 333 sr = PSC_READ_2(sc, PSC_SR); 334 } 335 if (sr & SR_ORERR) 336 PSC_WRITE_1(sc, PSC_CR, CMD_RESET_ERR); 337 sc->sc_rx_ready = true; 338 handled = 1; 339 } 340 341 sr = PSC_READ_2(sc, PSC_SR); 342 if (sr & SR_TXRDY) { 343 while (sc->sc_tbc > 0 && (PSC_READ_2(sc, PSC_SR) & SR_TXRDY)) { 344 PSC_WRITE_1(sc, PSC_TB, *sc->sc_tba); 345 sc->sc_tba++; 346 sc->sc_tbc--; 347 } 348 if (sc->sc_tbc == 0) { 349 if (sc->sc_imr & INT_TXRDY) { 350 sc->sc_imr &= ~INT_TXRDY; 351 PSC_WRITE_2(sc, PSC_IMR, sc->sc_imr); 352 } 353 if (sc->sc_tx_busy) { 354 sc->sc_tx_busy = false; 355 sc->sc_tx_done = true; 356 handled = 1; 357 } 358 } 359 } 360 361 mutex_spin_exit(&sc->sc_lock); 362 363 if (sc->sc_rx_ready || sc->sc_tx_done) 364 softint_schedule(sc->sc_si); 365 366 return handled; 367 } 368 369 /* 370 * Soft interrupt (IPL_SOFTSERIAL / spltty) 371 */ 372 static void 373 psc_rxsoft(struct psc_softc *sc, struct tty *tp) 374 { 375 int (*rint)(int, struct tty *) = tp->t_linesw->l_rint; 376 377 /* 378 * Single-producer (pscintr at IPL_HIGH) / single-consumer ring, so 379 * sc_rbput can be read without the lock; we only advance sc_rbget. 380 */ 381 while (sc->sc_rbget != sc->sc_rbput) { 382 uint8_t c = sc->sc_rbuf[sc->sc_rbget]; 383 384 if ((*rint)(c, tp) == -1) 385 break; /* tty buffer full; retry later */ 386 sc->sc_rbget = (sc->sc_rbget + 1) & PSC_RING_MASK; 387 } 388 } 389 390 static void 391 pscsoft(void *arg) 392 { 393 struct psc_softc *sc = arg; 394 struct tty *tp = sc->sc_tty; 395 396 if (tp == NULL) 397 return; 398 399 if (sc->sc_rx_ready) { 400 sc->sc_rx_ready = false; 401 psc_rxsoft(sc, tp); 402 } 403 404 if (sc->sc_tx_done) { 405 sc->sc_tx_done = false; 406 CLR(tp->t_state, TS_BUSY); 407 if (ISSET(tp->t_state, TS_FLUSH)) 408 CLR(tp->t_state, TS_FLUSH); 409 else 410 ndflush(&tp->t_outq, 411 (int)(sc->sc_tba - tp->t_outq.c_cf)); 412 (*tp->t_linesw->l_start)(tp); 413 } 414 } 415 416 /* tty oproc: queue the next contiguous output chunk and arm tx interrupts. */ 417 static void 418 pscstart(struct tty *tp) 419 { 420 struct psc_softc *sc = device_lookup_private(&psc_cd, PSCUNIT(tp->t_dev)); 421 int s; 422 423 if (sc == NULL) 424 return; 425 426 s = spltty(); 427 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 428 goto out; 429 if (!ttypull(tp)) 430 goto out; 431 432 SET(tp->t_state, TS_BUSY); 433 434 mutex_spin_enter(&sc->sc_lock); 435 sc->sc_tba = tp->t_outq.c_cf; 436 sc->sc_tbc = ndqb(&tp->t_outq, 0); 437 sc->sc_tx_busy = true; 438 if (!(sc->sc_imr & INT_TXRDY)) { 439 sc->sc_imr |= INT_TXRDY; 440 PSC_WRITE_2(sc, PSC_IMR, sc->sc_imr); 441 } 442 mutex_spin_exit(&sc->sc_lock); 443 out: 444 splx(s); 445 } 446 447 static int 448 pscparam(struct tty *tp, struct termios *t) 449 { 450 struct psc_softc *sc = device_lookup_private(&psc_cd, PSCUNIT(tp->t_dev)); 451 452 if (sc == NULL) 453 return ENXIO; 454 455 /* 456 * XXX: accept the requested termios but do not reprogram the 457 * bit clock here, so a stray speed change cannot make the console 458 * unreadable. 459 */ 460 tp->t_ispeed = t->c_ispeed; 461 tp->t_ospeed = t->c_ospeed; 462 tp->t_cflag = t->c_cflag; 463 464 return 0; 465 } 466 467 int 468 pscopen(dev_t dev, int flag, int mode, struct lwp *l) 469 { 470 struct psc_softc *sc = device_lookup_private(&psc_cd, PSCUNIT(dev)); 471 struct tty *tp; 472 int error, s; 473 474 if (sc == NULL) 475 return ENXIO; 476 tp = sc->sc_tty; 477 478 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 479 return EBUSY; 480 481 s = spltty(); 482 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 483 struct termios t; 484 485 tp->t_dev = dev; 486 487 /* Enable receive (and break) interrupts. */ 488 mutex_spin_enter(&sc->sc_lock); 489 sc->sc_imr |= INT_RXRDY; 490 PSC_WRITE_2(sc, PSC_IMR, sc->sc_imr); 491 mutex_spin_exit(&sc->sc_lock); 492 493 t.c_ospeed = t.c_ispeed = PSC_CONSOLE_SPEED; 494 t.c_cflag = (CREAD | CS8 | HUPCL | CLOCAL); 495 tp->t_ospeed = 0; 496 (void)pscparam(tp, &t); 497 tp->t_iflag = TTYDEF_IFLAG; 498 tp->t_oflag = TTYDEF_OFLAG; 499 tp->t_lflag = TTYDEF_LFLAG; 500 ttychars(tp); 501 ttsetwater(tp); 502 } 503 splx(s); 504 505 error = ttyopen(tp, 0, ISSET(flag, O_NONBLOCK)); 506 if (error) 507 return error; 508 509 return (*tp->t_linesw->l_open)(dev, tp); 510 } 511 512 int 513 pscclose(dev_t dev, int flag, int mode, struct lwp *l) 514 { 515 struct psc_softc *sc = device_lookup_private(&psc_cd, PSCUNIT(dev)); 516 struct tty *tp = sc->sc_tty; 517 518 if (!ISSET(tp->t_state, TS_ISOPEN)) 519 return 0; 520 521 (*tp->t_linesw->l_close)(tp, flag); 522 ttyclose(tp); 523 524 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 525 /* Last close: leave RX interrupts on for the console. */ 526 if (!sc->sc_console) { 527 mutex_spin_enter(&sc->sc_lock); 528 sc->sc_imr &= ~INT_RXRDY; 529 PSC_WRITE_2(sc, PSC_IMR, sc->sc_imr); 530 mutex_spin_exit(&sc->sc_lock); 531 } 532 } 533 return 0; 534 } 535 536 int 537 pscread(dev_t dev, struct uio *uio, int flag) 538 { 539 struct psc_softc *sc = device_lookup_private(&psc_cd, PSCUNIT(dev)); 540 struct tty *tp = sc->sc_tty; 541 542 return (*tp->t_linesw->l_read)(tp, uio, flag); 543 } 544 545 int 546 pscwrite(dev_t dev, struct uio *uio, int flag) 547 { 548 struct psc_softc *sc = device_lookup_private(&psc_cd, PSCUNIT(dev)); 549 struct tty *tp = sc->sc_tty; 550 551 return (*tp->t_linesw->l_write)(tp, uio, flag); 552 } 553 554 int 555 pscpoll(dev_t dev, int events, struct lwp *l) 556 { 557 struct psc_softc *sc = device_lookup_private(&psc_cd, PSCUNIT(dev)); 558 struct tty *tp = sc->sc_tty; 559 560 return (*tp->t_linesw->l_poll)(tp, events, l); 561 } 562 563 struct tty * 564 psctty(dev_t dev) 565 { 566 struct psc_softc *sc = device_lookup_private(&psc_cd, PSCUNIT(dev)); 567 568 return sc->sc_tty; 569 } 570 571 int 572 pscioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 573 { 574 struct psc_softc *sc = device_lookup_private(&psc_cd, PSCUNIT(dev)); 575 struct tty *tp = sc->sc_tty; 576 int error; 577 578 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 579 if (error != EPASSTHROUGH) 580 return error; 581 582 return ttioctl(tp, cmd, data, flag, l); 583 } 584 585 void 586 pscstop(struct tty *tp, int flag) 587 { 588 struct psc_softc *sc = device_lookup_private(&psc_cd, PSCUNIT(tp->t_dev)); 589 590 if (sc == NULL) 591 return; 592 593 mutex_spin_enter(&sc->sc_lock); 594 if (ISSET(tp->t_state, TS_BUSY)) { 595 sc->sc_tbc = 0; 596 if (!ISSET(tp->t_state, TS_TTSTOP)) 597 SET(tp->t_state, TS_FLUSH); 598 } 599 mutex_spin_exit(&sc->sc_lock); 600 } 601 602 /* 603 * Console interface. 604 */ 605 606 static void 607 psccnprobe(struct consdev *cp) 608 { 609 /* Selection is performed by ofwoea_cnprobe(); nothing to do. */ 610 } 611 612 static void 613 psccninit(struct consdev *cp) 614 { 615 /* 616 * The board's console is PSC1, at a fixed MBAR offset. 617 * XXX: This should be configurable. 618 */ 619 psc_console.cs_base = 620 (volatile uint8_t *)(MPC5200_MBAR_DEFAULT + MPC5200_REG_PSC1); 621 psc_console.cs_mapped = true; 622 } 623 624 static int 625 psccngetc(dev_t dev) 626 { 627 628 if (!psc_console.cs_mapped) 629 return -1; 630 if ((PSC_CN_SR(&psc_console) & SR_RXRDY) == 0) 631 return -1; 632 return PSC_CN_RB(&psc_console); 633 } 634 635 static void 636 psccnputc(dev_t dev, int c) 637 { 638 639 if (!psc_console.cs_mapped) 640 return; 641 if (c == '\n') 642 psccnputc(dev, '\r'); 643 while ((PSC_CN_SR(&psc_console) & SR_TXRDY) == 0) 644 continue; 645 PSC_CN_TB(&psc_console) = c; 646 } 647 648 static void 649 psccnpollc(dev_t dev, int on) 650 { 651 /* The low-level console path is always polled. */ 652 } 653