1 /* $OpenBSD: cduart.c,v 1.1 2021/04/24 07:49:11 visa Exp $ */
2
3 /*
4 * Copyright (c) 2021 Visa Hankala
5 *
6 * Permission to use, copy, modify, and/or 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 /*
20 * Driver for Cadence UART.
21 */
22
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/conf.h>
26 #include <sys/device.h>
27 #include <sys/fcntl.h>
28 #include <sys/tty.h>
29 #include <sys/syslog.h>
30
31 #include <machine/bus.h>
32 #include <machine/fdt.h>
33
34 #include <dev/cons.h>
35
36 #include <dev/ofw/fdt.h>
37 #include <dev/ofw/openfirm.h>
38
39 #define CDUART_CR 0x0000
40 #define CDUART_CR_STOPBRK (1 << 8)
41 #define CDUART_CR_STARTBRK (1 << 7)
42 #define CDUART_CR_TORST (1 << 6)
43 #define CDUART_CR_TXDIS (1 << 5)
44 #define CDUART_CR_TXEN (1 << 4)
45 #define CDUART_CR_RXDIS (1 << 3)
46 #define CDUART_CR_RXEN (1 << 2)
47 #define CDUART_CR_TXRST (1 << 1)
48 #define CDUART_CR_RXRST (1 << 0)
49 #define CDUART_MR 0x0004
50 #define CDUART_MR_CHMODE_MASK (0x3 << 8)
51 #define CDUART_MR_NBSTOP_MASK (0x3 << 6)
52 #define CDUART_MR_PAR_MASK (0x7 << 3)
53 #define CDUART_MR_PAR_NO (0x4 << 3)
54 #define CDUART_MR_PAR_FORCED1 (0x3 << 3)
55 #define CDUART_MR_PAR_FORCED0 (0x2 << 3)
56 #define CDUART_MR_PAR_ODD (0x1 << 3)
57 #define CDUART_MR_PAR_EVEN (0x0 << 3)
58 #define CDUART_MR_CHRL_MASK (0x3 << 1)
59 #define CDUART_MR_CHRL_C6 (0x3 << 1)
60 #define CDUART_MR_CHRL_C7 (0x2 << 1)
61 #define CDUART_MR_CHRL_C8 (0x0 << 1)
62 #define CDUART_MR_CLKSEL (1 << 0)
63 #define CDUART_IER 0x0008
64 #define CDUART_IDR 0x000c
65 #define CDUART_IMR 0x0010
66 #define CDUART_ISR 0x0014
67 #define CDUART_ISR_TXOVR (1 << 12)
68 #define CDUART_ISR_TNFUL (1 << 11)
69 #define CDUART_ISR_TTRIG (1 << 10)
70 #define CDUART_IXR_DMS (1 << 9)
71 #define CDUART_IXR_TOUT (1 << 8)
72 #define CDUART_IXR_PARITY (1 << 7)
73 #define CDUART_IXR_FRAMING (1 << 6)
74 #define CDUART_IXR_RXOVR (1 << 5)
75 #define CDUART_IXR_TXFULL (1 << 4)
76 #define CDUART_IXR_TXEMPTY (1 << 3)
77 #define CDUART_IXR_RXFULL (1 << 2)
78 #define CDUART_IXR_RXEMPTY (1 << 1)
79 #define CDUART_IXR_RTRIG (1 << 0)
80 #define CDUART_RXTOUT 0x001c
81 #define CDUART_RXWM 0x0020
82 #define CDUART_SR 0x002c
83 #define CDUART_SR_TNFUL (1 << 14)
84 #define CDUART_SR_TTRIG (1 << 13)
85 #define CDUART_SR_FLOWDEL (1 << 12)
86 #define CDUART_SR_TACTIVE (1 << 11)
87 #define CDUART_SR_RACTIVE (1 << 10)
88 #define CDUART_SR_TXFULL (1 << 4)
89 #define CDUART_SR_TXEMPTY (1 << 3)
90 #define CDUART_SR_RXFULL (1 << 2)
91 #define CDUART_SR_RXEMPTY (1 << 1)
92 #define CDUART_SR_RXOVR (1 << 0)
93 #define CDUART_FIFO 0x0030
94
95 #define CDUART_SPACE_SIZE 0x0048
96
97 #define CDUART_FIFOSIZE 64
98 #define CDUART_IBUFSIZE 128
99
100 struct cduart_softc {
101 struct device sc_dev;
102 bus_space_tag_t sc_iot;
103 bus_space_handle_t sc_ioh;
104 void *sc_ih;
105 void *sc_si;
106
107 struct tty *sc_tty;
108 uint8_t sc_cua;
109
110 struct timeout sc_diag_tmo;
111 int sc_overflows;
112 int sc_floods;
113 int sc_errors;
114
115 int sc_ibufs[2][CDUART_IBUFSIZE];
116 int *sc_ibuf;
117 int *sc_ibufend;
118 int *sc_ibufp;
119 };
120
121 int cduart_match(struct device *, void *, void *);
122 void cduart_attach(struct device *, struct device *, void *);
123 void cduart_diag(void *);
124 int cduart_intr(void *);
125 void cduart_softintr(void *);
126
127 struct tty *cduarttty(dev_t);
128 struct cduart_softc *cduart_sc(dev_t);
129
130 int cduartparam(struct tty *, struct termios *);
131 void cduartstart(struct tty *);
132
133 int cduartcnattach(bus_space_tag_t, bus_addr_t, int, tcflag_t);
134 void cduartcnprobe(struct consdev *);
135 void cduartcninit(struct consdev *);
136 int cduartcngetc(dev_t);
137 void cduartcnputc(dev_t, int);
138 void cduartcnpollc(dev_t, int);
139
140 cdev_decl(com);
141 cdev_decl(cduart);
142
143 const struct cfattach cduart_ca = {
144 sizeof(struct cduart_softc), cduart_match, cduart_attach
145 };
146
147 struct cfdriver cduart_cd = {
148 NULL, "cduart", DV_DULL
149 };
150
151 bus_space_tag_t cduartconsiot;
152 bus_space_handle_t cduartconsioh;
153 int cduartconsrate;
154 tcflag_t cduartconscflag;
155 struct cdevsw cduartdev = cdev_tty_init(3, cduart);
156
157 #define DEVUNIT(x) (minor(x) & 0x7f)
158 #define DEVCUA(x) (minor(x) & 0x80)
159
160 static inline uint32_t
cduart_read(struct cduart_softc * sc,uint32_t reg)161 cduart_read(struct cduart_softc *sc, uint32_t reg)
162 {
163 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg);
164 }
165
166 static inline void
cduart_write(struct cduart_softc * sc,uint32_t reg,uint32_t val)167 cduart_write(struct cduart_softc *sc, uint32_t reg, uint32_t val)
168 {
169 bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, val);
170 }
171
172 void
cduart_init_cons(void)173 cduart_init_cons(void)
174 {
175 struct fdt_reg reg;
176 void *node;
177
178 if ((node = fdt_find_cons("cdns,uart-r1p8")) == NULL &&
179 (node = fdt_find_cons("cdns,uart-r1p12")) == NULL)
180 return;
181 if (fdt_get_reg(node, 0, ®) != 0)
182 return;
183
184 cduartcnattach(fdt_cons_bs_tag, reg.addr, B115200, TTYDEF_CFLAG);
185 }
186
187 int
cduart_match(struct device * parent,void * match,void * aux)188 cduart_match(struct device *parent, void *match, void *aux)
189 {
190 struct fdt_attach_args *faa = aux;
191
192 return OF_is_compatible(faa->fa_node, "cdns,uart-r1p8") ||
193 OF_is_compatible(faa->fa_node, "cdns,uart-r1p12");
194 }
195
196 void
cduart_attach(struct device * parent,struct device * self,void * aux)197 cduart_attach(struct device *parent, struct device *self, void *aux)
198 {
199 struct fdt_attach_args *faa = aux;
200 struct cduart_softc *sc = (struct cduart_softc *)self;
201 uint32_t cr, isr;
202 int maj;
203
204 if (faa->fa_nreg < 1) {
205 printf(": no registers\n");
206 return;
207 }
208
209 sc->sc_iot = faa->fa_iot;
210 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
211 faa->fa_reg[0].size, 0, &sc->sc_ioh) != 0) {
212 printf(": can't map registers\n");
213 return;
214 }
215
216 /* Disable all interrupts. */
217 cduart_write(sc, CDUART_IDR, ~0U);
218
219 /* Clear any pending interrupts. */
220 isr = cduart_read(sc, CDUART_ISR);
221 cduart_write(sc, CDUART_ISR, isr);
222
223 sc->sc_ih = fdt_intr_establish_idx(faa->fa_node, 0, IPL_TTY,
224 cduart_intr, sc, sc->sc_dev.dv_xname);
225 if (sc->sc_ih == NULL) {
226 printf(": can't establish interrupt\n");
227 goto fail;
228 }
229
230 timeout_set(&sc->sc_diag_tmo, cduart_diag, sc);
231 sc->sc_si = softintr_establish(IPL_TTY, cduart_softintr, sc);
232 if (sc->sc_si == NULL) {
233 printf(": can't establish soft interrupt\n");
234 goto fail;
235 }
236
237 if (faa->fa_node == stdout_node) {
238 /* Locate the major number. */
239 for (maj = 0; maj < nchrdev; maj++) {
240 if (cdevsw[maj].d_open == cduartopen)
241 break;
242 }
243 KASSERT(maj < nchrdev);
244 cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
245 printf(": console");
246 }
247
248 /* Enable transmitter and receiver. */
249 cr = cduart_read(sc, CDUART_CR);
250 cr &= ~(CDUART_CR_TXDIS | CDUART_CR_RXDIS);
251 cr |= CDUART_CR_TXEN | CDUART_CR_RXEN;
252 cduart_write(sc, CDUART_CR, cr);
253
254 printf("\n");
255
256 return;
257
258 fail:
259 if (sc->sc_si != NULL)
260 softintr_disestablish(sc->sc_si);
261 if (sc->sc_ih != NULL)
262 fdt_intr_disestablish(sc->sc_ih);
263 if (sc->sc_ioh != 0)
264 bus_space_unmap(sc->sc_iot, sc->sc_ioh, CDUART_SPACE_SIZE);
265 }
266
267 int
cduart_intr(void * arg)268 cduart_intr(void *arg)
269 {
270 struct cduart_softc *sc = arg;
271 struct tty *tp = sc->sc_tty;
272 int *ibufp;
273 uint32_t isr, sr;
274 int c, handled = 0;
275
276 if (tp == NULL)
277 return 0;
278
279 isr = cduart_read(sc, CDUART_ISR);
280 cduart_write(sc, CDUART_ISR, isr);
281
282 if ((isr & CDUART_IXR_TXEMPTY) && (tp->t_state & TS_BUSY)) {
283 tp->t_state &= ~TS_BUSY;
284 (*linesw[tp->t_line].l_start)(tp);
285 handled = 1;
286 }
287
288 if (isr & (CDUART_IXR_TOUT | CDUART_IXR_RTRIG)) {
289 ibufp = sc->sc_ibufp;
290 for (;;) {
291 sr = cduart_read(sc, CDUART_SR);
292 if (sr & CDUART_SR_RXEMPTY)
293 break;
294 c = cduart_read(sc, CDUART_FIFO) & 0xff;
295
296 if (ibufp < sc->sc_ibufend) {
297 *ibufp++ = c;
298 } else {
299 sc->sc_floods++;
300 if (sc->sc_errors++ == 0)
301 timeout_add_sec(&sc->sc_diag_tmo, 60);
302 }
303 }
304 if (sc->sc_ibufp != ibufp) {
305 sc->sc_ibufp = ibufp;
306 softintr_schedule(sc->sc_si);
307 }
308 handled = 1;
309 }
310
311 if (isr & CDUART_IXR_RXOVR) {
312 sc->sc_overflows++;
313 if (sc->sc_errors++ == 0)
314 timeout_add_sec(&sc->sc_diag_tmo, 60);
315 handled = 1;
316 }
317
318 return handled;
319 }
320
321 void
cduart_softintr(void * arg)322 cduart_softintr(void *arg)
323 {
324 struct cduart_softc *sc = arg;
325 struct tty *tp = sc->sc_tty;
326 int *ibufend, *ibufp;
327 int s;
328
329 s = spltty();
330
331 ibufp = sc->sc_ibuf;
332 ibufend = sc->sc_ibufp;
333
334 if (ibufp == ibufend) {
335 splx(s);
336 return;
337 }
338
339 sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
340 sc->sc_ibufs[1] : sc->sc_ibufs[0];
341 sc->sc_ibufend = sc->sc_ibuf + CDUART_IBUFSIZE;
342
343 if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0) {
344 splx(s);
345 return;
346 }
347
348 splx(s);
349
350 while (ibufp < ibufend)
351 (*linesw[tp->t_line].l_rint)(*ibufp++, tp);
352 }
353
354 void
cduart_diag(void * arg)355 cduart_diag(void *arg)
356 {
357 struct cduart_softc *sc = arg;
358 int overflows, floods;
359 int s;
360
361 s = spltty();
362 sc->sc_errors = 0;
363 overflows = sc->sc_overflows;
364 sc->sc_overflows = 0;
365 floods = sc->sc_floods;
366 sc->sc_floods = 0;
367 splx(s);
368 log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
369 sc->sc_dev.dv_xname,
370 overflows, overflows == 1 ? "" : "s",
371 floods, floods == 1 ? "" : "s");
372 }
373
374 int
cduartopen(dev_t dev,int flag,int mode,struct proc * p)375 cduartopen(dev_t dev, int flag, int mode, struct proc *p)
376 {
377 struct cduart_softc *sc;
378 struct tty *tp;
379 uint32_t sr;
380 int error, s;
381
382 sc = cduart_sc(dev);
383 if (sc == NULL)
384 return ENXIO;
385
386 s = spltty();
387
388 if (sc->sc_tty == NULL)
389 sc->sc_tty = ttymalloc(0);
390
391 tp = sc->sc_tty;
392 tp->t_oproc = cduartstart;
393 tp->t_param = cduartparam;
394 tp->t_dev = dev;
395 if ((tp->t_state & TS_ISOPEN) == 0) {
396 tp->t_state |= TS_WOPEN | TS_CARR_ON;
397 ttychars(tp);
398 tp->t_iflag = TTYDEF_IFLAG;
399 tp->t_oflag = TTYDEF_OFLAG;
400 tp->t_cflag = TTYDEF_CFLAG;
401 tp->t_lflag = TTYDEF_LFLAG;
402 tp->t_ispeed = B115200; /* XXX */
403 tp->t_ospeed = tp->t_ispeed;
404 ttsetwater(tp);
405
406 sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
407 sc->sc_ibufend = sc->sc_ibuf + CDUART_IBUFSIZE;
408
409 cduart_write(sc, CDUART_RXTOUT, 10);
410 cduart_write(sc, CDUART_RXWM, CDUART_FIFOSIZE / 2);
411
412 /* Clear any pending I/O. */
413 for (;;) {
414 sr = cduart_read(sc, CDUART_SR);
415 if (sr & CDUART_SR_RXEMPTY)
416 break;
417 (void)cduart_read(sc, CDUART_FIFO);
418 }
419
420 cduart_write(sc, CDUART_IER,
421 CDUART_IXR_TOUT | CDUART_IXR_RXOVR | CDUART_IXR_RTRIG);
422 } else if ((tp->t_state & TS_XCLUDE) && suser(p) != 0) {
423 splx(s);
424 return EBUSY;
425 }
426
427 if (DEVCUA(dev)) {
428 if (tp->t_state & TS_ISOPEN) {
429 splx(s);
430 return EBUSY;
431 }
432 sc->sc_cua = 1;
433 } else {
434 if ((flag & O_NONBLOCK) && sc->sc_cua) {
435 splx(s);
436 return EBUSY;
437 } else {
438 while (sc->sc_cua) {
439 tp->t_state |= TS_WOPEN;
440 error = ttysleep(tp, &tp->t_rawq,
441 TTIPRI | PCATCH, ttopen);
442 if (error != 0 && (tp->t_state & TS_WOPEN)) {
443 tp->t_state &= ~TS_WOPEN;
444 splx(s);
445 return error;
446 }
447 }
448 }
449 }
450
451 splx(s);
452
453 return (*linesw[tp->t_line].l_open)(dev, tp, p);
454 }
455
456 int
cduartclose(dev_t dev,int flag,int mode,struct proc * p)457 cduartclose(dev_t dev, int flag, int mode, struct proc *p)
458 {
459 struct cduart_softc *sc;
460 struct tty *tp;
461 int s;
462
463 sc = cduart_sc(dev);
464 tp = sc->sc_tty;
465
466 if ((tp->t_state & TS_ISOPEN) == 0)
467 return 0;
468
469 (*linesw[tp->t_line].l_close)(tp, flag, p);
470 s = spltty();
471 /* Disable interrupts. */
472 cduart_write(sc, CDUART_IDR, ~0U);
473 sc->sc_cua = 0;
474 splx(s);
475 ttyclose(tp);
476
477 return 0;
478 }
479
480 int
cduartread(dev_t dev,struct uio * uio,int flag)481 cduartread(dev_t dev, struct uio *uio, int flag)
482 {
483 struct tty *tp;
484
485 tp = cduarttty(dev);
486 if (tp == NULL)
487 return ENODEV;
488
489 return (*linesw[tp->t_line].l_read)(tp, uio, flag);
490 }
491
492 int
cduartwrite(dev_t dev,struct uio * uio,int flag)493 cduartwrite(dev_t dev, struct uio *uio, int flag)
494 {
495 struct tty *tp;
496
497 tp = cduarttty(dev);
498 if (tp == NULL)
499 return ENODEV;
500
501 return (*linesw[tp->t_line].l_write)(tp, uio, flag);
502 }
503
504 int
cduartioctl(dev_t dev,u_long cmd,caddr_t data,int flag,struct proc * p)505 cduartioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
506 {
507 struct cduart_softc *sc;
508 struct tty *tp;
509 int error;
510
511 sc = cduart_sc(dev);
512 if (sc == NULL)
513 return ENODEV;
514
515 tp = sc->sc_tty;
516 if (tp == NULL)
517 return ENXIO;
518
519 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
520 if (error >= 0)
521 return error;
522
523 error = ttioctl(tp, cmd, data, flag, p);
524 if (error >= 0)
525 return error;
526
527 /* XXX */
528 switch (cmd) {
529 case TIOCSBRK:
530 case TIOCCBRK:
531 case TIOCSDTR:
532 case TIOCCDTR:
533 case TIOCMSET:
534 case TIOCMBIC:
535 case TIOCMGET:
536 case TIOCGFLAGS:
537 break;
538 case TIOCSFLAGS:
539 error = suser(p);
540 if (error != 0)
541 return EPERM;
542 break;
543 default:
544 return ENOTTY;
545 }
546
547 return 0;
548 }
549
550 int
cduartparam(struct tty * tp,struct termios * t)551 cduartparam(struct tty *tp, struct termios *t)
552 {
553 return 0;
554 }
555
556 void
cduartstart(struct tty * tp)557 cduartstart(struct tty *tp)
558 {
559 struct cduart_softc *sc;
560 uint32_t sr;
561 int s;
562
563 sc = cduart_sc(tp->t_dev);
564
565 s = spltty();
566 if (tp->t_state & TS_BUSY)
567 goto out;
568 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))
569 goto stopped;
570 ttwakeupwr(tp);
571 if (tp->t_outq.c_cc == 0)
572 goto stopped;
573 tp->t_state |= TS_BUSY;
574
575 cduart_write(sc, CDUART_ISR, CDUART_IXR_TXEMPTY);
576
577 sr = cduart_read(sc, CDUART_SR);
578 while ((sr & CDUART_SR_TXFULL) == 0 && tp->t_outq.c_cc != 0) {
579 cduart_write(sc, CDUART_FIFO, getc(&tp->t_outq));
580 sr = cduart_read(sc, CDUART_SR);
581 }
582
583 cduart_write(sc, CDUART_IER, CDUART_IXR_TXEMPTY);
584 out:
585 splx(s);
586 return;
587 stopped:
588 cduart_write(sc, CDUART_IDR, CDUART_IXR_TXEMPTY);
589 splx(s);
590 }
591
592 int
cduartstop(struct tty * tp,int flag)593 cduartstop(struct tty *tp, int flag)
594 {
595 return 0;
596 }
597
598 struct tty *
cduarttty(dev_t dev)599 cduarttty(dev_t dev)
600 {
601 struct cduart_softc *sc;
602
603 sc = cduart_sc(dev);
604 if (sc == NULL)
605 return NULL;
606
607 return sc->sc_tty;
608 }
609
610 struct cduart_softc *
cduart_sc(dev_t dev)611 cduart_sc(dev_t dev)
612 {
613 int unit = DEVUNIT(dev);
614
615 if (unit >= cduart_cd.cd_ndevs)
616 return NULL;
617 return (struct cduart_softc *)cduart_cd.cd_devs[unit];
618 }
619
620 struct consdev cduartcons = {
621 .cn_probe = NULL,
622 .cn_init = NULL,
623 .cn_getc = cduartcngetc,
624 .cn_putc = cduartcnputc,
625 .cn_pollc = cduartcnpollc,
626 .cn_bell = NULL,
627 .cn_dev = NODEV,
628 .cn_pri = CN_MIDPRI,
629 };
630
631 int
cduartcnattach(bus_space_tag_t iot,bus_addr_t iobase,int rate,tcflag_t cflag)632 cduartcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate,
633 tcflag_t cflag)
634 {
635 bus_space_handle_t ioh;
636 int maj;
637
638 /* Look for major of com(4) to replace. */
639 for (maj = 0; maj < nchrdev; maj++) {
640 if (cdevsw[maj].d_open == comopen)
641 break;
642 }
643 if (maj == nchrdev)
644 return ENXIO;
645
646 if (bus_space_map(iot, iobase, CDUART_SPACE_SIZE, 0, &ioh) != 0)
647 return ENOMEM;
648
649 cn_tab = &cduartcons;
650 cn_tab->cn_dev = makedev(maj, 0);
651 cdevsw[maj] = cduartdev;
652
653 cduartconsiot = iot;
654 cduartconsioh = ioh;
655 cduartconsrate = rate;
656 cduartconscflag = cflag;
657
658 return 0;
659 }
660
661 void
cduartcnprobe(struct consdev * cp)662 cduartcnprobe(struct consdev *cp)
663 {
664 }
665
666 void
cduartcninit(struct consdev * cp)667 cduartcninit(struct consdev *cp)
668 {
669 }
670
671 int
cduartcngetc(dev_t dev)672 cduartcngetc(dev_t dev)
673 {
674 int s;
675 uint8_t c;
676
677 s = splhigh();
678 while (bus_space_read_4(cduartconsiot, cduartconsioh,
679 CDUART_SR) & CDUART_SR_RXEMPTY)
680 CPU_BUSY_CYCLE();
681 c = bus_space_read_4(cduartconsiot, cduartconsioh, CDUART_FIFO);
682 splx(s);
683
684 return c;
685 }
686
687 void
cduartcnputc(dev_t dev,int c)688 cduartcnputc(dev_t dev, int c)
689 {
690 int s;
691
692 s = splhigh();
693 while (bus_space_read_4(cduartconsiot, cduartconsioh,
694 CDUART_SR) & CDUART_SR_TXFULL)
695 CPU_BUSY_CYCLE();
696 bus_space_write_4(cduartconsiot, cduartconsioh, CDUART_FIFO, c);
697 splx(s);
698 }
699
700 void
cduartcnpollc(dev_t dev,int on)701 cduartcnpollc(dev_t dev, int on)
702 {
703 }
704