plcom.c revision 1.10 1 /* $NetBSD: plcom.c,v 1.10 2005/06/04 13:38:08 rearnsha Exp $ */
2
3 /*-
4 * Copyright (c) 2001 ARM Ltd
5 * All rights reserved.
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. The name of the company may not be used to endorse or promote
16 * products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
32 * All rights reserved.
33 *
34 * This code is derived from software contributed to The NetBSD Foundation
35 * by Charles M. Hannum.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the NetBSD
48 * Foundation, Inc. and its contributors.
49 * 4. Neither the name of The NetBSD Foundation nor the names of its
50 * contributors may be used to endorse or promote products derived
51 * from this software without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
54 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 * POSSIBILITY OF SUCH DAMAGE.
64 */
65
66 /*
67 * Copyright (c) 1991 The Regents of the University of California.
68 * All rights reserved.
69 *
70 * Redistribution and use in source and binary forms, with or without
71 * modification, are permitted provided that the following conditions
72 * are met:
73 * 1. Redistributions of source code must retain the above copyright
74 * notice, this list of conditions and the following disclaimer.
75 * 2. Redistributions in binary form must reproduce the above copyright
76 * notice, this list of conditions and the following disclaimer in the
77 * documentation and/or other materials provided with the distribution.
78 * 3. Neither the name of the University nor the names of its contributors
79 * may be used to endorse or promote products derived from this software
80 * without specific prior written permission.
81 *
82 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
83 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
84 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
85 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
86 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
87 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
88 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
89 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
90 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
91 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
92 * SUCH DAMAGE.
93 *
94 * @(#)com.c 7.5 (Berkeley) 5/16/91
95 */
96
97 /*
98 * COM driver for the Prime Cell PL010 UART, which is similar to the 16C550,
99 * but has a completely different programmer's model.
100 * Derived from the NS16550AF com driver.
101 */
102
103 #include <sys/cdefs.h>
104 __KERNEL_RCSID(0, "$NetBSD: plcom.c,v 1.10 2005/06/04 13:38:08 rearnsha Exp $");
105
106 #include "opt_plcom.h"
107 #include "opt_ddb.h"
108 #include "opt_kgdb.h"
109 #include "opt_lockdebug.h"
110 #include "opt_multiprocessor.h"
111
112 #include "rnd.h"
113 #if NRND > 0 && defined(RND_COM)
114 #include <sys/rnd.h>
115 #endif
116
117 /*
118 * Override cnmagic(9) macro before including <sys/systm.h>.
119 * We need to know if cn_check_magic triggered debugger, so set a flag.
120 * Callers of cn_check_magic must declare int cn_trapped = 0;
121 * XXX: this is *ugly*!
122 */
123 #define cn_trap() \
124 do { \
125 console_debugger(); \
126 cn_trapped = 1; \
127 } while (/* CONSTCOND */ 0)
128
129 #include <sys/param.h>
130 #include <sys/systm.h>
131 #include <sys/ioctl.h>
132 #include <sys/select.h>
133 #include <sys/tty.h>
134 #include <sys/proc.h>
135 #include <sys/user.h>
136 #include <sys/conf.h>
137 #include <sys/file.h>
138 #include <sys/uio.h>
139 #include <sys/kernel.h>
140 #include <sys/syslog.h>
141 #include <sys/types.h>
142 #include <sys/device.h>
143 #include <sys/malloc.h>
144 #include <sys/timepps.h>
145 #include <sys/vnode.h>
146
147 #include <machine/intr.h>
148 #include <machine/bus.h>
149
150 #include <evbarm/dev/plcomreg.h>
151 #include <evbarm/dev/plcomvar.h>
152
153 #include <dev/cons.h>
154
155 static void plcom_enable_debugport (struct plcom_softc *);
156
157 void plcom_config (struct plcom_softc *);
158 void plcom_shutdown (struct plcom_softc *);
159 int plcomspeed (long, long);
160 static u_char cflag2lcr (tcflag_t);
161 int plcomparam (struct tty *, struct termios *);
162 void plcomstart (struct tty *);
163 int plcomhwiflow (struct tty *, int);
164
165 void plcom_loadchannelregs (struct plcom_softc *);
166 void plcom_hwiflow (struct plcom_softc *);
167 void plcom_break (struct plcom_softc *, int);
168 void plcom_modem (struct plcom_softc *, int);
169 void tiocm_to_plcom (struct plcom_softc *, u_long, int);
170 int plcom_to_tiocm (struct plcom_softc *);
171 void plcom_iflush (struct plcom_softc *);
172
173 int plcom_common_getc (dev_t, bus_space_tag_t, bus_space_handle_t);
174 void plcom_common_putc (dev_t, bus_space_tag_t, bus_space_handle_t, int);
175
176 int plcominit (bus_space_tag_t, bus_addr_t, int, int, tcflag_t,
177 bus_space_handle_t *);
178
179 dev_type_open(plcomopen);
180 dev_type_close(plcomclose);
181 dev_type_read(plcomread);
182 dev_type_write(plcomwrite);
183 dev_type_ioctl(plcomioctl);
184 dev_type_stop(plcomstop);
185 dev_type_tty(plcomtty);
186 dev_type_poll(plcompoll);
187
188 int plcomcngetc (dev_t);
189 void plcomcnputc (dev_t, int);
190 void plcomcnpollc (dev_t, int);
191
192 #define integrate static inline
193 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
194 void plcomsoft (void *);
195 #else
196 #ifndef __NO_SOFT_SERIAL_INTERRUPT
197 void plcomsoft (void);
198 #else
199 void plcomsoft (void *);
200 struct callout plcomsoft_callout = CALLOUT_INITIALIZER;
201 #endif
202 #endif
203 integrate void plcom_rxsoft (struct plcom_softc *, struct tty *);
204 integrate void plcom_txsoft (struct plcom_softc *, struct tty *);
205 integrate void plcom_stsoft (struct plcom_softc *, struct tty *);
206 integrate void plcom_schedrx (struct plcom_softc *);
207 void plcomdiag (void *);
208
209 extern struct cfdriver plcom_cd;
210
211 const struct cdevsw plcom_cdevsw = {
212 plcomopen, plcomclose, plcomread, plcomwrite, plcomioctl,
213 plcomstop, plcomtty, plcompoll, nommap, ttykqfilter, D_TTY
214 };
215
216 /*
217 * Make this an option variable one can patch.
218 * But be warned: this must be a power of 2!
219 */
220 u_int plcom_rbuf_size = PLCOM_RING_SIZE;
221
222 /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */
223 u_int plcom_rbuf_hiwat = (PLCOM_RING_SIZE * 1) / 4;
224 u_int plcom_rbuf_lowat = (PLCOM_RING_SIZE * 3) / 4;
225
226 static int plcomconsunit = -1;
227 static bus_space_tag_t plcomconstag;
228 static bus_space_handle_t plcomconsioh;
229 static int plcomconsattached;
230 static int plcomconsrate;
231 static tcflag_t plcomconscflag;
232 static struct cnm_state plcom_cnm_state;
233
234 static int ppscap =
235 PPS_TSFMT_TSPEC |
236 PPS_CAPTUREASSERT |
237 PPS_CAPTURECLEAR |
238 #ifdef PPS_SYNC
239 PPS_HARDPPSONASSERT | PPS_HARDPPSONCLEAR |
240 #endif /* PPS_SYNC */
241 PPS_OFFSETASSERT | PPS_OFFSETCLEAR;
242
243 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
244 #ifdef __NO_SOFT_SERIAL_INTERRUPT
245 volatile int plcom_softintr_scheduled;
246 #endif
247 #endif
248
249 #ifdef KGDB
250 #include <sys/kgdb.h>
251
252 static int plcom_kgdb_unit;
253 static bus_space_tag_t plcom_kgdb_iot;
254 static bus_space_handle_t plcom_kgdb_ioh;
255 static int plcom_kgdb_attached;
256
257 int plcom_kgdb_getc (void *);
258 void plcom_kgdb_putc (void *, int);
259 #endif /* KGDB */
260
261 #define PLCOMUNIT_MASK 0x7ffff
262 #define PLCOMDIALOUT_MASK 0x80000
263
264 #define PLCOMUNIT(x) (minor(x) & PLCOMUNIT_MASK)
265 #define PLCOMDIALOUT(x) (minor(x) & PLCOMDIALOUT_MASK)
266
267 #define PLCOM_ISALIVE(sc) ((sc)->enabled != 0 && \
268 ISSET((sc)->sc_dev.dv_flags, DVF_ACTIVE))
269
270 #define BR BUS_SPACE_BARRIER_READ
271 #define BW BUS_SPACE_BARRIER_WRITE
272 #define PLCOM_BARRIER(t, h, f) bus_space_barrier((t), (h), 0, PLCOM_UART_SIZE, (f))
273
274 #if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && defined(PLCOM_MPLOCK)
275
276 #define PLCOM_LOCK(sc) simple_lock(&(sc)->sc_lock)
277 #define PLCOM_UNLOCK(sc) simple_unlock(&(sc)->sc_lock)
278
279 #else
280
281 #define PLCOM_LOCK(sc)
282 #define PLCOM_UNLOCK(sc)
283
284 #endif
285
286 int
287 plcomspeed(long speed, long frequency)
288 {
289 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
290
291 int x, err;
292
293 #if 0
294 if (speed == 0)
295 return 0;
296 #endif
297 if (speed <= 0)
298 return -1;
299 x = divrnd(frequency / 16, speed);
300 if (x <= 0)
301 return -1;
302 err = divrnd(((quad_t)frequency) * 1000 / 16, speed * x) - 1000;
303 if (err < 0)
304 err = -err;
305 if (err > PLCOM_TOLERANCE)
306 return -1;
307 return x;
308
309 #undef divrnd
310 }
311
312 #ifdef PLCOM_DEBUG
313 int plcom_debug = 0;
314
315 void plcomstatus (struct plcom_softc *, char *);
316 void
317 plcomstatus(struct plcom_softc *sc, char *str)
318 {
319 struct tty *tp = sc->sc_tty;
320
321 printf("%s: %s %sclocal %sdcd %sts_carr_on %sdtr %stx_stopped\n",
322 sc->sc_dev.dv_xname, str,
323 ISSET(tp->t_cflag, CLOCAL) ? "+" : "-",
324 ISSET(sc->sc_msr, MSR_DCD) ? "+" : "-",
325 ISSET(tp->t_state, TS_CARR_ON) ? "+" : "-",
326 ISSET(sc->sc_mcr, MCR_DTR) ? "+" : "-",
327 sc->sc_tx_stopped ? "+" : "-");
328
329 printf("%s: %s %scrtscts %scts %sts_ttstop %srts %xrx_flags\n",
330 sc->sc_dev.dv_xname, str,
331 ISSET(tp->t_cflag, CRTSCTS) ? "+" : "-",
332 ISSET(sc->sc_msr, MSR_CTS) ? "+" : "-",
333 ISSET(tp->t_state, TS_TTSTOP) ? "+" : "-",
334 ISSET(sc->sc_mcr, MCR_RTS) ? "+" : "-",
335 sc->sc_rx_flags);
336 }
337 #endif
338
339 int
340 plcomprobe1(bus_space_tag_t iot, bus_space_handle_t ioh)
341 {
342 int data;
343
344 /* Disable the UART. */
345 bus_space_write_1(iot, ioh, plcom_cr, 0);
346 /* Make sure the FIFO is off. */
347 bus_space_write_1(iot, ioh, plcom_lcr, LCR_8BITS);
348 /* Disable interrupts. */
349 bus_space_write_1(iot, ioh, plcom_iir, 0);
350
351 /* Make sure we swallow anything in the receiving register. */
352 data = bus_space_read_1(iot, ioh, plcom_dr);
353
354 if (bus_space_read_1(iot, ioh, plcom_lcr) != LCR_8BITS)
355 return 0;
356
357 data = bus_space_read_1(iot, ioh, plcom_fr) & (FR_RXFF | FR_RXFE);
358
359 if (data != FR_RXFE)
360 return 0;
361
362 return 1;
363 }
364
365 static void
366 plcom_enable_debugport(struct plcom_softc *sc)
367 {
368 int s;
369
370 /* Turn on line break interrupt, set carrier. */
371 s = splserial();
372 PLCOM_LOCK(sc);
373 sc->sc_cr = CR_RIE | CR_RTIE | CR_UARTEN;
374 bus_space_write_1(sc->sc_iot, sc->sc_ioh, plcom_cr, sc->sc_cr);
375 SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
376 sc->sc_set_mcr(sc->sc_set_mcr_arg, sc->sc_dev.dv_unit, sc->sc_mcr);
377 PLCOM_UNLOCK(sc);
378 splx(s);
379 }
380
381 void
382 plcom_attach_subr(struct plcom_softc *sc)
383 {
384 int unit = sc->sc_iounit;
385 bus_space_tag_t iot = sc->sc_iot;
386 bus_space_handle_t ioh = sc->sc_ioh;
387 struct tty *tp;
388
389 callout_init(&sc->sc_diag_callout);
390 #if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && defined(PLCOM_MPLOCK)
391 simple_lock_init(&sc->sc_lock);
392 #endif
393
394 /* Disable interrupts before configuring the device. */
395 sc->sc_cr = 0;
396
397 if (plcomconstag && unit == plcomconsunit) {
398 plcomconsattached = 1;
399
400 plcomconstag = iot;
401 plcomconsioh = ioh;
402
403 /* Make sure the console is always "hardwired". */
404 delay(1000); /* wait for output to finish */
405 SET(sc->sc_hwflags, PLCOM_HW_CONSOLE);
406 SET(sc->sc_swflags, TIOCFLAG_SOFTCAR);
407 /* Must re-enable the console immediately, or we will
408 hang when trying to print. */
409 sc->sc_cr = CR_UARTEN;
410 }
411
412 bus_space_write_1(iot, ioh, plcom_cr, sc->sc_cr);
413
414 /* The PL010 has a 16-byte fifo, but the tx interrupt triggers when
415 there is space for 8 more bytes. */
416 sc->sc_fifolen = 8;
417 printf("\n");
418
419 if (ISSET(sc->sc_hwflags, PLCOM_HW_TXFIFO_DISABLE)) {
420 sc->sc_fifolen = 1;
421 printf("%s: txfifo disabled\n", sc->sc_dev.dv_xname);
422 }
423
424 if (sc->sc_fifolen > 1)
425 SET(sc->sc_hwflags, PLCOM_HW_FIFO);
426
427 tp = ttymalloc();
428 tp->t_oproc = plcomstart;
429 tp->t_param = plcomparam;
430 tp->t_hwiflow = plcomhwiflow;
431
432 sc->sc_tty = tp;
433 sc->sc_rbuf = malloc(plcom_rbuf_size << 1, M_DEVBUF, M_NOWAIT);
434 sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
435 sc->sc_rbavail = plcom_rbuf_size;
436 if (sc->sc_rbuf == NULL) {
437 printf("%s: unable to allocate ring buffer\n",
438 sc->sc_dev.dv_xname);
439 return;
440 }
441 sc->sc_ebuf = sc->sc_rbuf + (plcom_rbuf_size << 1);
442
443 tty_attach(tp);
444
445 if (ISSET(sc->sc_hwflags, PLCOM_HW_CONSOLE)) {
446 int maj;
447
448 /* locate the major number */
449 maj = cdevsw_lookup_major(&plcom_cdevsw);
450
451 cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
452
453 printf("%s: console\n", sc->sc_dev.dv_xname);
454 }
455
456 #ifdef KGDB
457 /*
458 * Allow kgdb to "take over" this port. If this is
459 * the kgdb device, it has exclusive use.
460 */
461 if (iot == plcom_kgdb_iot && unit == plcom_kgdb_unit) {
462 plcom_kgdb_attached = 1;
463
464 SET(sc->sc_hwflags, PLCOM_HW_KGDB);
465 printf("%s: kgdb\n", sc->sc_dev.dv_xname);
466 }
467 #endif
468
469 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
470 sc->sc_si = softintr_establish(IPL_SOFTSERIAL, plcomsoft, sc);
471 #endif
472
473 #if NRND > 0 && defined(RND_COM)
474 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
475 RND_TYPE_TTY, 0);
476 #endif
477
478 /* if there are no enable/disable functions, assume the device
479 is always enabled */
480 if (!sc->enable)
481 sc->enabled = 1;
482
483 plcom_config(sc);
484
485 SET(sc->sc_hwflags, PLCOM_HW_DEV_OK);
486 }
487
488 void
489 plcom_config(struct plcom_softc *sc)
490 {
491 bus_space_tag_t iot = sc->sc_iot;
492 bus_space_handle_t ioh = sc->sc_ioh;
493
494 /* Disable interrupts before configuring the device. */
495 sc->sc_cr = 0;
496 bus_space_write_1(iot, ioh, plcom_cr, sc->sc_cr);
497
498 if (ISSET(sc->sc_hwflags, PLCOM_HW_CONSOLE|PLCOM_HW_KGDB))
499 plcom_enable_debugport(sc);
500 }
501
502 int
503 plcom_detach(self, flags)
504 struct device *self;
505 int flags;
506 {
507 struct plcom_softc *sc = (struct plcom_softc *)self;
508 int maj, mn;
509
510 /* locate the major number */
511 maj = cdevsw_lookup_major(&plcom_cdevsw);
512
513 /* Nuke the vnodes for any open instances. */
514 mn = self->dv_unit;
515 vdevgone(maj, mn, mn, VCHR);
516
517 mn |= PLCOMDIALOUT_MASK;
518 vdevgone(maj, mn, mn, VCHR);
519
520 /* Free the receive buffer. */
521 free(sc->sc_rbuf, M_DEVBUF);
522
523 /* Detach and free the tty. */
524 tty_detach(sc->sc_tty);
525 ttyfree(sc->sc_tty);
526
527 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
528 /* Unhook the soft interrupt handler. */
529 softintr_disestablish(sc->sc_si);
530 #endif
531
532 #if NRND > 0 && defined(RND_COM)
533 /* Unhook the entropy source. */
534 rnd_detach_source(&sc->rnd_source);
535 #endif
536
537 return 0;
538 }
539
540 int
541 plcom_activate(struct device *self, enum devact act)
542 {
543 struct plcom_softc *sc = (struct plcom_softc *)self;
544 int s, rv = 0;
545
546 s = splserial();
547 PLCOM_LOCK(sc);
548 switch (act) {
549 case DVACT_ACTIVATE:
550 rv = EOPNOTSUPP;
551 break;
552
553 case DVACT_DEACTIVATE:
554 if (sc->sc_hwflags & (PLCOM_HW_CONSOLE|PLCOM_HW_KGDB)) {
555 rv = EBUSY;
556 break;
557 }
558
559 if (sc->disable != NULL && sc->enabled != 0) {
560 (*sc->disable)(sc);
561 sc->enabled = 0;
562 }
563 break;
564 }
565
566 PLCOM_UNLOCK(sc);
567 splx(s);
568 return rv;
569 }
570
571 void
572 plcom_shutdown(struct plcom_softc *sc)
573 {
574 struct tty *tp = sc->sc_tty;
575 int s;
576
577 s = splserial();
578 PLCOM_LOCK(sc);
579
580 /* If we were asserting flow control, then deassert it. */
581 SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
582 plcom_hwiflow(sc);
583
584 /* Clear any break condition set with TIOCSBRK. */
585 plcom_break(sc, 0);
586
587 /* Turn off PPS capture on last close. */
588 sc->sc_ppsmask = 0;
589 sc->ppsparam.mode = 0;
590
591 /*
592 * Hang up if necessary. Wait a bit, so the other side has time to
593 * notice even if we immediately open the port again.
594 * Avoid tsleeping above splhigh().
595 */
596 if (ISSET(tp->t_cflag, HUPCL)) {
597 plcom_modem(sc, 0);
598 PLCOM_UNLOCK(sc);
599 splx(s);
600 /* XXX tsleep will only timeout */
601 (void) tsleep(sc, TTIPRI, ttclos, hz);
602 s = splserial();
603 PLCOM_LOCK(sc);
604 }
605
606 /* Turn off interrupts. */
607 if (ISSET(sc->sc_hwflags, PLCOM_HW_CONSOLE))
608 /* interrupt on break */
609 sc->sc_cr = CR_RIE | CR_RTIE | CR_UARTEN;
610 else
611 sc->sc_cr = 0;
612 bus_space_write_1(sc->sc_iot, sc->sc_ioh, plcom_cr, sc->sc_cr);
613
614 if (sc->disable) {
615 #ifdef DIAGNOSTIC
616 if (!sc->enabled)
617 panic("plcom_shutdown: not enabled?");
618 #endif
619 (*sc->disable)(sc);
620 sc->enabled = 0;
621 }
622 PLCOM_UNLOCK(sc);
623 splx(s);
624 }
625
626 int
627 plcomopen(dev_t dev, int flag, int mode, struct proc *p)
628 {
629 struct plcom_softc *sc;
630 struct tty *tp;
631 int s, s2;
632 int error;
633
634 sc = device_lookup(&plcom_cd, PLCOMUNIT(dev));
635 if (sc == NULL || !ISSET(sc->sc_hwflags, PLCOM_HW_DEV_OK) ||
636 sc->sc_rbuf == NULL)
637 return ENXIO;
638
639 if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0)
640 return ENXIO;
641
642 #ifdef KGDB
643 /*
644 * If this is the kgdb port, no other use is permitted.
645 */
646 if (ISSET(sc->sc_hwflags, PLCOM_HW_KGDB))
647 return EBUSY;
648 #endif
649
650 tp = sc->sc_tty;
651
652 if (ISSET(tp->t_state, TS_ISOPEN) &&
653 ISSET(tp->t_state, TS_XCLUDE) &&
654 p->p_ucred->cr_uid != 0)
655 return EBUSY;
656
657 s = spltty();
658
659 /*
660 * Do the following iff this is a first open.
661 */
662 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
663 struct termios t;
664
665 tp->t_dev = dev;
666
667 s2 = splserial();
668 PLCOM_LOCK(sc);
669
670 if (sc->enable) {
671 if ((*sc->enable)(sc)) {
672 PLCOM_UNLOCK(sc);
673 splx(s2);
674 splx(s);
675 printf("%s: device enable failed\n",
676 sc->sc_dev.dv_xname);
677 return EIO;
678 }
679 sc->enabled = 1;
680 plcom_config(sc);
681 }
682
683 /* Turn on interrupts. */
684 /* IER_ERXRDY | IER_ERLS | IER_EMSC; */
685 sc->sc_cr = CR_RIE | CR_RTIE | CR_MSIE | CR_UARTEN;
686 bus_space_write_1(sc->sc_iot, sc->sc_ioh, plcom_cr, sc->sc_cr);
687
688 /* Fetch the current modem control status, needed later. */
689 sc->sc_msr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, plcom_fr);
690
691 /* Clear PPS capture state on first open. */
692 sc->sc_ppsmask = 0;
693 sc->ppsparam.mode = 0;
694
695 PLCOM_UNLOCK(sc);
696 splx(s2);
697
698 /*
699 * Initialize the termios status to the defaults. Add in the
700 * sticky bits from TIOCSFLAGS.
701 */
702 t.c_ispeed = 0;
703 if (ISSET(sc->sc_hwflags, PLCOM_HW_CONSOLE)) {
704 t.c_ospeed = plcomconsrate;
705 t.c_cflag = plcomconscflag;
706 } else {
707 t.c_ospeed = TTYDEF_SPEED;
708 t.c_cflag = TTYDEF_CFLAG;
709 }
710 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
711 SET(t.c_cflag, CLOCAL);
712 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
713 SET(t.c_cflag, CRTSCTS);
714 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
715 SET(t.c_cflag, MDMBUF);
716 /* Make sure plcomparam() will do something. */
717 tp->t_ospeed = 0;
718 (void) plcomparam(tp, &t);
719 tp->t_iflag = TTYDEF_IFLAG;
720 tp->t_oflag = TTYDEF_OFLAG;
721 tp->t_lflag = TTYDEF_LFLAG;
722 ttychars(tp);
723 ttsetwater(tp);
724
725 s2 = splserial();
726 PLCOM_LOCK(sc);
727
728 /*
729 * Turn on DTR. We must always do this, even if carrier is not
730 * present, because otherwise we'd have to use TIOCSDTR
731 * immediately after setting CLOCAL, which applications do not
732 * expect. We always assert DTR while the device is open
733 * unless explicitly requested to deassert it.
734 */
735 plcom_modem(sc, 1);
736
737 /* Clear the input ring, and unblock. */
738 sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
739 sc->sc_rbavail = plcom_rbuf_size;
740 plcom_iflush(sc);
741 CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
742 plcom_hwiflow(sc);
743
744 #ifdef PLCOM_DEBUG
745 if (plcom_debug)
746 plcomstatus(sc, "plcomopen ");
747 #endif
748
749 PLCOM_UNLOCK(sc);
750 splx(s2);
751 }
752
753 splx(s);
754
755 error = ttyopen(tp, PLCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
756 if (error)
757 goto bad;
758
759 error = (*tp->t_linesw->l_open)(dev, tp);
760 if (error)
761 goto bad;
762
763 return 0;
764
765 bad:
766 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
767 /*
768 * We failed to open the device, and nobody else had it opened.
769 * Clean up the state as appropriate.
770 */
771 plcom_shutdown(sc);
772 }
773
774 return error;
775 }
776
777 int
778 plcomclose(dev_t dev, int flag, int mode, struct proc *p)
779 {
780 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev));
781 struct tty *tp = sc->sc_tty;
782
783 /* XXX This is for cons.c. */
784 if (!ISSET(tp->t_state, TS_ISOPEN))
785 return 0;
786
787 (*tp->t_linesw->l_close)(tp, flag);
788 ttyclose(tp);
789
790 if (PLCOM_ISALIVE(sc) == 0)
791 return 0;
792
793 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
794 /*
795 * Although we got a last close, the device may still be in
796 * use; e.g. if this was the dialout node, and there are still
797 * processes waiting for carrier on the non-dialout node.
798 */
799 plcom_shutdown(sc);
800 }
801
802 return 0;
803 }
804
805 int
806 plcomread(dev_t dev, struct uio *uio, int flag)
807 {
808 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev));
809 struct tty *tp = sc->sc_tty;
810
811 if (PLCOM_ISALIVE(sc) == 0)
812 return EIO;
813
814 return (*tp->t_linesw->l_read)(tp, uio, flag);
815 }
816
817 int
818 plcomwrite(dev_t dev, struct uio *uio, int flag)
819 {
820 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev));
821 struct tty *tp = sc->sc_tty;
822
823 if (PLCOM_ISALIVE(sc) == 0)
824 return EIO;
825
826 return (*tp->t_linesw->l_write)(tp, uio, flag);
827 }
828
829 int
830 plcompoll(dev_t dev, int events, struct proc *p)
831 {
832 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev));
833 struct tty *tp = sc->sc_tty;
834
835 if (PLCOM_ISALIVE(sc) == 0)
836 return EIO;
837
838 return (*tp->t_linesw->l_poll)(tp, events, p);
839 }
840
841 struct tty *
842 plcomtty(dev_t dev)
843 {
844 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev));
845 struct tty *tp = sc->sc_tty;
846
847 return tp;
848 }
849
850 int
851 plcomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
852 {
853 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev));
854 struct tty *tp = sc->sc_tty;
855 int error;
856 int s;
857
858 if (PLCOM_ISALIVE(sc) == 0)
859 return EIO;
860
861 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
862 if (error != EPASSTHROUGH)
863 return error;
864
865 error = ttioctl(tp, cmd, data, flag, p);
866 if (error != EPASSTHROUGH)
867 return error;
868
869 error = 0;
870
871 s = splserial();
872 PLCOM_LOCK(sc);
873
874 switch (cmd) {
875 case TIOCSBRK:
876 plcom_break(sc, 1);
877 break;
878
879 case TIOCCBRK:
880 plcom_break(sc, 0);
881 break;
882
883 case TIOCSDTR:
884 plcom_modem(sc, 1);
885 break;
886
887 case TIOCCDTR:
888 plcom_modem(sc, 0);
889 break;
890
891 case TIOCGFLAGS:
892 *(int *)data = sc->sc_swflags;
893 break;
894
895 case TIOCSFLAGS:
896 error = suser(p->p_ucred, &p->p_acflag);
897 if (error)
898 break;
899 sc->sc_swflags = *(int *)data;
900 break;
901
902 case TIOCMSET:
903 case TIOCMBIS:
904 case TIOCMBIC:
905 tiocm_to_plcom(sc, cmd, *(int *)data);
906 break;
907
908 case TIOCMGET:
909 *(int *)data = plcom_to_tiocm(sc);
910 break;
911
912 case PPS_IOC_CREATE:
913 break;
914
915 case PPS_IOC_DESTROY:
916 break;
917
918 case PPS_IOC_GETPARAMS: {
919 pps_params_t *pp;
920 pp = (pps_params_t *)data;
921 *pp = sc->ppsparam;
922 break;
923 }
924
925 case PPS_IOC_SETPARAMS: {
926 pps_params_t *pp;
927 int mode;
928 pp = (pps_params_t *)data;
929 if (pp->mode & ~ppscap) {
930 error = EINVAL;
931 break;
932 }
933 sc->ppsparam = *pp;
934 /*
935 * Compute msr masks from user-specified timestamp state.
936 */
937 mode = sc->ppsparam.mode;
938 #ifdef PPS_SYNC
939 if (mode & PPS_HARDPPSONASSERT) {
940 mode |= PPS_CAPTUREASSERT;
941 /* XXX revoke any previous HARDPPS source */
942 }
943 if (mode & PPS_HARDPPSONCLEAR) {
944 mode |= PPS_CAPTURECLEAR;
945 /* XXX revoke any previous HARDPPS source */
946 }
947 #endif /* PPS_SYNC */
948 switch (mode & PPS_CAPTUREBOTH) {
949 case 0:
950 sc->sc_ppsmask = 0;
951 break;
952
953 case PPS_CAPTUREASSERT:
954 sc->sc_ppsmask = MSR_DCD;
955 sc->sc_ppsassert = MSR_DCD;
956 sc->sc_ppsclear = -1;
957 break;
958
959 case PPS_CAPTURECLEAR:
960 sc->sc_ppsmask = MSR_DCD;
961 sc->sc_ppsassert = -1;
962 sc->sc_ppsclear = 0;
963 break;
964
965 case PPS_CAPTUREBOTH:
966 sc->sc_ppsmask = MSR_DCD;
967 sc->sc_ppsassert = MSR_DCD;
968 sc->sc_ppsclear = 0;
969 break;
970
971 default:
972 error = EINVAL;
973 break;
974 }
975 break;
976 }
977
978 case PPS_IOC_GETCAP:
979 *(int*)data = ppscap;
980 break;
981
982 case PPS_IOC_FETCH: {
983 pps_info_t *pi;
984 pi = (pps_info_t *)data;
985 *pi = sc->ppsinfo;
986 break;
987 }
988
989 case TIOCDCDTIMESTAMP: /* XXX old, overloaded API used by xntpd v3 */
990 /*
991 * Some GPS clocks models use the falling rather than
992 * rising edge as the on-the-second signal.
993 * The old API has no way to specify PPS polarity.
994 */
995 sc->sc_ppsmask = MSR_DCD;
996 #ifndef PPS_TRAILING_EDGE
997 sc->sc_ppsassert = MSR_DCD;
998 sc->sc_ppsclear = -1;
999 TIMESPEC_TO_TIMEVAL((struct timeval *)data,
1000 &sc->ppsinfo.assert_timestamp);
1001 #else
1002 sc->sc_ppsassert = -1
1003 sc->sc_ppsclear = 0;
1004 TIMESPEC_TO_TIMEVAL((struct timeval *)data,
1005 &sc->ppsinfo.clear_timestamp);
1006 #endif
1007 break;
1008
1009 default:
1010 error = EPASSTHROUGH;
1011 break;
1012 }
1013
1014 PLCOM_UNLOCK(sc);
1015 splx(s);
1016
1017 #ifdef PLCOM_DEBUG
1018 if (plcom_debug)
1019 plcomstatus(sc, "plcomioctl ");
1020 #endif
1021
1022 return error;
1023 }
1024
1025 integrate void
1026 plcom_schedrx(struct plcom_softc *sc)
1027 {
1028
1029 sc->sc_rx_ready = 1;
1030
1031 /* Wake up the poller. */
1032 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1033 softintr_schedule(sc->sc_si);
1034 #else
1035 #ifndef __NO_SOFT_SERIAL_INTERRUPT
1036 setsoftserial();
1037 #else
1038 if (!plcom_softintr_scheduled) {
1039 plcom_softintr_scheduled = 1;
1040 callout_reset(&plcomsoft_callout, 1, plcomsoft, NULL);
1041 }
1042 #endif
1043 #endif
1044 }
1045
1046 void
1047 plcom_break(struct plcom_softc *sc, int onoff)
1048 {
1049
1050 if (onoff)
1051 SET(sc->sc_lcr, LCR_BRK);
1052 else
1053 CLR(sc->sc_lcr, LCR_BRK);
1054
1055 if (!sc->sc_heldchange) {
1056 if (sc->sc_tx_busy) {
1057 sc->sc_heldtbc = sc->sc_tbc;
1058 sc->sc_tbc = 0;
1059 sc->sc_heldchange = 1;
1060 } else
1061 plcom_loadchannelregs(sc);
1062 }
1063 }
1064
1065 void
1066 plcom_modem(struct plcom_softc *sc, int onoff)
1067 {
1068
1069 if (sc->sc_mcr_dtr == 0)
1070 return;
1071
1072 if (onoff)
1073 SET(sc->sc_mcr, sc->sc_mcr_dtr);
1074 else
1075 CLR(sc->sc_mcr, sc->sc_mcr_dtr);
1076
1077 if (!sc->sc_heldchange) {
1078 if (sc->sc_tx_busy) {
1079 sc->sc_heldtbc = sc->sc_tbc;
1080 sc->sc_tbc = 0;
1081 sc->sc_heldchange = 1;
1082 } else
1083 plcom_loadchannelregs(sc);
1084 }
1085 }
1086
1087 void
1088 tiocm_to_plcom(struct plcom_softc *sc, u_long how, int ttybits)
1089 {
1090 u_char plcombits;
1091
1092 plcombits = 0;
1093 if (ISSET(ttybits, TIOCM_DTR))
1094 SET(plcombits, MCR_DTR);
1095 if (ISSET(ttybits, TIOCM_RTS))
1096 SET(plcombits, MCR_RTS);
1097
1098 switch (how) {
1099 case TIOCMBIC:
1100 CLR(sc->sc_mcr, plcombits);
1101 break;
1102
1103 case TIOCMBIS:
1104 SET(sc->sc_mcr, plcombits);
1105 break;
1106
1107 case TIOCMSET:
1108 CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
1109 SET(sc->sc_mcr, plcombits);
1110 break;
1111 }
1112
1113 if (!sc->sc_heldchange) {
1114 if (sc->sc_tx_busy) {
1115 sc->sc_heldtbc = sc->sc_tbc;
1116 sc->sc_tbc = 0;
1117 sc->sc_heldchange = 1;
1118 } else
1119 plcom_loadchannelregs(sc);
1120 }
1121 }
1122
1123 int
1124 plcom_to_tiocm(struct plcom_softc *sc)
1125 {
1126 u_char plcombits;
1127 int ttybits = 0;
1128
1129 plcombits = sc->sc_mcr;
1130 if (ISSET(plcombits, MCR_DTR))
1131 SET(ttybits, TIOCM_DTR);
1132 if (ISSET(plcombits, MCR_RTS))
1133 SET(ttybits, TIOCM_RTS);
1134
1135 plcombits = sc->sc_msr;
1136 if (ISSET(plcombits, MSR_DCD))
1137 SET(ttybits, TIOCM_CD);
1138 if (ISSET(plcombits, MSR_CTS))
1139 SET(ttybits, TIOCM_CTS);
1140 if (ISSET(plcombits, MSR_DSR))
1141 SET(ttybits, TIOCM_DSR);
1142
1143 if (sc->sc_cr != 0)
1144 SET(ttybits, TIOCM_LE);
1145
1146 return ttybits;
1147 }
1148
1149 static u_char
1150 cflag2lcr(tcflag_t cflag)
1151 {
1152 u_char lcr = 0;
1153
1154 switch (ISSET(cflag, CSIZE)) {
1155 case CS5:
1156 SET(lcr, LCR_5BITS);
1157 break;
1158 case CS6:
1159 SET(lcr, LCR_6BITS);
1160 break;
1161 case CS7:
1162 SET(lcr, LCR_7BITS);
1163 break;
1164 case CS8:
1165 SET(lcr, LCR_8BITS);
1166 break;
1167 }
1168 if (ISSET(cflag, PARENB)) {
1169 SET(lcr, LCR_PEN);
1170 if (!ISSET(cflag, PARODD))
1171 SET(lcr, LCR_EPS);
1172 }
1173 if (ISSET(cflag, CSTOPB))
1174 SET(lcr, LCR_STP2);
1175
1176 return lcr;
1177 }
1178
1179 int
1180 plcomparam(struct tty *tp, struct termios *t)
1181 {
1182 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(tp->t_dev));
1183 int ospeed;
1184 u_char lcr;
1185 int s;
1186
1187 if (PLCOM_ISALIVE(sc) == 0)
1188 return EIO;
1189
1190 ospeed = plcomspeed(t->c_ospeed, sc->sc_frequency);
1191
1192 /* Check requested parameters. */
1193 if (ospeed < 0)
1194 return EINVAL;
1195 if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
1196 return EINVAL;
1197
1198 /*
1199 * For the console, always force CLOCAL and !HUPCL, so that the port
1200 * is always active.
1201 */
1202 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
1203 ISSET(sc->sc_hwflags, PLCOM_HW_CONSOLE)) {
1204 SET(t->c_cflag, CLOCAL);
1205 CLR(t->c_cflag, HUPCL);
1206 }
1207
1208 /*
1209 * If there were no changes, don't do anything. This avoids dropping
1210 * input and improves performance when all we did was frob things like
1211 * VMIN and VTIME.
1212 */
1213 if (tp->t_ospeed == t->c_ospeed &&
1214 tp->t_cflag == t->c_cflag)
1215 return 0;
1216
1217 lcr = ISSET(sc->sc_lcr, LCR_BRK) | cflag2lcr(t->c_cflag);
1218
1219 s = splserial();
1220 PLCOM_LOCK(sc);
1221
1222 sc->sc_lcr = lcr;
1223
1224 /*
1225 * PL010 has a fixed-length FIFO trigger point.
1226 */
1227 if (ISSET(sc->sc_hwflags, PLCOM_HW_FIFO))
1228 sc->sc_fifo = 1;
1229 else
1230 sc->sc_fifo = 0;
1231
1232 if (sc->sc_fifo)
1233 SET(sc->sc_lcr, LCR_FEN);
1234
1235 /*
1236 * If we're not in a mode that assumes a connection is present, then
1237 * ignore carrier changes.
1238 */
1239 if (ISSET(t->c_cflag, CLOCAL | MDMBUF))
1240 sc->sc_msr_dcd = 0;
1241 else
1242 sc->sc_msr_dcd = MSR_DCD;
1243 /*
1244 * Set the flow control pins depending on the current flow control
1245 * mode.
1246 */
1247 if (ISSET(t->c_cflag, CRTSCTS)) {
1248 sc->sc_mcr_dtr = MCR_DTR;
1249 sc->sc_mcr_rts = MCR_RTS;
1250 sc->sc_msr_cts = MSR_CTS;
1251 } else if (ISSET(t->c_cflag, MDMBUF)) {
1252 /*
1253 * For DTR/DCD flow control, make sure we don't toggle DTR for
1254 * carrier detection.
1255 */
1256 sc->sc_mcr_dtr = 0;
1257 sc->sc_mcr_rts = MCR_DTR;
1258 sc->sc_msr_cts = MSR_DCD;
1259 } else {
1260 /*
1261 * If no flow control, then always set RTS. This will make
1262 * the other side happy if it mistakenly thinks we're doing
1263 * RTS/CTS flow control.
1264 */
1265 sc->sc_mcr_dtr = MCR_DTR | MCR_RTS;
1266 sc->sc_mcr_rts = 0;
1267 sc->sc_msr_cts = 0;
1268 if (ISSET(sc->sc_mcr, MCR_DTR))
1269 SET(sc->sc_mcr, MCR_RTS);
1270 else
1271 CLR(sc->sc_mcr, MCR_RTS);
1272 }
1273 sc->sc_msr_mask = sc->sc_msr_cts | sc->sc_msr_dcd;
1274
1275 #if 0
1276 if (ospeed == 0)
1277 CLR(sc->sc_mcr, sc->sc_mcr_dtr);
1278 else
1279 SET(sc->sc_mcr, sc->sc_mcr_dtr);
1280 #endif
1281
1282 sc->sc_dlbl = ospeed;
1283 sc->sc_dlbh = ospeed >> 8;
1284
1285 /* And copy to tty. */
1286 tp->t_ispeed = 0;
1287 tp->t_ospeed = t->c_ospeed;
1288 tp->t_cflag = t->c_cflag;
1289
1290 if (!sc->sc_heldchange) {
1291 if (sc->sc_tx_busy) {
1292 sc->sc_heldtbc = sc->sc_tbc;
1293 sc->sc_tbc = 0;
1294 sc->sc_heldchange = 1;
1295 } else
1296 plcom_loadchannelregs(sc);
1297 }
1298
1299 if (!ISSET(t->c_cflag, CHWFLOW)) {
1300 /* Disable the high water mark. */
1301 sc->sc_r_hiwat = 0;
1302 sc->sc_r_lowat = 0;
1303 if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
1304 CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
1305 plcom_schedrx(sc);
1306 }
1307 if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) {
1308 CLR(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED);
1309 plcom_hwiflow(sc);
1310 }
1311 } else {
1312 sc->sc_r_hiwat = plcom_rbuf_hiwat;
1313 sc->sc_r_lowat = plcom_rbuf_lowat;
1314 }
1315
1316 PLCOM_UNLOCK(sc);
1317 splx(s);
1318
1319 /*
1320 * Update the tty layer's idea of the carrier bit, in case we changed
1321 * CLOCAL or MDMBUF. We don't hang up here; we only do that by
1322 * explicit request.
1323 */
1324 (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, MSR_DCD));
1325
1326 #ifdef PLCOM_DEBUG
1327 if (plcom_debug)
1328 plcomstatus(sc, "plcomparam ");
1329 #endif
1330
1331 if (!ISSET(t->c_cflag, CHWFLOW)) {
1332 if (sc->sc_tx_stopped) {
1333 sc->sc_tx_stopped = 0;
1334 plcomstart(tp);
1335 }
1336 }
1337
1338 return 0;
1339 }
1340
1341 void
1342 plcom_iflush(struct plcom_softc *sc)
1343 {
1344 bus_space_tag_t iot = sc->sc_iot;
1345 bus_space_handle_t ioh = sc->sc_ioh;
1346 #ifdef DIAGNOSTIC
1347 int reg;
1348 #endif
1349 int timo;
1350
1351 #ifdef DIAGNOSTIC
1352 reg = 0xffff;
1353 #endif
1354 timo = 50000;
1355 /* flush any pending I/O */
1356 while (! ISSET(bus_space_read_1(iot, ioh, plcom_fr), FR_RXFE)
1357 && --timo)
1358 #ifdef DIAGNOSTIC
1359 reg =
1360 #else
1361 (void)
1362 #endif
1363 bus_space_read_1(iot, ioh, plcom_dr);
1364 #ifdef DIAGNOSTIC
1365 if (!timo)
1366 printf("%s: plcom_iflush timeout %02x\n", sc->sc_dev.dv_xname,
1367 reg);
1368 #endif
1369 }
1370
1371 void
1372 plcom_loadchannelregs(struct plcom_softc *sc)
1373 {
1374 bus_space_tag_t iot = sc->sc_iot;
1375 bus_space_handle_t ioh = sc->sc_ioh;
1376
1377 /* XXXXX necessary? */
1378 plcom_iflush(sc);
1379
1380 bus_space_write_1(iot, ioh, plcom_cr, 0);
1381
1382 bus_space_write_1(iot, ioh, plcom_dlbl, sc->sc_dlbl);
1383 bus_space_write_1(iot, ioh, plcom_dlbh, sc->sc_dlbh);
1384 bus_space_write_1(iot, ioh, plcom_lcr, sc->sc_lcr);
1385 sc->sc_set_mcr(sc->sc_set_mcr_arg, sc->sc_dev.dv_unit,
1386 sc->sc_mcr_active = sc->sc_mcr);
1387
1388 bus_space_write_1(iot, ioh, plcom_cr, sc->sc_cr);
1389 }
1390
1391 int
1392 plcomhwiflow(struct tty *tp, int block)
1393 {
1394 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(tp->t_dev));
1395 int s;
1396
1397 if (PLCOM_ISALIVE(sc) == 0)
1398 return 0;
1399
1400 if (sc->sc_mcr_rts == 0)
1401 return 0;
1402
1403 s = splserial();
1404 PLCOM_LOCK(sc);
1405
1406 if (block) {
1407 if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
1408 SET(sc->sc_rx_flags, RX_TTY_BLOCKED);
1409 plcom_hwiflow(sc);
1410 }
1411 } else {
1412 if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
1413 CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
1414 plcom_schedrx(sc);
1415 }
1416 if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
1417 CLR(sc->sc_rx_flags, RX_TTY_BLOCKED);
1418 plcom_hwiflow(sc);
1419 }
1420 }
1421
1422 PLCOM_UNLOCK(sc);
1423 splx(s);
1424 return 1;
1425 }
1426
1427 /*
1428 * (un)block input via hw flowcontrol
1429 */
1430 void
1431 plcom_hwiflow(struct plcom_softc *sc)
1432 {
1433 if (sc->sc_mcr_rts == 0)
1434 return;
1435
1436 if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) {
1437 CLR(sc->sc_mcr, sc->sc_mcr_rts);
1438 CLR(sc->sc_mcr_active, sc->sc_mcr_rts);
1439 } else {
1440 SET(sc->sc_mcr, sc->sc_mcr_rts);
1441 SET(sc->sc_mcr_active, sc->sc_mcr_rts);
1442 }
1443 sc->sc_set_mcr(sc->sc_set_mcr_arg, sc->sc_dev.dv_unit,
1444 sc->sc_mcr_active);
1445 }
1446
1447
1448 void
1449 plcomstart(struct tty *tp)
1450 {
1451 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(tp->t_dev));
1452 bus_space_tag_t iot = sc->sc_iot;
1453 bus_space_handle_t ioh = sc->sc_ioh;
1454 int s;
1455
1456 if (PLCOM_ISALIVE(sc) == 0)
1457 return;
1458
1459 s = spltty();
1460 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
1461 goto out;
1462 if (sc->sc_tx_stopped)
1463 goto out;
1464
1465 if (tp->t_outq.c_cc <= tp->t_lowat) {
1466 if (ISSET(tp->t_state, TS_ASLEEP)) {
1467 CLR(tp->t_state, TS_ASLEEP);
1468 wakeup(&tp->t_outq);
1469 }
1470 selwakeup(&tp->t_wsel);
1471 if (tp->t_outq.c_cc == 0)
1472 goto out;
1473 }
1474
1475 /* Grab the first contiguous region of buffer space. */
1476 {
1477 u_char *tba;
1478 int tbc;
1479
1480 tba = tp->t_outq.c_cf;
1481 tbc = ndqb(&tp->t_outq, 0);
1482
1483 (void)splserial();
1484 PLCOM_LOCK(sc);
1485
1486 sc->sc_tba = tba;
1487 sc->sc_tbc = tbc;
1488 }
1489
1490 SET(tp->t_state, TS_BUSY);
1491 sc->sc_tx_busy = 1;
1492
1493 /* Enable transmit completion interrupts if necessary. */
1494 if (!ISSET(sc->sc_cr, CR_TIE)) {
1495 SET(sc->sc_cr, CR_TIE);
1496 bus_space_write_1(iot, ioh, plcom_cr, sc->sc_cr);
1497 }
1498
1499 /* Output the first chunk of the contiguous buffer. */
1500 {
1501 int n;
1502
1503 n = sc->sc_tbc;
1504 if (n > sc->sc_fifolen)
1505 n = sc->sc_fifolen;
1506 bus_space_write_multi_1(iot, ioh, plcom_dr, sc->sc_tba, n);
1507 sc->sc_tbc -= n;
1508 sc->sc_tba += n;
1509 }
1510 PLCOM_UNLOCK(sc);
1511 out:
1512 splx(s);
1513 return;
1514 }
1515
1516 /*
1517 * Stop output on a line.
1518 */
1519 void
1520 plcomstop(struct tty *tp, int flag)
1521 {
1522 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(tp->t_dev));
1523 int s;
1524
1525 s = splserial();
1526 PLCOM_LOCK(sc);
1527 if (ISSET(tp->t_state, TS_BUSY)) {
1528 /* Stop transmitting at the next chunk. */
1529 sc->sc_tbc = 0;
1530 sc->sc_heldtbc = 0;
1531 if (!ISSET(tp->t_state, TS_TTSTOP))
1532 SET(tp->t_state, TS_FLUSH);
1533 }
1534 PLCOM_UNLOCK(sc);
1535 splx(s);
1536 }
1537
1538 void
1539 plcomdiag(void *arg)
1540 {
1541 struct plcom_softc *sc = arg;
1542 int overflows, floods;
1543 int s;
1544
1545 s = splserial();
1546 PLCOM_LOCK(sc);
1547 overflows = sc->sc_overflows;
1548 sc->sc_overflows = 0;
1549 floods = sc->sc_floods;
1550 sc->sc_floods = 0;
1551 sc->sc_errors = 0;
1552 PLCOM_UNLOCK(sc);
1553 splx(s);
1554
1555 log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n",
1556 sc->sc_dev.dv_xname,
1557 overflows, overflows == 1 ? "" : "s",
1558 floods, floods == 1 ? "" : "s");
1559 }
1560
1561 integrate void
1562 plcom_rxsoft(struct plcom_softc *sc, struct tty *tp)
1563 {
1564 int (*rint) (int, struct tty *) = tp->t_linesw->l_rint;
1565 u_char *get, *end;
1566 u_int cc, scc;
1567 u_char rsr;
1568 int code;
1569 int s;
1570
1571 end = sc->sc_ebuf;
1572 get = sc->sc_rbget;
1573 scc = cc = plcom_rbuf_size - sc->sc_rbavail;
1574
1575 if (cc == plcom_rbuf_size) {
1576 sc->sc_floods++;
1577 if (sc->sc_errors++ == 0)
1578 callout_reset(&sc->sc_diag_callout, 60 * hz,
1579 plcomdiag, sc);
1580 }
1581
1582 while (cc) {
1583 code = get[0];
1584 rsr = get[1];
1585 if (ISSET(rsr, RSR_OE | RSR_BE | RSR_FE | RSR_PE)) {
1586 if (ISSET(rsr, RSR_OE)) {
1587 sc->sc_overflows++;
1588 if (sc->sc_errors++ == 0)
1589 callout_reset(&sc->sc_diag_callout,
1590 60 * hz, plcomdiag, sc);
1591 }
1592 if (ISSET(rsr, RSR_BE | RSR_FE))
1593 SET(code, TTY_FE);
1594 if (ISSET(rsr, RSR_PE))
1595 SET(code, TTY_PE);
1596 }
1597 if ((*rint)(code, tp) == -1) {
1598 /*
1599 * The line discipline's buffer is out of space.
1600 */
1601 if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
1602 /*
1603 * We're either not using flow control, or the
1604 * line discipline didn't tell us to block for
1605 * some reason. Either way, we have no way to
1606 * know when there's more space available, so
1607 * just drop the rest of the data.
1608 */
1609 get += cc << 1;
1610 if (get >= end)
1611 get -= plcom_rbuf_size << 1;
1612 cc = 0;
1613 } else {
1614 /*
1615 * Don't schedule any more receive processing
1616 * until the line discipline tells us there's
1617 * space available (through plcomhwiflow()).
1618 * Leave the rest of the data in the input
1619 * buffer.
1620 */
1621 SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
1622 }
1623 break;
1624 }
1625 get += 2;
1626 if (get >= end)
1627 get = sc->sc_rbuf;
1628 cc--;
1629 }
1630
1631 if (cc != scc) {
1632 sc->sc_rbget = get;
1633 s = splserial();
1634 PLCOM_LOCK(sc);
1635
1636 cc = sc->sc_rbavail += scc - cc;
1637 /* Buffers should be ok again, release possible block. */
1638 if (cc >= sc->sc_r_lowat) {
1639 if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
1640 CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
1641 SET(sc->sc_cr, CR_RIE | CR_RTIE);
1642 bus_space_write_1(sc->sc_iot, sc->sc_ioh, plcom_cr, sc->sc_cr);
1643 }
1644 if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) {
1645 CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED);
1646 plcom_hwiflow(sc);
1647 }
1648 }
1649 PLCOM_UNLOCK(sc);
1650 splx(s);
1651 }
1652 }
1653
1654 integrate void
1655 plcom_txsoft(struct plcom_softc *sc, struct tty *tp)
1656 {
1657
1658 CLR(tp->t_state, TS_BUSY);
1659 if (ISSET(tp->t_state, TS_FLUSH))
1660 CLR(tp->t_state, TS_FLUSH);
1661 else
1662 ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf));
1663 (*tp->t_linesw->l_start)(tp);
1664 }
1665
1666 integrate void
1667 plcom_stsoft(struct plcom_softc *sc, struct tty *tp)
1668 {
1669 u_char msr, delta;
1670 int s;
1671
1672 s = splserial();
1673 PLCOM_LOCK(sc);
1674 msr = sc->sc_msr;
1675 delta = sc->sc_msr_delta;
1676 sc->sc_msr_delta = 0;
1677 PLCOM_UNLOCK(sc);
1678 splx(s);
1679
1680 if (ISSET(delta, sc->sc_msr_dcd)) {
1681 /*
1682 * Inform the tty layer that carrier detect changed.
1683 */
1684 (void) (*tp->t_linesw->l_modem)(tp, ISSET(msr, MSR_DCD));
1685 }
1686
1687 if (ISSET(delta, sc->sc_msr_cts)) {
1688 /* Block or unblock output according to flow control. */
1689 if (ISSET(msr, sc->sc_msr_cts)) {
1690 sc->sc_tx_stopped = 0;
1691 (*tp->t_linesw->l_start)(tp);
1692 } else {
1693 sc->sc_tx_stopped = 1;
1694 }
1695 }
1696
1697 #ifdef PLCOM_DEBUG
1698 if (plcom_debug)
1699 plcomstatus(sc, "plcom_stsoft");
1700 #endif
1701 }
1702
1703 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1704 void
1705 plcomsoft(void *arg)
1706 {
1707 struct plcom_softc *sc = arg;
1708 struct tty *tp;
1709
1710 if (PLCOM_ISALIVE(sc) == 0)
1711 return;
1712
1713 {
1714 #else
1715 void
1716 #ifndef __NO_SOFT_SERIAL_INTERRUPT
1717 plcomsoft(void)
1718 #else
1719 plcomsoft(void *arg)
1720 #endif
1721 {
1722 struct plcom_softc *sc;
1723 struct tty *tp;
1724 int unit;
1725 #ifdef __NO_SOFT_SERIAL_INTERRUPT
1726 int s;
1727
1728 s = splsoftserial();
1729 plcom_softintr_scheduled = 0;
1730 #endif
1731
1732 for (unit = 0; unit < plcom_cd.cd_ndevs; unit++) {
1733 sc = device_lookup(&plcom_cd, unit);
1734 if (sc == NULL || !ISSET(sc->sc_hwflags, PLCOM_HW_DEV_OK))
1735 continue;
1736
1737 if (PLCOM_ISALIVE(sc) == 0)
1738 continue;
1739
1740 tp = sc->sc_tty;
1741 if (tp == NULL)
1742 continue;
1743 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0)
1744 continue;
1745 #endif
1746 tp = sc->sc_tty;
1747
1748 if (sc->sc_rx_ready) {
1749 sc->sc_rx_ready = 0;
1750 plcom_rxsoft(sc, tp);
1751 }
1752
1753 if (sc->sc_st_check) {
1754 sc->sc_st_check = 0;
1755 plcom_stsoft(sc, tp);
1756 }
1757
1758 if (sc->sc_tx_done) {
1759 sc->sc_tx_done = 0;
1760 plcom_txsoft(sc, tp);
1761 }
1762 }
1763
1764 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
1765 #ifdef __NO_SOFT_SERIAL_INTERRUPT
1766 splx(s);
1767 #endif
1768 #endif
1769 }
1770
1771 #ifdef __ALIGN_BRACKET_LEVEL_FOR_CTAGS
1772 /* there has got to be a better way to do plcomsoft() */
1773 }}
1774 #endif
1775
1776 int
1777 plcomintr(void *arg)
1778 {
1779 struct plcom_softc *sc = arg;
1780 bus_space_tag_t iot = sc->sc_iot;
1781 bus_space_handle_t ioh = sc->sc_ioh;
1782 u_char *put, *end;
1783 u_int cc;
1784 u_char rsr, iir;
1785
1786 if (PLCOM_ISALIVE(sc) == 0)
1787 return 0;
1788
1789 PLCOM_LOCK(sc);
1790 iir = bus_space_read_1(iot, ioh, plcom_iir);
1791 if (! ISSET(iir, IIR_IMASK)) {
1792 PLCOM_UNLOCK(sc);
1793 return 0;
1794 }
1795
1796 end = sc->sc_ebuf;
1797 put = sc->sc_rbput;
1798 cc = sc->sc_rbavail;
1799
1800 do {
1801 u_char msr, delta, fr;
1802
1803 fr = bus_space_read_1(iot, ioh, plcom_fr);
1804
1805 if (!ISSET(fr, FR_RXFE) &&
1806 !ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
1807 while (cc > 0) {
1808 int cn_trapped = 0;
1809 put[0] = bus_space_read_1(iot, ioh,
1810 plcom_dr);
1811 rsr = bus_space_read_1(iot, ioh, plcom_rsr);
1812 /* Clear any error status. */
1813 if (ISSET(rsr,
1814 (RSR_BE | RSR_OE | RSR_PE | RSR_FE)))
1815 bus_space_write_1(iot, ioh, plcom_ecr,
1816 0);
1817 if (ISSET(rsr, RSR_BE)) {
1818 cn_trapped = 0;
1819 cn_check_magic(sc->sc_tty->t_dev,
1820 CNC_BREAK, plcom_cnm_state);
1821 if (cn_trapped)
1822 continue;
1823 #if defined(KGDB)
1824 if (ISSET(sc->sc_hwflags,
1825 PLCOM_HW_KGDB)) {
1826 kgdb_connect(1);
1827 continue;
1828 }
1829 #endif
1830 }
1831
1832 put[1] = rsr;
1833 cn_trapped = 0;
1834 cn_check_magic(sc->sc_tty->t_dev,
1835 put[0], plcom_cnm_state);
1836 if (cn_trapped) {
1837 fr = bus_space_read_1(iot, ioh,
1838 plcom_fr);
1839 if (ISSET(fr, FR_RXFE))
1840 break;
1841
1842 continue;
1843 }
1844 put += 2;
1845 if (put >= end)
1846 put = sc->sc_rbuf;
1847 cc--;
1848
1849 fr = bus_space_read_1(iot, ioh, plcom_fr);
1850 if (ISSET(fr, FR_RXFE))
1851 break;
1852 }
1853
1854 /*
1855 * Current string of incoming characters ended because
1856 * no more data was available or we ran out of space.
1857 * Schedule a receive event if any data was received.
1858 * If we're out of space, turn off receive interrupts.
1859 */
1860 sc->sc_rbput = put;
1861 sc->sc_rbavail = cc;
1862 if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
1863 sc->sc_rx_ready = 1;
1864
1865 /*
1866 * See if we are in danger of overflowing a buffer. If
1867 * so, use hardware flow control to ease the pressure.
1868 */
1869 if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) &&
1870 cc < sc->sc_r_hiwat) {
1871 SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
1872 plcom_hwiflow(sc);
1873 }
1874
1875 /*
1876 * If we're out of space, disable receive interrupts
1877 * until the queue has drained a bit.
1878 */
1879 if (!cc) {
1880 SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
1881 CLR(sc->sc_cr, CR_RIE | CR_RTIE);
1882 bus_space_write_1(iot, ioh, plcom_cr,
1883 sc->sc_cr);
1884 }
1885 } else {
1886 if (ISSET(iir, IIR_RIS)) {
1887 bus_space_write_1(iot, ioh, plcom_cr, 0);
1888 delay(10);
1889 bus_space_write_1(iot, ioh, plcom_cr,
1890 sc->sc_cr);
1891 continue;
1892 }
1893 }
1894
1895 msr = bus_space_read_1(iot, ioh, plcom_fr);
1896 delta = msr ^ sc->sc_msr;
1897 sc->sc_msr = msr;
1898 /* Clear any pending modem status interrupt. */
1899 if (iir & IIR_MIS)
1900 bus_space_write_1(iot, ioh, plcom_icr, 0);
1901 /*
1902 * Pulse-per-second (PSS) signals on edge of DCD?
1903 * Process these even if line discipline is ignoring DCD.
1904 */
1905 if (delta & sc->sc_ppsmask) {
1906 struct timeval tv;
1907 if ((msr & sc->sc_ppsmask) == sc->sc_ppsassert) {
1908 /* XXX nanotime() */
1909 microtime(&tv);
1910 TIMEVAL_TO_TIMESPEC(&tv,
1911 &sc->ppsinfo.assert_timestamp);
1912 if (sc->ppsparam.mode & PPS_OFFSETASSERT) {
1913 timespecadd(&sc->ppsinfo.assert_timestamp,
1914 &sc->ppsparam.assert_offset,
1915 &sc->ppsinfo.assert_timestamp);
1916 }
1917
1918 #ifdef PPS_SYNC
1919 if (sc->ppsparam.mode & PPS_HARDPPSONASSERT)
1920 hardpps(&tv, tv.tv_usec);
1921 #endif
1922 sc->ppsinfo.assert_sequence++;
1923 sc->ppsinfo.current_mode = sc->ppsparam.mode;
1924
1925 } else if ((msr & sc->sc_ppsmask) == sc->sc_ppsclear) {
1926 /* XXX nanotime() */
1927 microtime(&tv);
1928 TIMEVAL_TO_TIMESPEC(&tv,
1929 &sc->ppsinfo.clear_timestamp);
1930 if (sc->ppsparam.mode & PPS_OFFSETCLEAR) {
1931 timespecadd(&sc->ppsinfo.clear_timestamp,
1932 &sc->ppsparam.clear_offset,
1933 &sc->ppsinfo.clear_timestamp);
1934 }
1935
1936 #ifdef PPS_SYNC
1937 if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR)
1938 hardpps(&tv, tv.tv_usec);
1939 #endif
1940 sc->ppsinfo.clear_sequence++;
1941 sc->ppsinfo.current_mode = sc->ppsparam.mode;
1942 }
1943 }
1944
1945 /*
1946 * Process normal status changes
1947 */
1948 if (ISSET(delta, sc->sc_msr_mask)) {
1949 SET(sc->sc_msr_delta, delta);
1950
1951 /*
1952 * Stop output immediately if we lose the output
1953 * flow control signal or carrier detect.
1954 */
1955 if (ISSET(~msr, sc->sc_msr_mask)) {
1956 sc->sc_tbc = 0;
1957 sc->sc_heldtbc = 0;
1958 #ifdef PLCOM_DEBUG
1959 if (plcom_debug)
1960 plcomstatus(sc, "plcomintr ");
1961 #endif
1962 }
1963
1964 sc->sc_st_check = 1;
1965 }
1966
1967 /*
1968 * Done handling any receive interrupts. See if data
1969 * can be * transmitted as well. Schedule tx done
1970 * event if no data left * and tty was marked busy.
1971 */
1972 if (ISSET(iir, IIR_TIS)) {
1973 /*
1974 * If we've delayed a parameter change, do it
1975 * now, and restart * output.
1976 */
1977 if (sc->sc_heldchange) {
1978 plcom_loadchannelregs(sc);
1979 sc->sc_heldchange = 0;
1980 sc->sc_tbc = sc->sc_heldtbc;
1981 sc->sc_heldtbc = 0;
1982 }
1983
1984 /*
1985 * Output the next chunk of the contiguous
1986 * buffer, if any.
1987 */
1988 if (sc->sc_tbc > 0) {
1989 int n;
1990
1991 n = sc->sc_tbc;
1992 if (n > sc->sc_fifolen)
1993 n = sc->sc_fifolen;
1994 bus_space_write_multi_1(iot, ioh, plcom_dr,
1995 sc->sc_tba, n);
1996 sc->sc_tbc -= n;
1997 sc->sc_tba += n;
1998 } else {
1999 /*
2000 * Disable transmit plcompletion
2001 * interrupts if necessary.
2002 */
2003 if (ISSET(sc->sc_cr, CR_TIE)) {
2004 CLR(sc->sc_cr, CR_TIE);
2005 bus_space_write_1(iot, ioh, plcom_cr,
2006 sc->sc_cr);
2007 }
2008 if (sc->sc_tx_busy) {
2009 sc->sc_tx_busy = 0;
2010 sc->sc_tx_done = 1;
2011 }
2012 }
2013 }
2014 } while (ISSET((iir = bus_space_read_1(iot, ioh, plcom_iir)),
2015 IIR_IMASK));
2016
2017 PLCOM_UNLOCK(sc);
2018
2019 /* Wake up the poller. */
2020 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
2021 softintr_schedule(sc->sc_si);
2022 #else
2023 #ifndef __NO_SOFT_SERIAL_INTERRUPT
2024 setsoftserial();
2025 #else
2026 if (!plcom_softintr_scheduled) {
2027 plcom_softintr_scheduled = 1;
2028 callout_reset(&plcomsoft_callout, 1, plcomsoft, NULL);
2029 }
2030 #endif
2031 #endif
2032
2033 #if NRND > 0 && defined(RND_COM)
2034 rnd_add_uint32(&sc->rnd_source, iir | rsr);
2035 #endif
2036
2037 return 1;
2038 }
2039
2040 /*
2041 * The following functions are polled getc and putc routines, shared
2042 * by the console and kgdb glue.
2043 *
2044 * The read-ahead code is so that you can detect pending in-band
2045 * cn_magic in polled mode while doing output rather than having to
2046 * wait until the kernel decides it needs input.
2047 */
2048
2049 #define MAX_READAHEAD 20
2050 static int plcom_readahead[MAX_READAHEAD];
2051 static int plcom_readaheadcount = 0;
2052
2053 int
2054 plcom_common_getc(dev_t dev, bus_space_tag_t iot, bus_space_handle_t ioh)
2055 {
2056 int s = splserial();
2057 u_char stat, c;
2058
2059 /* got a character from reading things earlier */
2060 if (plcom_readaheadcount > 0) {
2061 int i;
2062
2063 c = plcom_readahead[0];
2064 for (i = 1; i < plcom_readaheadcount; i++) {
2065 plcom_readahead[i-1] = plcom_readahead[i];
2066 }
2067 plcom_readaheadcount--;
2068 splx(s);
2069 return c;
2070 }
2071
2072 /* block until a character becomes available */
2073 while (ISSET(stat = bus_space_read_1(iot, ioh, plcom_fr), FR_RXFE))
2074 ;
2075
2076 c = bus_space_read_1(iot, ioh, plcom_dr);
2077 stat = bus_space_read_1(iot, ioh, plcom_iir);
2078 {
2079 int cn_trapped = 0; /* unused */
2080 #ifdef DDB
2081 extern int db_active;
2082 if (!db_active)
2083 #endif
2084 cn_check_magic(dev, c, plcom_cnm_state);
2085 }
2086 splx(s);
2087 return c;
2088 }
2089
2090 void
2091 plcom_common_putc(dev_t dev, bus_space_tag_t iot, bus_space_handle_t ioh,
2092 int c)
2093 {
2094 int s = splserial();
2095 int timo;
2096
2097 int cin, stat;
2098 if (plcom_readaheadcount < MAX_READAHEAD
2099 && !ISSET(stat = bus_space_read_1(iot, ioh, plcom_fr), FR_RXFE)) {
2100 int cn_trapped = 0;
2101 cin = bus_space_read_1(iot, ioh, plcom_dr);
2102 stat = bus_space_read_1(iot, ioh, plcom_iir);
2103 cn_check_magic(dev, cin, plcom_cnm_state);
2104 plcom_readahead[plcom_readaheadcount++] = cin;
2105 }
2106
2107 /* wait for any pending transmission to finish */
2108 timo = 150000;
2109 while (!ISSET(bus_space_read_1(iot, ioh, plcom_fr), FR_TXFE) && --timo)
2110 continue;
2111
2112 bus_space_write_1(iot, ioh, plcom_dr, c);
2113 PLCOM_BARRIER(iot, ioh, BR | BW);
2114
2115 /* wait for this transmission to complete */
2116 timo = 1500000;
2117 while (!ISSET(bus_space_read_1(iot, ioh, plcom_fr), FR_TXFE) && --timo)
2118 continue;
2119
2120 splx(s);
2121 }
2122
2123 /*
2124 * Initialize UART for use as console or KGDB line.
2125 */
2126 int
2127 plcominit(bus_space_tag_t iot, bus_addr_t iobase, int rate, int frequency,
2128 tcflag_t cflag, bus_space_handle_t *iohp)
2129 {
2130 bus_space_handle_t ioh;
2131
2132 if (bus_space_map(iot, iobase, PLCOM_UART_SIZE, 0, &ioh))
2133 return ENOMEM; /* ??? */
2134
2135 rate = plcomspeed(rate, frequency);
2136 bus_space_write_1(iot, ioh, plcom_cr, 0);
2137 bus_space_write_1(iot, ioh, plcom_dlbl, rate);
2138 bus_space_write_1(iot, ioh, plcom_dlbh, rate >> 8);
2139 bus_space_write_1(iot, ioh, plcom_lcr, cflag2lcr(cflag) | LCR_FEN);
2140 bus_space_write_1(iot, ioh, plcom_cr, CR_UARTEN);
2141
2142 #if 0
2143 /* Ought to do something like this, but we have no sc to
2144 dereference. */
2145 sc->sc_set_mcr(sc->sc_set_mcr_arg, sc->sc_dev.dv_unit,
2146 MCR_DTR | MCR_RTS);
2147 #endif
2148
2149 *iohp = ioh;
2150 return 0;
2151 }
2152
2153 /*
2154 * Following are all routines needed for PLCOM to act as console
2155 */
2156 struct consdev plcomcons = {
2157 NULL, NULL, plcomcngetc, plcomcnputc, plcomcnpollc, NULL,
2158 NULL, NULL, NODEV, CN_NORMAL
2159 };
2160
2161
2162 int
2163 plcomcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, int frequency,
2164 tcflag_t cflag, int unit)
2165 {
2166 int res;
2167
2168 res = plcominit(iot, iobase, rate, frequency, cflag, &plcomconsioh);
2169 if (res)
2170 return res;
2171
2172 cn_tab = &plcomcons;
2173 cn_init_magic(&plcom_cnm_state);
2174 cn_set_magic("\047\001"); /* default magic is BREAK */
2175
2176 plcomconstag = iot;
2177 plcomconsunit = unit;
2178 plcomconsrate = rate;
2179 plcomconscflag = cflag;
2180
2181 return 0;
2182 }
2183
2184 void
2185 plcomcndetach(void)
2186 {
2187 bus_space_unmap(plcomconstag, plcomconsioh, PLCOM_UART_SIZE);
2188 plcomconstag = NULL;
2189
2190 cn_tab = NULL;
2191 }
2192
2193 int
2194 plcomcngetc(dev_t dev)
2195 {
2196 return plcom_common_getc(dev, plcomconstag, plcomconsioh);
2197 }
2198
2199 /*
2200 * Console kernel output character routine.
2201 */
2202 void
2203 plcomcnputc(dev_t dev, int c)
2204 {
2205 plcom_common_putc(dev, plcomconstag, plcomconsioh, c);
2206 }
2207
2208 void
2209 plcomcnpollc(dev_t dev, int on)
2210 {
2211
2212 }
2213
2214 #ifdef KGDB
2215 int
2216 plcom_kgdb_attach(bus_space_tag_t iot, bus_addr_t iobase, int rate,
2217 int frequency, tcflag_t cflag, int unit)
2218 {
2219 int res;
2220
2221 if (iot == plcomconstag && iobase == plcomconsunit)
2222 return EBUSY; /* cannot share with console */
2223
2224 res = plcominit(iot, iobase, rate, frequency, cflag, &plcom_kgdb_ioh);
2225 if (res)
2226 return res;
2227
2228 kgdb_attach(plcom_kgdb_getc, plcom_kgdb_putc, NULL);
2229 kgdb_dev = 123; /* unneeded, only to satisfy some tests */
2230
2231 plcom_kgdb_iot = iot;
2232 plcom_kgdb_unit = unit;
2233
2234 return 0;
2235 }
2236
2237 /* ARGSUSED */
2238 int
2239 plcom_kgdb_getc(void *arg)
2240 {
2241 return plcom_common_getc(NODEV, plcom_kgdb_iot, plcom_kgdb_ioh);
2242 }
2243
2244 /* ARGSUSED */
2245 void
2246 plcom_kgdb_putc(void *arg, int c)
2247 {
2248 plcom_common_putc(NODEV, plcom_kgdb_iot, plcom_kgdb_ioh, c);
2249 }
2250 #endif /* KGDB */
2251
2252 /* helper function to identify the plcom ports used by
2253 console or KGDB (and not yet autoconf attached) */
2254 int
2255 plcom_is_console(bus_space_tag_t iot, int unit,
2256 bus_space_handle_t *ioh)
2257 {
2258 bus_space_handle_t help;
2259
2260 if (!plcomconsattached &&
2261 iot == plcomconstag && unit == plcomconsunit)
2262 help = plcomconsioh;
2263 #ifdef KGDB
2264 else if (!plcom_kgdb_attached &&
2265 iot == plcom_kgdb_iot && unit == plcom_kgdb_unit)
2266 help = plcom_kgdb_ioh;
2267 #endif
2268 else
2269 return 0;
2270
2271 if (ioh)
2272 *ioh = help;
2273 return 1;
2274 }
2275