1 /* $OpenBSD: mvuart.c,v 1.4 2021/10/24 17:52:26 mpi Exp $ */
2 /*
3 * Copyright (c) 2005 Dale Rahn <drahn@motorola.com>
4 * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/param.h>
20 #include <sys/ioctl.h>
21 #include <sys/proc.h>
22 #include <sys/tty.h>
23 #include <sys/systm.h>
24 #include <sys/device.h>
25 #include <sys/conf.h>
26 #include <sys/fcntl.h>
27
28 #include <machine/bus.h>
29 #include <machine/fdt.h>
30
31 #include <dev/cons.h>
32
33 #include <dev/ofw/openfirm.h>
34 #include <dev/ofw/ofw_clock.h>
35 #include <dev/ofw/ofw_pinctrl.h>
36 #include <dev/ofw/fdt.h>
37
38 #define MVUART_RBR 0x00
39 #define MVUART_TSH 0x04
40 #define MVUART_CTRL 0x08
41 #define MVUART_CTRL_RX_RDY_INT (1 << 4)
42 #define MVUART_CTRL_TX_RDY_INT (1 << 5)
43 #define MVUART_STAT 0x0c
44 #define MVUART_STAT_STD_OVR_ERR (1 << 0)
45 #define MVUART_STAT_STD_PAR_ERR (1 << 1)
46 #define MVUART_STAT_STD_FRM_ERR (1 << 2)
47 #define MVUART_STAT_STD_BRK_DET (1 << 3)
48 #define MVUART_STAT_STD_ERROR_MASK (0xf << 0)
49 #define MVUART_STAT_STD_RX_RDY (1 << 4)
50 #define MVUART_STAT_STD_TX_RDY (1 << 5)
51 #define MVUART_STAT_STD_TX_EMPTY (1 << 6)
52 #define MVUART_STAT_STD_TX_FIFO_FULL (1 << 11)
53 #define MVUART_STAT_STD_TX_FIFO_EMPTY (1 << 13)
54 #define MVUART_BAUD_RATE_DIV 0x10
55 #define MVUART_BAUD_RATE_DIV_MASK 0x3ff
56
57 #define DEVUNIT(x) (minor(x) & 0x7f)
58 #define DEVCUA(x) (minor(x) & 0x80)
59
60 #define HREAD4(sc, reg) \
61 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
62 #define HWRITE4(sc, reg, val) \
63 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
64 #define HSET4(sc, reg, bits) \
65 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
66 #define HCLR4(sc, reg, bits) \
67 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
68
69 struct mvuart_softc {
70 struct device sc_dev;
71 bus_space_tag_t sc_iot;
72 bus_space_handle_t sc_ioh;
73 int sc_node;
74 struct soft_intrhand *sc_si;
75 void *sc_ih;
76 struct tty *sc_tty;
77 int sc_floods;
78 int sc_errors;
79 int sc_halt;
80 uint8_t sc_hwflags;
81 #define COM_HW_NOIEN 0x01
82 #define COM_HW_FIFO 0x02
83 #define COM_HW_SIR 0x20
84 #define COM_HW_CONSOLE 0x40
85 uint8_t sc_cua;
86 uint16_t *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend;
87 #define MVUART_IBUFSIZE 128
88 #define MVUART_IHIGHWATER 100
89 uint16_t sc_ibufs[2][MVUART_IBUFSIZE];
90 };
91
92 int mvuart_match(struct device *, void *, void *);
93 void mvuart_attach(struct device *, struct device *, void *);
94
95 void mvuartcnprobe(struct consdev *cp);
96 void mvuartcninit(struct consdev *cp);
97 int mvuartcnattach(bus_space_tag_t, bus_addr_t, int, tcflag_t);
98 int mvuartcngetc(dev_t dev);
99 void mvuartcnputc(dev_t dev, int c);
100 void mvuartcnpollc(dev_t dev, int on);
101 int mvuart_param(struct tty *, struct termios *);
102 void mvuart_start(struct tty *);
103 void mvuart_softint(void *arg);
104
105 struct mvuart_softc *mvuart_sc(dev_t dev);
106
107 int mvuart_intr(void *);
108 int mvuart_intr_rx(struct mvuart_softc *);
109 int mvuart_intr_tx(struct mvuart_softc *);
110
111 /* XXX - we imitate 'com' serial ports and take over their entry points */
112 /* XXX: These belong elsewhere */
113 cdev_decl(com);
114 cdev_decl(mvuart);
115
116 struct cfdriver mvuart_cd = {
117 NULL, "mvuart", DV_TTY
118 };
119
120 const struct cfattach mvuart_ca = {
121 sizeof(struct mvuart_softc), mvuart_match, mvuart_attach
122 };
123
124 bus_space_tag_t mvuartconsiot;
125 bus_space_handle_t mvuartconsioh;
126 bus_addr_t mvuartconsaddr;
127
128 struct cdevsw mvuartdev =
129 cdev_tty_init(3/*XXX NMVUART */, mvuart); /* 12: serial port */
130
131 void
mvuart_init_cons(void)132 mvuart_init_cons(void)
133 {
134 struct fdt_reg reg;
135 void *node;
136
137 if ((node = fdt_find_cons("marvell,armada-3700-uart")) == NULL)
138 return;
139
140 if (fdt_get_reg(node, 0, ®))
141 return;
142
143 mvuartcnattach(fdt_cons_bs_tag, reg.addr, B115200, TTYDEF_CFLAG);
144 }
145
146 int
mvuart_match(struct device * parent,void * match,void * aux)147 mvuart_match(struct device *parent, void *match, void *aux)
148 {
149 struct fdt_attach_args *faa = aux;
150
151 return OF_is_compatible(faa->fa_node, "marvell,armada-3700-uart");
152 }
153
154 void
mvuart_attach(struct device * parent,struct device * self,void * aux)155 mvuart_attach(struct device *parent, struct device *self, void *aux)
156 {
157 struct mvuart_softc *sc = (struct mvuart_softc *)self;
158 struct fdt_attach_args *faa = aux;
159 int maj;
160
161 if (faa->fa_nreg < 1)
162 return;
163
164 pinctrl_byname(faa->fa_node, "default");
165
166 sc->sc_node = faa->fa_node;
167 sc->sc_iot = faa->fa_iot;
168 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
169 faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
170 panic("%s: bus_space_map failed", sc->sc_dev.dv_xname);
171 return;
172 }
173
174 if (faa->fa_reg[0].addr == mvuartconsaddr) {
175 /* Locate the major number. */
176 for (maj = 0; maj < nchrdev; maj++)
177 if (cdevsw[maj].d_open == mvuartopen)
178 break;
179 cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
180
181 printf(": console");
182 }
183
184 printf("\n");
185
186 sc->sc_ih = fdt_intr_establish_idx(faa->fa_node, 0, IPL_TTY,
187 mvuart_intr, sc, sc->sc_dev.dv_xname);
188 if (sc->sc_ih == NULL)
189 panic("%s: can't establish hard interrupt",
190 sc->sc_dev.dv_xname);
191
192 sc->sc_si = softintr_establish(IPL_TTY, mvuart_softint, sc);
193 if (sc->sc_si == NULL)
194 panic("%s: can't establish soft interrupt",
195 sc->sc_dev.dv_xname);
196 }
197
198 int
mvuart_intr(void * arg)199 mvuart_intr(void *arg)
200 {
201 struct mvuart_softc *sc = arg;
202 uint32_t stat;
203 int ret = 0;
204
205 if (sc->sc_tty == NULL)
206 return 0;
207
208 stat = HREAD4(sc, MVUART_STAT);
209
210 if ((stat & MVUART_STAT_STD_RX_RDY) != 0)
211 ret |= mvuart_intr_rx(sc);
212
213 if ((stat & MVUART_STAT_STD_TX_RDY) != 0)
214 ret |= mvuart_intr_tx(sc);
215
216 return ret;
217 }
218
219 int
mvuart_intr_rx(struct mvuart_softc * sc)220 mvuart_intr_rx(struct mvuart_softc *sc)
221 {
222 uint32_t stat;
223 uint16_t *p, c;
224
225 p = sc->sc_ibufp;
226
227 stat = HREAD4(sc, MVUART_STAT);
228 while ((stat & MVUART_STAT_STD_RX_RDY) != 0) {
229 c = HREAD4(sc, MVUART_RBR);
230 c |= (stat & MVUART_STAT_STD_ERROR_MASK) << 8;
231 if (p >= sc->sc_ibufend) {
232 sc->sc_floods++;
233 } else {
234 *p++ = c;
235 }
236 stat = HREAD4(sc, MVUART_STAT);
237 }
238 sc->sc_ibufp = p;
239
240 softintr_schedule(sc->sc_si);
241 return 1;
242 }
243
244 int
mvuart_intr_tx(struct mvuart_softc * sc)245 mvuart_intr_tx(struct mvuart_softc *sc)
246 {
247 struct tty *tp = sc->sc_tty;
248
249 HCLR4(sc, MVUART_CTRL, MVUART_CTRL_TX_RDY_INT);
250 if (ISSET(tp->t_state, TS_BUSY)) {
251 CLR(tp->t_state, TS_BUSY | TS_FLUSH);
252 if (sc->sc_halt > 0)
253 wakeup(&tp->t_outq);
254 (*linesw[tp->t_line].l_start)(tp);
255 }
256
257 return 1;
258 }
259
260 int
mvuart_param(struct tty * tp,struct termios * t)261 mvuart_param(struct tty *tp, struct termios *t)
262 {
263 struct mvuart_softc *sc = mvuart_sc(tp->t_dev);
264 int error, ospeed = t->c_ospeed;
265 tcflag_t oldcflag;
266
267 if (t->c_ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
268 return EINVAL;
269
270 switch (ISSET(t->c_cflag, CSIZE)) {
271 case CS5:
272 case CS6:
273 case CS7:
274 return EINVAL;
275 case CS8:
276 break;
277 }
278
279 if (ospeed != 0) {
280 while (ISSET(tp->t_state, TS_BUSY)) {
281 ++sc->sc_halt;
282 error = ttysleep(tp, &tp->t_outq,
283 TTOPRI | PCATCH, "mvuartprm");
284 --sc->sc_halt;
285 if (error) {
286 mvuart_start(tp);
287 return (error);
288 }
289 }
290 }
291
292 /* and copy to tty */
293 tp->t_ispeed = t->c_ispeed;
294 tp->t_ospeed = t->c_ospeed;
295 oldcflag = tp->t_cflag;
296 tp->t_cflag = t->c_cflag;
297
298 mvuart_start(tp);
299 return 0;
300 }
301
302 void
mvuart_start(struct tty * tp)303 mvuart_start(struct tty *tp)
304 {
305 struct mvuart_softc *sc = mvuart_sc(tp->t_dev);
306 uint8_t buf;
307 int i, n, s;
308
309 s = spltty();
310 if (ISSET(tp->t_state, TS_BUSY)) {
311 splx(s);
312 return;
313 }
314 if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP))
315 goto out;
316 if (tp->t_outq.c_cc <= tp->t_lowat) {
317 if (ISSET(tp->t_state, TS_ASLEEP)) {
318 CLR(tp->t_state, TS_ASLEEP);
319 wakeup(&tp->t_outq);
320 }
321 if (tp->t_outq.c_cc == 0)
322 goto out;
323 selwakeup(&tp->t_wsel);
324 }
325 SET(tp->t_state, TS_BUSY);
326
327 for (i = 0; i < 32; i++) {
328 n = q_to_b(&tp->t_outq, &buf, 1);
329 if (n < 1)
330 break;
331 HWRITE4(sc, MVUART_TSH, buf);
332 if (HREAD4(sc, MVUART_STAT) & MVUART_STAT_STD_TX_FIFO_FULL)
333 break;
334 }
335 HSET4(sc, MVUART_CTRL, MVUART_CTRL_TX_RDY_INT);
336
337 out:
338 splx(s);
339 }
340
341 void
mvuart_softint(void * arg)342 mvuart_softint(void *arg)
343 {
344 struct mvuart_softc *sc = arg;
345 struct tty *tp;
346 uint16_t *ibufp;
347 uint16_t *ibufend;
348 int c, err, s;
349
350 if (sc == NULL || sc->sc_ibufp == sc->sc_ibuf)
351 return;
352
353 tp = sc->sc_tty;
354 s = spltty();
355
356 ibufp = sc->sc_ibuf;
357 ibufend = sc->sc_ibufp;
358
359 if (ibufp == ibufend || tp == NULL || !ISSET(tp->t_state, TS_ISOPEN)) {
360 splx(s);
361 return;
362 }
363
364 sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
365 sc->sc_ibufs[1] : sc->sc_ibufs[0];
366 sc->sc_ibufhigh = sc->sc_ibuf + MVUART_IHIGHWATER;
367 sc->sc_ibufend = sc->sc_ibuf + MVUART_IBUFSIZE;
368
369 splx(s);
370
371 while (ibufp < ibufend) {
372 err = 0;
373 c = *ibufp++;
374 if (ISSET(c, (MVUART_STAT_STD_PAR_ERR << 8)))
375 err |= TTY_PE;
376 if (ISSET(c, (MVUART_STAT_STD_FRM_ERR << 8)))
377 err |= TTY_FE;
378 c = (c & 0xff) | err;
379 (*linesw[tp->t_line].l_rint)(c, tp);
380 }
381 }
382
383 int
mvuartopen(dev_t dev,int flag,int mode,struct proc * p)384 mvuartopen(dev_t dev, int flag, int mode, struct proc *p)
385 {
386 struct mvuart_softc *sc;
387 struct tty *tp;
388 int s, error = 0;
389
390 sc = mvuart_sc(dev);
391 if (sc == NULL)
392 return ENXIO;
393
394 s = spltty();
395 if (sc->sc_tty == NULL)
396 tp = sc->sc_tty = ttymalloc(0);
397 else
398 tp = sc->sc_tty;
399
400 splx(s);
401
402 tp->t_oproc = mvuart_start;
403 tp->t_param = mvuart_param;
404 tp->t_dev = dev;
405
406 if (!ISSET(tp->t_state, TS_ISOPEN)) {
407 SET(tp->t_state, TS_WOPEN);
408 ttychars(tp);
409 tp->t_iflag = TTYDEF_IFLAG;
410 tp->t_oflag = TTYDEF_OFLAG;
411
412 tp->t_cflag = TTYDEF_CFLAG;
413 tp->t_lflag = TTYDEF_LFLAG;
414 tp->t_ispeed = tp->t_ospeed = B115200;
415
416 s = spltty();
417
418 mvuart_param(tp, &tp->t_termios);
419 ttsetwater(tp);
420 sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
421 sc->sc_ibufhigh = sc->sc_ibuf + MVUART_IHIGHWATER;
422 sc->sc_ibufend = sc->sc_ibuf + MVUART_IBUFSIZE;
423
424 /* Enable interrupts */
425 HSET4(sc, MVUART_CTRL, MVUART_CTRL_RX_RDY_INT);
426
427 SET(tp->t_state, TS_CARR_ON); /* XXX */
428 } else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p) != 0)
429 return EBUSY;
430 else
431 s = spltty();
432
433 if (DEVCUA(dev)) {
434 if (ISSET(tp->t_state, TS_ISOPEN)) {
435 splx(s);
436 return EBUSY;
437 }
438 sc->sc_cua = 1;
439 } else {
440 /* tty (not cua) device; wait for carrier if necessary */
441 if (ISSET(flag, O_NONBLOCK)) {
442 if (sc->sc_cua) {
443 /* Opening TTY non-blocking... but the CUA is busy */
444 splx(s);
445 return EBUSY;
446 }
447 } else {
448 while (sc->sc_cua ||
449 (!ISSET(tp->t_cflag, CLOCAL) &&
450 !ISSET(tp->t_state, TS_CARR_ON))) {
451 SET(tp->t_state, TS_WOPEN);
452 error = ttysleep(tp, &tp->t_rawq,
453 TTIPRI | PCATCH, ttopen);
454 /*
455 * If TS_WOPEN has been reset, that means the
456 * cua device has been closed. We don't want
457 * to fail in that case,
458 * so just go around again.
459 */
460 if (error && ISSET(tp->t_state, TS_WOPEN)) {
461 CLR(tp->t_state, TS_WOPEN);
462 splx(s);
463 return error;
464 }
465 }
466 }
467 }
468 splx(s);
469 return (*linesw[tp->t_line].l_open)(dev,tp,p);
470 }
471
472 int
mvuartclose(dev_t dev,int flag,int mode,struct proc * p)473 mvuartclose(dev_t dev, int flag, int mode, struct proc *p)
474 {
475 struct mvuart_softc *sc = mvuart_sc(dev);
476 struct tty *tp = sc->sc_tty;
477 int s;
478
479 if (!ISSET(tp->t_state, TS_ISOPEN))
480 return 0;
481
482 (*linesw[tp->t_line].l_close)(tp, flag, p);
483 s = spltty();
484 if (!ISSET(tp->t_state, TS_WOPEN)) {
485 /* Disable interrupts */
486 HCLR4(sc, MVUART_CTRL, MVUART_CTRL_RX_RDY_INT |
487 MVUART_CTRL_TX_RDY_INT);
488 }
489 CLR(tp->t_state, TS_BUSY | TS_FLUSH);
490 sc->sc_cua = 0;
491 splx(s);
492 ttyclose(tp);
493
494 return 0;
495 }
496
497 int
mvuartread(dev_t dev,struct uio * uio,int flag)498 mvuartread(dev_t dev, struct uio *uio, int flag)
499 {
500 struct tty *tty;
501
502 tty = mvuarttty(dev);
503 if (tty == NULL)
504 return ENODEV;
505
506 return((*linesw[tty->t_line].l_read)(tty, uio, flag));
507 }
508
509 int
mvuartwrite(dev_t dev,struct uio * uio,int flag)510 mvuartwrite(dev_t dev, struct uio *uio, int flag)
511 {
512 struct tty *tty;
513
514 tty = mvuarttty(dev);
515 if (tty == NULL)
516 return ENODEV;
517
518 return((*linesw[tty->t_line].l_write)(tty, uio, flag));
519 }
520
521 int
mvuartioctl(dev_t dev,u_long cmd,caddr_t data,int flag,struct proc * p)522 mvuartioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
523 {
524 struct mvuart_softc *sc;
525 struct tty *tp;
526 int error;
527
528 sc = mvuart_sc(dev);
529 if (sc == NULL)
530 return (ENODEV);
531
532 tp = sc->sc_tty;
533 if (tp == NULL)
534 return (ENXIO);
535
536 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
537 if (error >= 0)
538 return (error);
539
540 error = ttioctl(tp, cmd, data, flag, p);
541 if (error >= 0)
542 return (error);
543
544 switch(cmd) {
545 case TIOCSBRK:
546 case TIOCCBRK:
547 case TIOCSDTR:
548 case TIOCCDTR:
549 case TIOCMSET:
550 case TIOCMBIS:
551 case TIOCMBIC:
552 case TIOCMGET:
553 case TIOCGFLAGS:
554 break;
555 case TIOCSFLAGS:
556 error = suser(p);
557 if (error != 0)
558 return(EPERM);
559 break;
560 default:
561 return (ENOTTY);
562 }
563
564 return 0;
565 }
566
567 int
mvuartstop(struct tty * tp,int flag)568 mvuartstop(struct tty *tp, int flag)
569 {
570 return 0;
571 }
572
573 struct tty *
mvuarttty(dev_t dev)574 mvuarttty(dev_t dev)
575 {
576 struct mvuart_softc *sc;
577 sc = mvuart_sc(dev);
578 if (sc == NULL)
579 return NULL;
580 return sc->sc_tty;
581 }
582
583 struct mvuart_softc *
mvuart_sc(dev_t dev)584 mvuart_sc(dev_t dev)
585 {
586 int unit;
587 unit = DEVUNIT(dev);
588 if (unit >= mvuart_cd.cd_ndevs)
589 return NULL;
590 return (struct mvuart_softc *)mvuart_cd.cd_devs[unit];
591 }
592
593 /* serial console */
594 void
mvuartcnprobe(struct consdev * cp)595 mvuartcnprobe(struct consdev *cp)
596 {
597 }
598
599 void
mvuartcninit(struct consdev * cp)600 mvuartcninit(struct consdev *cp)
601 {
602 }
603
604 int
mvuartcnattach(bus_space_tag_t iot,bus_addr_t iobase,int rate,tcflag_t cflag)605 mvuartcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, tcflag_t cflag)
606 {
607 static struct consdev mvuartcons = {
608 NULL, NULL, mvuartcngetc, mvuartcnputc, mvuartcnpollc, NULL,
609 NODEV, CN_MIDPRI
610 };
611 int maj;
612
613 if (bus_space_map(iot, iobase, 0x200, 0, &mvuartconsioh))
614 return ENOMEM;
615
616 /* Look for major of com(4) to replace. */
617 for (maj = 0; maj < nchrdev; maj++)
618 if (cdevsw[maj].d_open == comopen)
619 break;
620 if (maj == nchrdev)
621 return ENXIO;
622
623 cn_tab = &mvuartcons;
624 cn_tab->cn_dev = makedev(maj, 0);
625 cdevsw[maj] = mvuartdev; /* KLUDGE */
626
627 mvuartconsiot = iot;
628 mvuartconsaddr = iobase;
629
630 return 0;
631 }
632
633 int
mvuartcngetc(dev_t dev)634 mvuartcngetc(dev_t dev)
635 {
636 int c;
637 int s;
638 s = splhigh();
639 while ((bus_space_read_4(mvuartconsiot, mvuartconsioh, MVUART_STAT) &
640 MVUART_STAT_STD_RX_RDY) == 0)
641 ;
642 c = bus_space_read_4(mvuartconsiot, mvuartconsioh, MVUART_RBR);
643 splx(s);
644 return c;
645 }
646
647 void
mvuartcnputc(dev_t dev,int c)648 mvuartcnputc(dev_t dev, int c)
649 {
650 int s;
651 s = splhigh();
652 while ((bus_space_read_4(mvuartconsiot, mvuartconsioh, MVUART_STAT) &
653 MVUART_STAT_STD_TX_FIFO_FULL) != 0)
654 ;
655 bus_space_write_4(mvuartconsiot, mvuartconsioh, MVUART_TSH, (uint8_t)c);
656 while ((bus_space_read_4(mvuartconsiot, mvuartconsioh, MVUART_STAT) &
657 MVUART_STAT_STD_TX_FIFO_EMPTY) != 0)
658 ;
659 splx(s);
660 }
661
662 void
mvuartcnpollc(dev_t dev,int on)663 mvuartcnpollc(dev_t dev, int on)
664 {
665 }
666