1 /* $NetBSD: ucom.c,v 1.40 2001/11/13 06:24:54 lukem Exp $ */
4 * Copyright (c) 2001-2003, 2005, 2008
5 * Shunsuke Akiyama <akiyama@jp.FreeBSD.org>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
32 * All rights reserved.
34 * This code is derived from software contributed to The NetBSD Foundation
35 * by Lennart Augustsson (lennart@augustsson.net) at
36 * Carlstedt Research & Technology.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the NetBSD
49 * Foundation, Inc. and its contributors.
50 * 4. Neither the name of The NetBSD Foundation nor the names of its
51 * contributors may be used to endorse or promote products derived
52 * from this software without specific prior written permission.
54 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
55 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
69 * This is a Frankenstein of FreeBSD's usb4bsd ucom and Dragonfly's old ucom
70 * module. There might be bugs lurking everywhere still
72 * In particular serial console on ucom is completely untested and likely broken
73 * as well as anyting that requires the modem control lines.
76 #include <sys/stdint.h>
77 #include <sys/param.h>
78 #include <sys/queue.h>
79 #include <sys/types.h>
80 #include <sys/systm.h>
81 #include <sys/kernel.h>
83 #include <sys/module.h>
85 #include <sys/condvar.h>
86 #include <sys/sysctl.h>
87 #include <sys/unistd.h>
88 #include <sys/callout.h>
89 #include <sys/malloc.h>
92 #include <sys/serial.h>
93 #include <sys/thread2.h>
96 #include <bus/u4b/usb.h>
97 #include <bus/u4b/usbdi.h>
98 #include <bus/u4b/usbdi_util.h>
100 #define USB_DEBUG_VAR ucom_debug
101 #include <bus/u4b/usb_debug.h>
102 #include <bus/u4b/usb_busdma.h>
103 #include <bus/u4b/usb_process.h>
105 #include <bus/u4b/serial/usb_serial.h>
107 /* #include "opt_gdb.h" */
109 static SYSCTL_NODE(_hw_usb, OID_AUTO, ucom, CTLFLAG_RW, 0, "USB ucom");
111 static int ucom_pps_mode;
113 SYSCTL_INT(_hw_usb_ucom, OID_AUTO, pps_mode, CTLFLAG_RW,
114 &ucom_pps_mode, 0, "pulse capturing mode - 0/1/2 - disabled/CTS/DCD");
115 TUNABLE_INT("hw.usb.ucom.pss_mode", &ucom_pps_mode);
119 static int ucom_debug = 0;
121 SYSCTL_INT(_hw_usb_ucom, OID_AUTO, debug, CTLFLAG_RW,
122 &ucom_debug, 0, "ucom debug level");
125 #define UCOM_CONS_BUFSIZE 1024
127 static uint8_t ucom_cons_rx_buf[UCOM_CONS_BUFSIZE];
128 static uint8_t ucom_cons_tx_buf[UCOM_CONS_BUFSIZE];
130 static unsigned int ucom_cons_rx_low = 0;
131 static unsigned int ucom_cons_rx_high = 0;
133 static unsigned int ucom_cons_tx_low = 0;
134 static unsigned int ucom_cons_tx_high = 0;
136 static int ucom_cons_unit = -1;
137 static int ucom_cons_subunit = 0;
138 static int ucom_cons_baud = 9600;
139 static struct ucom_softc *ucom_cons_softc = NULL;
141 TUNABLE_INT("hw.usb.ucom.cons_unit", &ucom_cons_unit);
142 SYSCTL_INT(_hw_usb_ucom, OID_AUTO, cons_unit, CTLFLAG_RW,
143 &ucom_cons_unit, 0, "console unit number");
144 TUNABLE_INT("hw.usb.ucom.cons_subunit", &ucom_cons_subunit);
145 SYSCTL_INT(_hw_usb_ucom, OID_AUTO, cons_subunit, CTLFLAG_RW,
146 &ucom_cons_subunit, 0, "console subunit number");
147 TUNABLE_INT("hw.usb.ucom.cons_baud", &ucom_cons_baud);
148 SYSCTL_INT(_hw_usb_ucom, OID_AUTO, cons_baud, CTLFLAG_RW,
149 &ucom_cons_baud, 0, "console baud rate");
151 static usb_proc_callback_t ucom_cfg_start_transfers;
152 static usb_proc_callback_t ucom_cfg_open;
153 static usb_proc_callback_t ucom_cfg_close;
154 static usb_proc_callback_t ucom_cfg_line_state;
155 static usb_proc_callback_t ucom_cfg_status_change;
156 static usb_proc_callback_t ucom_cfg_param;
158 static int ucom_unit_alloc(void);
159 static void ucom_unit_free(int);
160 static int ucom_attach_tty(struct ucom_super_softc *, struct ucom_softc *);
161 static void ucom_detach_tty(struct ucom_super_softc *, struct ucom_softc *);
162 static void ucom_queue_command(struct ucom_softc *,
163 usb_proc_callback_t *, struct termios *pt,
164 struct usb_proc_msg *t0, struct usb_proc_msg *t1);
165 static void ucom_shutdown(struct ucom_softc *);
166 static void ucom_ring(struct ucom_softc *, uint8_t);
167 static void ucom_break(struct ucom_softc *, uint8_t);
168 static void ucom_dtr(struct ucom_softc *, uint8_t);
169 static void ucom_rts(struct ucom_softc *, uint8_t);
171 static int ucom_open(struct ucom_softc *sc);
172 static int ucom_close(struct ucom_softc *sc);
173 static void ucom_start(struct tty *tp);
174 static void ucom_stop(struct tty *tp, int);
175 static int ucom_param(struct tty *tp, struct termios *t);
176 static int ucom_modem(struct tty *tp, int sigon, int sigoff);
178 static int ucom_fromtio(int);
179 static int ucom_totio(int);
181 static void disc_optim(struct tty *, struct termios *, struct ucom_softc *);
183 static d_open_t ucom_dev_open;
184 static d_close_t ucom_dev_close;
185 static d_read_t ucom_dev_read;
186 static d_write_t ucom_dev_write;
187 static d_ioctl_t ucom_dev_ioctl;
189 static struct dev_ops ucom_ops = {
190 { "ucom", 0, D_MPSAFE | D_TTY },
191 .d_open = ucom_dev_open,
192 .d_close = ucom_dev_close,
193 .d_read = ucom_dev_read,
194 .d_write = ucom_dev_write,
195 .d_ioctl = ucom_dev_ioctl,
196 .d_kqfilter = ttykqfilter,
197 .d_revoke = ttyrevoke
200 static moduledata_t ucom_mod = {
206 DECLARE_MODULE(ucom, ucom_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
207 MODULE_DEPEND(ucom, usb, 1, 1, 1);
208 MODULE_VERSION(ucom, UCOM_MODVER);
211 #define tty_gone(tp) ((tp->t_state) & (TS_ZOMBIE))
213 #define UCOM_UNIT_MAX 128 /* maximum number of units */
214 #define UCOM_TTY_PREFIX "ucom"
217 #define CALLOUT_MASK 0x80
218 #define CONTROL_MASK 0x60
219 #define CONTROL_INIT_STATE 0x20
220 #define CONTROL_LOCK_STATE 0x40
222 static struct unrhdr *ucom_unrhdr;
223 static struct lock ucom_lock;
224 static int ucom_close_refs;
230 ucom_unrhdr = new_unrhdr(0, UCOM_UNIT_MAX - 1, NULL);
231 lockinit(&ucom_lock, "UCOM LOCK", 0, 0);
233 SYSINIT(ucom_init, SI_BOOT2_KLD - 1, SI_ORDER_ANY, ucom_init, NULL);
236 ucom_uninit(void *arg)
247 lockuninit(&ucom_lock);
249 SYSUNINIT(ucom_uninit, SI_BOOT2_KLD - 2, SI_ORDER_ANY, ucom_uninit, NULL);
252 * Mark a unit number (the X in cuaUX) as in use.
254 * Note that devices using a different naming scheme (see ucom_tty_name()
255 * callback) still use this unit allocation.
258 ucom_unit_alloc(void)
263 if (ucom_unrhdr == NULL) {
264 DPRINTF("ucom_unrhdr is NULL\n");
267 unit = alloc_unr(ucom_unrhdr);
268 DPRINTF("unit %d is allocated\n", unit);
273 * Mark the unit number as not in use.
276 ucom_unit_free(int unit)
279 if (unit < 0 || unit >= UCOM_UNIT_MAX || ucom_unrhdr == NULL) {
280 DPRINTF("cannot free unit number\n");
283 DPRINTF("unit %d is freed\n", unit);
284 free_unr(ucom_unrhdr, unit);
288 * Setup a group of one or more serial ports.
290 * The lock pointed to by "lock" is applied before all
291 * callbacks are called back. Also "lock" must be applied
292 * before calling into the ucom-layer!
295 ucom_attach(struct ucom_super_softc *ssc, struct ucom_softc *sc,
296 int subunits, void *parent,
297 const struct ucom_callback *callback, struct lock *lock)
304 (callback == NULL) ||
309 /* XXX Do we want our own lock here maybe */
312 /* allocate a uniq unit number */
313 ssc->sc_unit = ucom_unit_alloc();
314 if (ssc->sc_unit == -1)
317 /* generate TTY name string */
318 ksnprintf(ssc->sc_ttyname, sizeof(ssc->sc_ttyname),
319 UCOM_TTY_PREFIX "%d", ssc->sc_unit);
321 /* create USB request handling process */
322 error = usb_proc_create(&ssc->sc_tq, lock, "ucom", USB_PRI_MED);
324 ucom_unit_free(ssc->sc_unit);
327 ssc->sc_subunits = subunits;
328 ssc->sc_flag = UCOM_FLAG_ATTACHED |
331 if (callback->ucom_free == NULL)
332 ssc->sc_flag |= UCOM_FLAG_WAIT_REFS;
334 /* increment reference count */
337 for (subunit = 0; subunit < ssc->sc_subunits; subunit++) {
338 sc[subunit].sc_subunit = subunit;
339 sc[subunit].sc_super = ssc;
340 sc[subunit].sc_lock = lock;
341 sc[subunit].sc_parent = parent;
342 sc[subunit].sc_callback = callback;
344 error = ucom_attach_tty(ssc, &sc[subunit]);
346 ucom_detach(ssc, &sc[0]);
349 /* increment reference count */
352 /* set subunit attached */
353 sc[subunit].sc_flag |= UCOM_FLAG_ATTACHED;
356 DPRINTF("tp = %p, unit = %d, subunits = %d\n",
357 sc->sc_tty, ssc->sc_unit, ssc->sc_subunits);
363 * The following function will do nothing if the structure pointed to
364 * by "ssc" and "sc" is zero or has already been detached.
367 ucom_detach(struct ucom_super_softc *ssc, struct ucom_softc *sc)
371 if (!(ssc->sc_flag & UCOM_FLAG_ATTACHED))
372 return; /* not initialized */
374 destroy_dev(sc->sc_cdev);
375 destroy_dev(sc->sc_cdev_init);
376 destroy_dev(sc->sc_cdev_lock);
377 destroy_dev(sc->sc_cdev2);
378 destroy_dev(sc->sc_cdev2_init);
379 destroy_dev(sc->sc_cdev2_lock);
382 lwkt_gettoken(&sc->sc_tty->t_token);
384 if (ssc->sc_sysctl_ttyname != NULL) {
385 sysctl_remove_oid(ssc->sc_sysctl_ttyname, 1, 0);
386 ssc->sc_sysctl_ttyname = NULL;
389 if (ssc->sc_sysctl_ttyports != NULL) {
390 sysctl_remove_oid(ssc->sc_sysctl_ttyports, 1, 0);
391 ssc->sc_sysctl_ttyports = NULL;
394 usb_proc_drain(&ssc->sc_tq);
396 for (subunit = 0; subunit < ssc->sc_subunits; subunit++) {
397 if (sc[subunit].sc_flag & UCOM_FLAG_ATTACHED) {
399 ucom_detach_tty(ssc, &sc[subunit]);
401 /* avoid duplicate detach */
402 sc[subunit].sc_flag &= ~UCOM_FLAG_ATTACHED;
405 usb_proc_free(&ssc->sc_tq);
409 if (ssc->sc_flag & UCOM_FLAG_WAIT_REFS)
412 /* make sure we don't detach twice */
413 ssc->sc_flag &= ~UCOM_FLAG_ATTACHED;
416 lwkt_reltoken(&sc->sc_tty->t_token);
420 ucom_drain(struct ucom_super_softc *ssc)
422 lockmgr(&ucom_lock, LK_EXCLUSIVE);
423 while (ssc->sc_refs > 0) {
424 kprintf("ucom: Waiting for a TTY device to close.\n");
425 usb_pause_mtx(&ucom_lock, hz);
427 lockmgr(&ucom_lock, LK_RELEASE);
431 ucom_drain_all(void *arg)
433 lockmgr(&ucom_lock, LK_EXCLUSIVE);
434 while (ucom_close_refs > 0) {
435 kprintf("ucom: Waiting for all detached TTY "
436 "devices to have open fds closed.\n");
437 usb_pause_mtx(&ucom_lock, hz);
439 lockmgr(&ucom_lock, LK_RELEASE);
443 ucom_attach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc)
446 char buf[32]; /* temporary TTY device name buffer */
448 tp = ttymalloc(&sc->sc_tty);
450 lwkt_gettoken(&tp->t_token);
452 tp->t_sc = (void *)sc;
454 tp->t_oproc = ucom_start;
455 tp->t_param = ucom_param;
456 tp->t_stop = ucom_stop;
458 /* Check if the client has a custom TTY name */
460 if (sc->sc_callback->ucom_tty_name) {
461 sc->sc_callback->ucom_tty_name(sc, buf,
462 sizeof(buf), ssc->sc_unit, sc->sc_subunit);
465 /* Use default TTY name */
466 if (ssc->sc_subunits > 1) {
467 /* multiple modems in one */
468 ksnprintf(buf, sizeof(buf), "%u.%u",
469 ssc->sc_unit, sc->sc_subunit);
472 ksnprintf(buf, sizeof(buf), "%u",
477 sc->sc_cdev = make_dev(&ucom_ops, ssc->sc_unit,
478 UID_ROOT, GID_WHEEL, 0600, "ttyU%s", buf);
479 sc->sc_cdev_init = make_dev(&ucom_ops, ssc->sc_unit | CONTROL_INIT_STATE,
480 UID_ROOT, GID_WHEEL, 0600, "ttyiU%s", buf);
481 sc->sc_cdev_lock = make_dev(&ucom_ops, ssc->sc_unit | CONTROL_LOCK_STATE,
482 UID_ROOT, GID_WHEEL, 0600, "ttylU%s", buf);
483 sc->sc_cdev2 = make_dev(&ucom_ops, ssc->sc_unit | CALLOUT_MASK,
484 UID_UUCP, GID_DIALER, 0660, "cuaU%s", buf);
485 sc->sc_cdev2_init = make_dev(&ucom_ops, ssc->sc_unit | CALLOUT_MASK | CONTROL_INIT_STATE,
486 UID_UUCP, GID_DIALER, 0660, "cuaiU%s", buf);
487 sc->sc_cdev2_lock = make_dev(&ucom_ops, ssc->sc_unit | CALLOUT_MASK | CONTROL_LOCK_STATE,
488 UID_UUCP, GID_DIALER, 0660, "cualU%s", buf);
490 sc->sc_cdev->si_tty = tp;
491 sc->sc_cdev_init->si_tty = tp;
492 sc->sc_cdev_lock->si_tty = tp;
494 sc->sc_cdev->si_drv1 = sc;
495 sc->sc_cdev_init->si_drv1 = sc;
496 sc->sc_cdev_lock->si_drv1 = sc;
498 sc->sc_cdev2->si_tty = tp;
499 sc->sc_cdev2_init->si_tty = tp;
500 sc->sc_cdev2_lock->si_tty = tp;
502 sc->sc_cdev2->si_drv1 = sc;
503 sc->sc_cdev2_init->si_drv1 = sc;
504 sc->sc_cdev2_lock->si_drv1 = sc;
508 DPRINTF("ttycreate: %s\n", buf);
510 /* Check if this device should be a console */
511 if ((ucom_cons_softc == NULL) &&
512 (ssc->sc_unit == ucom_cons_unit) &&
513 (sc->sc_subunit == ucom_cons_subunit)) {
515 DPRINTF("unit %d subunit %d is console",
516 ssc->sc_unit, sc->sc_subunit);
518 ucom_cons_softc = sc;
521 tty_init_console(tp, ucom_cons_baud);
523 tp->t_termios.c_ispeed = ucom_cons_baud;
524 tp->t_termios.c_ospeed = ucom_cons_baud;
526 UCOM_MTX_LOCK(ucom_cons_softc);
527 ucom_cons_rx_low = 0;
528 ucom_cons_rx_high = 0;
529 ucom_cons_tx_low = 0;
530 ucom_cons_tx_high = 0;
531 sc->sc_flag |= UCOM_FLAG_CONSOLE;
532 ucom_open(ucom_cons_softc);
533 ucom_param(tp, &tp->t_termios);
534 UCOM_MTX_UNLOCK(ucom_cons_softc);
537 lwkt_reltoken(&tp->t_token);
543 ucom_detach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc)
545 struct tty *tp = sc->sc_tty;
547 DPRINTF("sc = %p, tp = %p\n", sc, sc->sc_tty);
549 if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
550 UCOM_MTX_LOCK(ucom_cons_softc);
551 ucom_close(ucom_cons_softc);
552 sc->sc_flag &= ~UCOM_FLAG_CONSOLE;
553 UCOM_MTX_UNLOCK(ucom_cons_softc);
554 ucom_cons_softc = NULL;
557 /* the config thread has been stopped when we get here */
560 sc->sc_flag |= UCOM_FLAG_GONE;
561 sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_LL_READY);
565 lwkt_gettoken(&tp->t_token);
569 if (tp->t_state & TS_ISOPEN) {
570 kprintf("device still open, forcing close\n");
571 (*linesw[tp->t_line].l_close)(tp, 0);
574 ucom_close(sc); /* close, if any */
577 * make sure that read and write transfers are stopped
579 if (sc->sc_callback->ucom_stop_read) {
580 (sc->sc_callback->ucom_stop_read) (sc);
582 if (sc->sc_callback->ucom_stop_write) {
583 (sc->sc_callback->ucom_stop_write) (sc);
586 lwkt_reltoken(&tp->t_token);
591 dev_ops_remove_minor(&ucom_ops,ssc->sc_unit);
597 ucom_set_pnpinfo_usb(struct ucom_super_softc *ssc, device_t dev)
601 struct usb_attach_arg *uaa;
603 ksnprintf(buf, sizeof(buf), "ttyname=" UCOM_TTY_PREFIX
604 "%d ttyports=%d", ssc->sc_unit, ssc->sc_subunits);
606 /* Store the PNP info in the first interface for the device */
607 uaa = device_get_ivars(dev);
608 iface_index = uaa->info.bIfaceIndex;
610 if (usbd_set_pnpinfo(uaa->device, iface_index, buf) != 0)
611 device_printf(dev, "Could not set PNP info\n");
614 * The following information is also replicated in the PNP-info
615 * string which is registered above:
617 if (ssc->sc_sysctl_ttyname == NULL) {
619 ssc->sc_sysctl_ttyname = SYSCTL_ADD_STRING(NULL,
620 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
621 OID_AUTO, "ttyname", CTLFLAG_RD, ssc->sc_ttyname, 0,
622 "TTY device basename");
625 if (ssc->sc_sysctl_ttyports == NULL) {
627 ssc->sc_sysctl_ttyports = SYSCTL_ADD_INT(NULL,
628 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
629 OID_AUTO, "ttyports", CTLFLAG_RD,
630 NULL, ssc->sc_subunits, "Number of ports");
636 ucom_queue_command(struct ucom_softc *sc,
637 usb_proc_callback_t *fn, struct termios *pt,
638 struct usb_proc_msg *t0, struct usb_proc_msg *t1)
640 struct ucom_super_softc *ssc = sc->sc_super;
641 struct ucom_param_task *task;
643 UCOM_MTX_ASSERT(sc, MA_OWNED);
645 if (usb_proc_is_gone(&ssc->sc_tq)) {
646 DPRINTF("proc is gone\n");
647 return; /* nothing to do */
650 * NOTE: The task cannot get executed before we drop the
651 * "sc_lock" lock. It is safe to update fields in the message
652 * structure after that the message got queued.
654 task = (struct ucom_param_task *)
655 usb_proc_msignal(&ssc->sc_tq, t0, t1);
657 /* Setup callback and softc pointers */
658 task->hdr.pm_callback = fn;
662 * Make a copy of the termios. This field is only present if
663 * the "pt" field is not NULL.
666 task->termios_copy = *pt;
669 * Closing the device should be synchronous.
671 if (fn == ucom_cfg_close)
672 usb_proc_mwait(&ssc->sc_tq, t0, t1);
675 * In case of multiple configure requests,
676 * keep track of the last one!
678 if (fn == ucom_cfg_start_transfers)
679 sc->sc_last_start_xfer = &task->hdr;
683 ucom_shutdown(struct ucom_softc *sc)
685 struct tty *tp = sc->sc_tty;
687 UCOM_MTX_ASSERT(sc, MA_OWNED);
692 * Hang up if necessary:
694 if (tp->t_termios.c_cflag & HUPCL) {
695 ucom_modem(tp, 0, SER_DTR);
702 * else: taskqueue is draining or gone
705 ucom_cfg_is_gone(struct ucom_softc *sc)
707 struct ucom_super_softc *ssc = sc->sc_super;
709 return (usb_proc_is_gone(&ssc->sc_tq));
713 ucom_cfg_start_transfers(struct usb_proc_msg *_task)
715 struct ucom_cfg_task *task =
716 (struct ucom_cfg_task *)_task;
717 struct ucom_softc *sc = task->sc;
719 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
722 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
723 /* TTY device closed */
727 if (_task == sc->sc_last_start_xfer)
728 sc->sc_flag |= UCOM_FLAG_GP_DATA;
730 if (sc->sc_callback->ucom_start_read) {
731 (sc->sc_callback->ucom_start_read) (sc);
733 if (sc->sc_callback->ucom_start_write) {
734 (sc->sc_callback->ucom_start_write) (sc);
739 ucom_start_transfers(struct ucom_softc *sc)
741 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
745 * Make sure that data transfers are started in both
748 if (sc->sc_callback->ucom_start_read) {
749 (sc->sc_callback->ucom_start_read) (sc);
751 if (sc->sc_callback->ucom_start_write) {
752 (sc->sc_callback->ucom_start_write) (sc);
757 ucom_cfg_open(struct usb_proc_msg *_task)
759 struct ucom_cfg_task *task =
760 (struct ucom_cfg_task *)_task;
761 struct ucom_softc *sc = task->sc;
765 if (sc->sc_flag & UCOM_FLAG_LL_READY) {
771 sc->sc_flag |= UCOM_FLAG_LL_READY;
773 if (sc->sc_callback->ucom_cfg_open) {
774 (sc->sc_callback->ucom_cfg_open) (sc);
777 usb_pause_mtx(sc->sc_lock, hz / 10);
783 ucom_dev_open(struct dev_open_args *ap)
785 cdev_t dev = ap->a_head.a_dev;
786 struct ucom_softc *sc = (struct ucom_softc *)dev->si_drv1;
794 error = ucom_open(sc);
801 ucom_open(struct ucom_softc *sc)
808 mynor = minor(sc->sc_cdev);
810 if (sc->sc_flag & UCOM_FLAG_GONE) {
813 if (sc->sc_flag & UCOM_FLAG_HL_READY) {
817 DPRINTF("tp = %p\n", sc->sc_tty);
819 if (sc->sc_callback->ucom_pre_open) {
821 * give the lower layer a chance to disallow TTY open, for
822 * example if the device is not present:
824 error = (sc->sc_callback->ucom_pre_open) (sc);
829 sc->sc_flag |= UCOM_FLAG_HL_READY;
832 lwkt_gettoken(&tp->t_token);
834 if (!ISSET(tp->t_state, TS_ISOPEN)) {
837 tp->t_dev = reference_dev(sc->sc_cdev);
839 t = mynor & CALLOUT_MASK ? sc->sc_it_out : sc->sc_it_in;
843 tp->t_iflag = TTYDEF_IFLAG;
844 tp->t_oflag = TTYDEF_OFLAG;
845 tp->t_lflag = TTYDEF_LFLAG;
849 /* Disable transfers */
850 sc->sc_flag &= ~UCOM_FLAG_GP_DATA;
856 /* reset programmed line state */
861 /* reset jitter buffer */
862 sc->sc_jitterbuf_in = 0;
863 sc->sc_jitterbuf_out = 0;
865 ucom_queue_command(sc, ucom_cfg_open, NULL,
866 &sc->sc_open_task[0].hdr,
867 &sc->sc_open_task[1].hdr);
869 /* Queue transfer enable command last */
870 ucom_queue_command(sc, ucom_cfg_start_transfers, NULL,
871 &sc->sc_start_task[0].hdr,
872 &sc->sc_start_task[1].hdr);
874 ucom_modem(sc->sc_tty, SER_DTR | SER_RTS, 0);
880 ucom_status_change(sc);
882 if (ISSET(sc->sc_msr, SER_DCD)) {
883 (*linesw[tp->t_line].l_modem)(tp, 1);
887 error = ttyopen(sc->sc_cdev, tp);
889 lwkt_reltoken(&tp->t_token);
893 error = (*linesw[tp->t_line].l_open)(sc->sc_cdev, tp);
895 lwkt_reltoken(&tp->t_token);
899 disc_optim(tp, &tp->t_termios, sc);
901 lwkt_reltoken(&tp->t_token);
907 ucom_cfg_close(struct usb_proc_msg *_task)
909 struct ucom_cfg_task *task =
910 (struct ucom_cfg_task *)_task;
911 struct ucom_softc *sc = task->sc;
915 if (sc->sc_flag & UCOM_FLAG_LL_READY) {
916 sc->sc_flag &= ~UCOM_FLAG_LL_READY;
917 if (sc->sc_callback->ucom_cfg_close)
918 (sc->sc_callback->ucom_cfg_close) (sc);
925 ucom_dev_close(struct dev_close_args *ap)
927 cdev_t dev = ap->a_head.a_dev;
928 struct ucom_softc *sc = (struct ucom_softc *)dev->si_drv1;
932 error = ucom_close(sc);
939 ucom_close(struct ucom_softc *sc)
941 struct tty *tp = sc->sc_tty;
944 DPRINTF("tp=%p\n", tp);
946 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
947 DPRINTF("tp=%p already closed\n", tp);
950 if (!ISSET(tp->t_state, TS_ISOPEN)) {
955 ucom_queue_command(sc, ucom_cfg_close, NULL,
956 &sc->sc_close_task[0].hdr,
957 &sc->sc_close_task[1].hdr);
959 sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_RTS_IFLOW);
961 if (sc->sc_callback->ucom_stop_read) {
962 (sc->sc_callback->ucom_stop_read) (sc);
965 lwkt_gettoken(&tp->t_token);
966 (*linesw[tp->t_line].l_close)(tp, 0); /* XXX: flags */
967 disc_optim(tp, &tp->t_termios, sc);
971 release_dev(tp->t_dev);
974 /* XXX: Detach wakeup */
975 lwkt_reltoken(&tp->t_token);
982 ucom_inwakeup(struct tty *tp)
984 struct ucom_softc *sc = tty_softc(tp);
990 UCOM_MTX_ASSERT(sc, MA_OWNED);
992 DPRINTF("tp=%p\n", tp);
994 if (ttydisc_can_bypass(tp) != 0 ||
995 (sc->sc_flag & UCOM_FLAG_HL_READY) == 0 ||
996 (sc->sc_flag & UCOM_FLAG_INWAKEUP) != 0) {
1000 /* prevent recursion */
1001 sc->sc_flag |= UCOM_FLAG_INWAKEUP;
1003 pos = sc->sc_jitterbuf_out;
1005 while (sc->sc_jitterbuf_in != pos) {
1008 c = (char)sc->sc_jitterbuf[pos];
1010 if (ttydisc_rint(tp, c, 0) == -1)
1013 if (pos >= UCOM_JITTERBUF_SIZE)
1014 pos -= UCOM_JITTERBUF_SIZE;
1017 sc->sc_jitterbuf_out = pos;
1019 /* clear RTS in async fashion */
1020 if ((sc->sc_jitterbuf_in == pos) &&
1021 (sc->sc_flag & UCOM_FLAG_RTS_IFLOW))
1024 sc->sc_flag &= ~UCOM_FLAG_INWAKEUP;
1029 ucom_dev_read(struct dev_read_args *ap)
1031 cdev_t dev = ap->a_head.a_dev;
1032 struct ucom_softc *sc;
1039 lwkt_gettoken(&tp->t_token);
1044 DPRINTF("tp = %p, flag = 0x%x\n", tp, ap->a_ioflag);
1046 /* must not be locked in case it blocks */
1047 /*UCOM_MTX_LOCK(sc);*/
1048 error = (*linesw[tp->t_line].l_read)(tp, ap->a_uio, ap->a_ioflag);
1049 /*UCOM_MTX_UNLOCK(sc);*/
1051 lwkt_reltoken(&tp->t_token);
1052 DPRINTF("error = %d\n", error);
1058 ucom_dev_write(struct dev_write_args *ap)
1060 cdev_t dev = ap->a_head.a_dev;
1061 struct ucom_softc *sc;
1066 lwkt_gettoken(&tp->t_token);
1071 DPRINTF("tp = %p, flag = 0x%x\n", tp, ap->a_ioflag);
1073 /* must not be locked in case it blocks */
1074 /*UCOM_MTX_LOCK(sc);*/
1075 error = (*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag);
1076 /*UCOM_MTX_UNLOCK(sc);*/
1078 lwkt_reltoken(&tp->t_token);
1079 DPRINTF("ucomwrite: error = %d\n", error);
1085 ucom_dev_ioctl(struct dev_ioctl_args *ap)
1087 cdev_t dev = ap->a_head.a_dev;
1088 struct ucom_softc *sc = (struct ucom_softc *)dev->si_drv1;
1089 u_long cmd = ap->a_cmd;
1090 caddr_t data = ap->a_data;
1091 struct tty *tp = sc->sc_tty;
1097 lwkt_gettoken(&tp->t_token);
1101 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
1102 lwkt_reltoken(&tp->t_token);
1103 UCOM_MTX_UNLOCK(sc);
1106 DPRINTF("cmd = 0x%08lx\n", cmd);
1107 if (mynor & CONTROL_MASK) {
1110 switch (mynor & CONTROL_MASK) {
1111 case CONTROL_INIT_STATE:
1112 ct = mynor & CALLOUT_MASK ? &sc->sc_it_out : &sc->sc_it_in;
1114 case CONTROL_LOCK_STATE:
1115 ct = mynor & CALLOUT_MASK ? &sc->sc_lt_out : &sc->sc_lt_in;
1118 lwkt_reltoken(&tp->t_token);
1119 UCOM_MTX_UNLOCK(sc);
1120 return (ENODEV); /* /dev/nodev */
1122 switch (ap->a_cmd) {
1124 error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
1126 lwkt_reltoken(&tp->t_token);
1127 UCOM_MTX_UNLOCK(sc);
1130 *ct = *(struct termios *)data;
1131 lwkt_reltoken(&tp->t_token);
1132 UCOM_MTX_UNLOCK(sc);
1135 *(struct termios *)data = *ct;
1136 lwkt_reltoken(&tp->t_token);
1137 UCOM_MTX_UNLOCK(sc);
1140 *(int *)data = TTYDISC;
1141 lwkt_reltoken(&tp->t_token);
1142 UCOM_MTX_UNLOCK(sc);
1145 bzero(data, sizeof(struct winsize));
1146 lwkt_reltoken(&tp->t_token);
1147 UCOM_MTX_UNLOCK(sc);
1150 lwkt_reltoken(&tp->t_token);
1151 UCOM_MTX_UNLOCK(sc);
1156 error = (*linesw[tp->t_line].l_ioctl)(tp, ap->a_cmd, ap->a_data,
1157 ap->a_fflag, ap->a_cred);
1159 if (error != ENOIOCTL) {
1160 DPRINTF("ucomioctl: l_ioctl: error = %d\n", error);
1161 lwkt_reltoken(&tp->t_token);
1162 UCOM_MTX_UNLOCK(sc);
1166 error = ttioctl(tp, ap->a_cmd, ap->a_data, ap->a_fflag);
1167 disc_optim(tp, &tp->t_termios, sc);
1168 if (error != ENOIOCTL) {
1169 DPRINTF("ucomioctl: ttioctl: error = %d\n", error);
1170 lwkt_reltoken(&tp->t_token);
1171 UCOM_MTX_UNLOCK(sc);
1204 d = *(int *)ap->a_data;
1205 DPRINTF("ucomioctl: TIOCMSET, 0x%x\n", d);
1206 ucom_modem(tp, ucom_fromtio(d), 0);
1209 d = ucom_modem(tp, 0, 0);
1210 DPRINTF("ucomioctl: TIOCMGET, 0x%x\n", d);
1211 *(int *)ap->a_data = ucom_totio(d);
1212 ucom_status_change(sc);
1215 d = *(int *)ap->a_data;
1216 ucom_modem(tp, ucom_fromtio(d), 0);
1219 d = *(int *)ap->a_data;
1220 ucom_modem(tp, 0, ucom_fromtio(d));
1223 if (sc->sc_callback->ucom_ioctl) {
1224 error = (sc->sc_callback->ucom_ioctl)
1225 (sc, cmd, data, 0, curthread);
1227 lwkt_reltoken(&tp->t_token);
1228 UCOM_MTX_UNLOCK(sc);
1235 if (error == ENOIOCTL)
1236 error = pps_ioctl(cmd, data, &sc->sc_pps);
1239 lwkt_reltoken(&tp->t_token);
1240 UCOM_MTX_UNLOCK(sc);
1246 ucom_totio(int bits)
1250 SET(bits, TIOCM_LE);
1252 if (ISSET(bits, SER_DTR)) {
1253 SET(rbits, TIOCM_DTR);
1255 if (ISSET(bits, SER_RTS)) {
1256 SET(rbits, TIOCM_RTS);
1258 if (ISSET(bits, SER_CTS)) {
1259 SET(rbits, TIOCM_CTS);
1261 if (ISSET(bits, SER_DCD)) {
1262 SET(rbits, TIOCM_CD);
1264 if (ISSET(bits, SER_DSR)) {
1265 SET(rbits, TIOCM_DSR);
1267 if (ISSET(bits, SER_RI)) {
1268 SET(rbits, TIOCM_RI);
1275 ucom_fromtio(int bits)
1279 if (ISSET(bits, TIOCM_DTR)) {
1280 SET(rbits, SER_DTR);
1282 if (ISSET(bits, TIOCM_RTS)) {
1283 SET(rbits, SER_RTS);
1285 if (ISSET(bits, TIOCM_CTS)) {
1286 SET(rbits, SER_CTS);
1288 if (ISSET(bits, TIOCM_CD)) {
1289 SET(rbits, SER_DCD);
1291 if (ISSET(bits, TIOCM_DSR)) {
1292 SET(rbits, SER_DSR);
1294 if (ISSET(bits, TIOCM_RI)) {
1302 ucom_modem(struct tty *tp, int sigon, int sigoff)
1304 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc;
1307 UCOM_MTX_ASSERT(sc, MA_OWNED);
1309 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
1312 if ((sigon == 0) && (sigoff == 0)) {
1314 if (sc->sc_mcr & SER_DTR) {
1317 if (sc->sc_mcr & SER_RTS) {
1320 if (sc->sc_msr & SER_CTS) {
1323 if (sc->sc_msr & SER_DCD) {
1326 if (sc->sc_msr & SER_DSR) {
1329 if (sc->sc_msr & SER_RI) {
1334 if (sigon & SER_DTR) {
1335 sc->sc_mcr |= SER_DTR;
1337 if (sigoff & SER_DTR) {
1338 sc->sc_mcr &= ~SER_DTR;
1340 if (sigon & SER_RTS) {
1341 sc->sc_mcr |= SER_RTS;
1343 if (sigoff & SER_RTS) {
1344 sc->sc_mcr &= ~SER_RTS;
1346 onoff = (sc->sc_mcr & SER_DTR) ? 1 : 0;
1347 ucom_dtr(sc, onoff);
1349 onoff = (sc->sc_mcr & SER_RTS) ? 1 : 0;
1350 ucom_rts(sc, onoff);
1356 ucom_cfg_line_state(struct usb_proc_msg *_task)
1358 struct ucom_cfg_task *task =
1359 (struct ucom_cfg_task *)_task;
1360 struct ucom_softc *sc = task->sc;
1367 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
1372 /* compute callback mask */
1373 if (sc->sc_callback->ucom_cfg_set_dtr)
1374 mask |= UCOM_LS_DTR;
1375 if (sc->sc_callback->ucom_cfg_set_rts)
1376 mask |= UCOM_LS_RTS;
1377 if (sc->sc_callback->ucom_cfg_set_break)
1378 mask |= UCOM_LS_BREAK;
1379 if (sc->sc_callback->ucom_cfg_set_ring)
1380 mask |= UCOM_LS_RING;
1382 /* compute the bits we are to program */
1383 notch_bits = (sc->sc_pls_set & sc->sc_pls_clr) & mask;
1384 any_bits = (sc->sc_pls_set | sc->sc_pls_clr) & mask;
1385 prev_value = sc->sc_pls_curr ^ notch_bits;
1386 last_value = sc->sc_pls_curr;
1388 /* reset programmed line state */
1389 sc->sc_pls_curr = 0;
1393 /* ensure that we don't lose any levels */
1394 if (notch_bits & UCOM_LS_DTR)
1395 sc->sc_callback->ucom_cfg_set_dtr(sc,
1396 (prev_value & UCOM_LS_DTR) ? 1 : 0);
1397 if (notch_bits & UCOM_LS_RTS)
1398 sc->sc_callback->ucom_cfg_set_rts(sc,
1399 (prev_value & UCOM_LS_RTS) ? 1 : 0);
1400 if (notch_bits & UCOM_LS_BREAK)
1401 sc->sc_callback->ucom_cfg_set_break(sc,
1402 (prev_value & UCOM_LS_BREAK) ? 1 : 0);
1403 if (notch_bits & UCOM_LS_RING)
1404 sc->sc_callback->ucom_cfg_set_ring(sc,
1405 (prev_value & UCOM_LS_RING) ? 1 : 0);
1407 /* set last value */
1408 if (any_bits & UCOM_LS_DTR)
1409 sc->sc_callback->ucom_cfg_set_dtr(sc,
1410 (last_value & UCOM_LS_DTR) ? 1 : 0);
1411 if (any_bits & UCOM_LS_RTS)
1412 sc->sc_callback->ucom_cfg_set_rts(sc,
1413 (last_value & UCOM_LS_RTS) ? 1 : 0);
1414 if (any_bits & UCOM_LS_BREAK)
1415 sc->sc_callback->ucom_cfg_set_break(sc,
1416 (last_value & UCOM_LS_BREAK) ? 1 : 0);
1417 if (any_bits & UCOM_LS_RING)
1418 sc->sc_callback->ucom_cfg_set_ring(sc,
1419 (last_value & UCOM_LS_RING) ? 1 : 0);
1423 ucom_line_state(struct ucom_softc *sc,
1424 uint8_t set_bits, uint8_t clear_bits)
1426 UCOM_MTX_ASSERT(sc, MA_OWNED);
1428 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
1432 DPRINTF("on=0x%02x, off=0x%02x\n", set_bits, clear_bits);
1434 /* update current programmed line state */
1435 sc->sc_pls_curr |= set_bits;
1436 sc->sc_pls_curr &= ~clear_bits;
1437 sc->sc_pls_set |= set_bits;
1438 sc->sc_pls_clr |= clear_bits;
1440 /* defer driver programming */
1441 ucom_queue_command(sc, ucom_cfg_line_state, NULL,
1442 &sc->sc_line_state_task[0].hdr,
1443 &sc->sc_line_state_task[1].hdr);
1447 ucom_ring(struct ucom_softc *sc, uint8_t onoff)
1449 DPRINTF("onoff = %d\n", onoff);
1452 ucom_line_state(sc, UCOM_LS_RING, 0);
1454 ucom_line_state(sc, 0, UCOM_LS_RING);
1458 ucom_break(struct ucom_softc *sc, uint8_t onoff)
1460 DPRINTF("onoff = %d\n", onoff);
1463 ucom_line_state(sc, UCOM_LS_BREAK, 0);
1465 ucom_line_state(sc, 0, UCOM_LS_BREAK);
1469 ucom_dtr(struct ucom_softc *sc, uint8_t onoff)
1471 DPRINTF("onoff = %d\n", onoff);
1474 ucom_line_state(sc, UCOM_LS_DTR, 0);
1476 ucom_line_state(sc, 0, UCOM_LS_DTR);
1480 ucom_rts(struct ucom_softc *sc, uint8_t onoff)
1482 DPRINTF("onoff = %d\n", onoff);
1485 ucom_line_state(sc, UCOM_LS_RTS, 0);
1487 ucom_line_state(sc, 0, UCOM_LS_RTS);
1491 ucom_cfg_status_change(struct usb_proc_msg *_task)
1493 struct ucom_cfg_task *task =
1494 (struct ucom_cfg_task *)_task;
1495 struct ucom_softc *sc = task->sc;
1504 UCOM_MTX_ASSERT(sc, MA_OWNED);
1506 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
1509 if (sc->sc_callback->ucom_cfg_get_status == NULL) {
1517 (sc->sc_callback->ucom_cfg_get_status) (sc, &new_lsr, &new_msr);
1519 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
1520 /* TTY device closed */
1523 msr_delta = (sc->sc_msr ^ new_msr);
1524 lsr_delta = (sc->sc_lsr ^ new_lsr);
1526 sc->sc_msr = new_msr;
1527 sc->sc_lsr = new_lsr;
1529 #if 0 /* missing pps_capture */
1531 * Time pulse counting support. Note that both CTS and DCD are
1532 * active-low signals. The status bit is high to indicate that
1533 * the signal on the line is low, which corresponds to a PPS
1536 switch(ucom_pps_mode) {
1538 if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) &&
1539 (msr_delta & SER_CTS)) {
1540 pps_capture(&sc->sc_pps);
1541 pps_event(&sc->sc_pps, (sc->sc_msr & SER_CTS) ?
1542 PPS_CAPTURECLEAR : PPS_CAPTUREASSERT);
1546 if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) &&
1547 (msr_delta & SER_DCD)) {
1548 pps_capture(&sc->sc_pps);
1549 pps_event(&sc->sc_pps, (sc->sc_msr & SER_DCD) ?
1550 PPS_CAPTURECLEAR : PPS_CAPTUREASSERT);
1558 if (msr_delta & SER_DCD) {
1560 int onoff = (sc->sc_msr & SER_DCD) ? 1 : 0;
1562 DPRINTF("DCD changed to %d\n", onoff);
1564 (*linesw[tp->t_line].l_modem)(tp, onoff);
1567 if ((lsr_delta & ULSR_BI) && (sc->sc_lsr & ULSR_BI)) {
1569 DPRINTF("BREAK detected\n");
1570 (*linesw[tp->t_line].l_rint)(0, tp);
1573 ttydisc_rint(tp, 0, TRE_BREAK);
1574 ttydisc_rint_done(tp);
1578 if ((lsr_delta & ULSR_FE) && (sc->sc_lsr & ULSR_FE)) {
1580 DPRINTF("Frame error detected\n");
1581 (*linesw[tp->t_line].l_rint)(0, tp);
1584 ttydisc_rint(tp, 0, TRE_FRAMING);
1585 ttydisc_rint_done(tp);
1589 if ((lsr_delta & ULSR_PE) && (sc->sc_lsr & ULSR_PE)) {
1591 DPRINTF("Parity error detected\n");
1592 (*linesw[tp->t_line].l_rint)(0, tp);
1594 ttydisc_rint(tp, 0, TRE_PARITY);
1595 ttydisc_rint_done(tp);
1601 ucom_status_change(struct ucom_softc *sc)
1603 UCOM_MTX_ASSERT(sc, MA_OWNED);
1605 if (sc->sc_flag & UCOM_FLAG_CONSOLE)
1606 return; /* not supported */
1608 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
1613 ucom_queue_command(sc, ucom_cfg_status_change, NULL,
1614 &sc->sc_status_task[0].hdr,
1615 &sc->sc_status_task[1].hdr);
1619 ucom_cfg_param(struct usb_proc_msg *_task)
1621 struct ucom_param_task *task =
1622 (struct ucom_param_task *)_task;
1623 struct ucom_softc *sc = task->sc;
1625 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
1628 if (sc->sc_callback->ucom_cfg_param == NULL) {
1632 (sc->sc_callback->ucom_cfg_param) (sc, &task->termios_copy);
1635 usb_pause_mtx(sc->sc_lock, hz / 10);
1639 ucom_param(struct tty *tp, struct termios *t)
1641 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc;
1645 lwkt_gettoken(&tp->t_token);
1646 UCOM_MTX_ASSERT(sc, MA_OWNED);
1651 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
1653 /* XXX the TTY layer should call "open()" first! */
1655 * Not quite: Its ordering is partly backwards, but
1656 * some parameters must be set early in ttydev_open(),
1657 * possibly before calling ttydevsw_open().
1659 error = ucom_open(sc);
1666 DPRINTF("sc = %p\n", sc);
1668 /* Check requested parameters. */
1669 if (t->c_ispeed && (t->c_ispeed != t->c_ospeed)) {
1670 /* XXX c_ospeed == 0 is perfectly valid. */
1671 DPRINTF("mismatch ispeed and ospeed\n");
1675 t->c_ispeed = t->c_ospeed;
1677 if (sc->sc_callback->ucom_pre_param) {
1678 /* Let the lower layer verify the parameters */
1679 error = (sc->sc_callback->ucom_pre_param) (sc, t);
1681 DPRINTF("callback error = %d\n", error);
1686 /* Disable transfers */
1687 sc->sc_flag &= ~UCOM_FLAG_GP_DATA;
1689 /* Queue baud rate programming command first */
1690 ucom_queue_command(sc, ucom_cfg_param, t,
1691 &sc->sc_param_task[0].hdr,
1692 &sc->sc_param_task[1].hdr);
1694 /* Queue transfer enable command last */
1695 ucom_queue_command(sc, ucom_cfg_start_transfers, NULL,
1696 &sc->sc_start_task[0].hdr,
1697 &sc->sc_start_task[1].hdr);
1699 if (t->c_cflag & CRTS_IFLOW) {
1700 sc->sc_flag |= UCOM_FLAG_RTS_IFLOW;
1701 } else if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW) {
1702 sc->sc_flag &= ~UCOM_FLAG_RTS_IFLOW;
1703 ucom_modem(tp, SER_RTS, 0);
1711 lwkt_reltoken(&tp->t_token);
1717 ucom_start(struct tty *tp)
1719 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc;
1722 /* may be called locked or unlocked */
1723 if (lockowned(sc->sc_lock)) {
1729 /* UCOM_MTX_ASSERT(sc, MA_OWNED); */
1731 DPRINTF("sc = %p\n", sc);
1733 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
1734 /* The higher layer is not ready */
1736 UCOM_MTX_UNLOCK(sc);
1740 lwkt_gettoken(&tp->t_token);
1742 if (tp->t_state & TS_TBLOCK) {
1743 if (ISSET(sc->sc_mcr, SER_RTS) &&
1744 ISSET(sc->sc_flag, UCOM_FLAG_RTS_IFLOW)) {
1745 DPRINTF("ucom_start: clear RTS\n");
1746 (void)ucom_modem(tp, 0, SER_RTS);
1749 if (!ISSET(sc->sc_mcr, SER_RTS) &&
1750 tp->t_rawq.c_cc <= tp->t_ilowat &&
1751 ISSET(sc->sc_flag, UCOM_FLAG_RTS_IFLOW)) {
1752 DPRINTF("ucom_start: set RTS\n");
1753 (void)ucom_modem(tp, SER_RTS, 0);
1757 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) {
1759 DPRINTF("ucom_start: stopped\n");
1763 if (tp->t_outq.c_cc <= tp->t_olowat) {
1764 if (ISSET(tp->t_state, TS_SO_OLOWAT)) {
1765 CLR(tp->t_state, TS_SO_OLOWAT);
1766 wakeup(TSA_OLOWAT(tp));
1768 KNOTE(&tp->t_wkq.ki_note, 0);
1769 if (tp->t_outq.c_cc == 0) {
1770 if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) ==
1771 TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
1772 CLR(tp->t_state, TS_SO_OCOMPLETE);
1773 wakeup(TSA_OCOMPLETE(tp));
1779 DPRINTF("about to start write?\n");
1780 ucom_start_transfers(sc);
1785 lwkt_reltoken(&tp->t_token);
1787 UCOM_MTX_UNLOCK(sc);
1791 ucom_stop(struct tty *tp, int flag)
1793 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc;
1795 DPRINTF("sc = %p, x = 0x%x\n", sc, flag);
1797 lwkt_gettoken(&tp->t_token);
1800 * This is just supposed to flush pending receive data,
1801 * not stop the reception of data entirely!
1804 if (sc->sc_callback->ucom_stop_read) {
1805 (sc->sc_callback->ucom_stop_read) (sc);
1807 if (sc->sc_callback->ucom_start_read) {
1808 (sc->sc_callback->ucom_start_read) (sc);
1816 if (flag & FWRITE) {
1818 if (ISSET(tp->t_state, TS_BUSY)) {
1820 if (!ISSET(tp->t_state, TS_TTSTOP))
1821 SET(tp->t_state, TS_FLUSH);
1826 lwkt_reltoken(&tp->t_token);
1829 /*------------------------------------------------------------------------*
1832 * len: maximum length of data to get
1834 * Get data from the TTY layer
1837 * 0: No data is available.
1838 * Else: Data is available.
1839 *------------------------------------------------------------------------*/
1841 /* Copy data from the tty layer to usb */
1843 ucom_get_data(struct ucom_softc *sc, struct usb_page_cache *pc,
1844 uint32_t offset, uint32_t len, uint32_t *actlen)
1846 struct usb_page_search res;
1847 struct tty *tp = sc->sc_tty;
1849 uint32_t offset_orig;
1853 UCOM_MTX_ASSERT(sc, MA_OWNED);
1855 if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
1858 /* get total TX length */
1860 temp = ucom_cons_tx_high - ucom_cons_tx_low;
1861 temp %= UCOM_CONS_BUFSIZE;
1863 /* limit TX length */
1865 if (temp > (UCOM_CONS_BUFSIZE - ucom_cons_tx_low))
1866 temp = (UCOM_CONS_BUFSIZE - ucom_cons_tx_low);
1873 usbd_copy_in(pc, offset, ucom_cons_tx_buf + ucom_cons_tx_low, temp);
1875 /* update counters */
1877 ucom_cons_tx_low += temp;
1878 ucom_cons_tx_low %= UCOM_CONS_BUFSIZE;
1880 /* store actual length */
1884 return (temp ? 1 : 0);
1888 !(sc->sc_flag & UCOM_FLAG_GP_DATA)) {
1890 return (0); /* multiport device polling */
1893 offset_orig = offset;
1895 lwkt_gettoken(&tp->t_token);
1897 usbd_get_page(pc, offset, &res);
1899 /* Buffer bigger than max requested data */
1900 if (res.length > len) {
1903 /* copy data directly into USB buffer */
1904 SET(tp->t_state, TS_BUSY);
1905 cnt = clist_qtob(&tp->t_outq, res.buffer, len);
1907 DPRINTF("ucom_get_data: cnt == 0\n");
1908 CLR(tp->t_state, TS_BUSY);
1912 CLR(tp->t_state, TS_BUSY);
1914 /* XXX mp: This breaks avrdude,
1915 does the flush need to happen
1917 if (ISSET(tp->t_state, TS_FLUSH))
1918 CLR(tp->t_state, TS_FLUSH);
1920 ndflush(&tp->t_outq,cnt);
1926 if (cnt < res.length) {
1931 lwkt_reltoken(&tp->t_token);
1933 actlen[0] = offset - offset_orig;
1935 DPRINTF("cnt=%d\n", actlen[0]);
1937 if (actlen[0] == 0) {
1944 * Write data to the tty layer
1948 ucom_put_data(struct ucom_softc *sc, struct usb_page_cache *pc,
1949 uint32_t offset, uint32_t len)
1951 struct usb_page_search res;
1952 struct tty *tp = sc->sc_tty;
1959 UCOM_MTX_ASSERT(sc, MA_OWNED);
1960 lwkt_gettoken(&tp->t_token);
1962 if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
1965 /* get maximum RX length */
1967 temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_rx_high + ucom_cons_rx_low;
1968 temp %= UCOM_CONS_BUFSIZE;
1970 /* limit RX length */
1972 if (temp > (UCOM_CONS_BUFSIZE - ucom_cons_rx_high))
1973 temp = (UCOM_CONS_BUFSIZE - ucom_cons_rx_high);
1980 usbd_copy_out(pc, offset, ucom_cons_rx_buf + ucom_cons_rx_high, temp);
1982 /* update counters */
1984 ucom_cons_rx_high += temp;
1985 ucom_cons_rx_high %= UCOM_CONS_BUFSIZE;
1987 lwkt_reltoken(&tp->t_token);
1992 lwkt_reltoken(&tp->t_token);
1993 return; /* multiport device polling */
1996 lwkt_reltoken(&tp->t_token);
1997 return; /* no data */
2000 /* set a flag to prevent recursation ? */
2003 usbd_get_page(pc, offset, &res);
2005 if (res.length > len) {
2009 offset += res.length;
2011 /* pass characters to tty layer */
2016 /* first check if we can pass the buffer directly */
2018 if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
2019 /* clear any jitter buffer */
2020 sc->sc_jitterbuf_in = 0;
2021 sc->sc_jitterbuf_out = 0;
2023 if (tp->t_rawq.c_cc + cnt > tp->t_ihiwat
2024 && (sc->sc_flag & UCOM_FLAG_RTS_IFLOW
2025 || tp->t_iflag & IXOFF)
2026 && !(tp->t_state & TS_TBLOCK))
2028 lostcc = clist_btoq((char *)buf, cnt, &tp->t_rawq);
2032 if (*buf == sc->hotchar)
2041 if (tp->t_state & TS_TTSTOP
2042 && (tp->t_iflag & IXANY
2043 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
2044 tp->t_state &= ~TS_TTSTOP;
2045 tp->t_lflag &= ~FLUSHO;
2049 kprintf("lost %d chars\n", lostcc);
2052 if (ttydisc_rint_bypass(tp, buf, cnt) != cnt) {
2053 DPRINTF("tp=%p, data lost\n", tp);
2059 for (cnt = 0; cnt != res.length; cnt++) {
2060 if (sc->sc_jitterbuf_in != sc->sc_jitterbuf_out ||
2061 (*linesw[tp->t_line].l_rint)((unsigned char)buf[cnt], tp) == -1) {
2065 pos = sc->sc_jitterbuf_in;
2066 end = sc->sc_jitterbuf_out +
2067 UCOM_JITTERBUF_SIZE - 1;
2069 if (end >= UCOM_JITTERBUF_SIZE)
2070 end -= UCOM_JITTERBUF_SIZE;
2072 for (; cnt != res.length; cnt++) {
2075 sc->sc_jitterbuf[pos] = buf[cnt];
2077 if (pos >= UCOM_JITTERBUF_SIZE)
2078 pos -= UCOM_JITTERBUF_SIZE;
2081 sc->sc_jitterbuf_in = pos;
2083 /* set RTS in async fashion */
2084 if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW)
2087 DPRINTF("tp=%p, lost %d "
2088 "chars\n", tp, res.length - cnt);
2094 lwkt_reltoken(&tp->t_token);
2096 ttydisc_rint_done(tp);
2102 ucom_free(void *xsc)
2104 struct ucom_softc *sc = xsc;
2106 if (sc->sc_callback->ucom_free != NULL)
2107 sc->sc_callback->ucom_free(sc);
2109 /*ucom_unref(sc->sc_super) XXX hack, see end of ucom_detach_tty() */;
2111 lockmgr(&ucom_lock, LK_EXCLUSIVE);
2113 lockmgr(&ucom_lock, LK_RELEASE);
2116 static cn_probe_t ucom_cnprobe;
2117 static cn_init_t ucom_cninit;
2118 static cn_term_t ucom_cnterm;
2119 static cn_getc_t ucom_cngetc;
2120 static cn_putc_t ucom_cnputc;
2123 static cn_grab_t ucom_cngrab;
2124 static cn_ungrab_t ucom_cnungrab;
2125 CONSOLE_DRIVER(ucom);
2129 ucom_cnprobe(struct consdev *cp)
2131 if (ucom_cons_unit != -1)
2132 cp->cn_pri = CN_NORMAL;
2134 cp->cn_pri = CN_DEAD;
2137 strlcpy(cp->cn_name, "ucom", sizeof(cp->cn_name));
2142 ucom_cninit(struct consdev *cp)
2147 ucom_cnterm(struct consdev *cp)
2152 ucom_cngrab(struct consdev *cp)
2157 ucom_cnungrab(struct consdev *cp)
2162 ucom_cngetc(struct consdev *cd)
2164 struct ucom_softc *sc = ucom_cons_softc;
2172 if (ucom_cons_rx_low != ucom_cons_rx_high) {
2173 c = ucom_cons_rx_buf[ucom_cons_rx_low];
2174 ucom_cons_rx_low ++;
2175 ucom_cons_rx_low %= UCOM_CONS_BUFSIZE;
2180 /* start USB transfers */
2181 ucom_outwakeup(sc->sc_tty);
2183 UCOM_MTX_UNLOCK(sc);
2185 /* poll if necessary */
2187 if (kdb_active && sc->sc_callback->ucom_poll)
2188 (sc->sc_callback->ucom_poll) (sc);
2194 ucom_cnputc(void *cd, int c)
2196 ucom_cnputc(struct consdev *cd, int c)
2200 struct ucom_softc *sc = ucom_cons_softc;
2210 /* compute maximum TX length */
2212 temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_tx_high + ucom_cons_tx_low;
2213 temp %= UCOM_CONS_BUFSIZE;
2216 ucom_cons_tx_buf[ucom_cons_tx_high] = c;
2217 ucom_cons_tx_high ++;
2218 ucom_cons_tx_high %= UCOM_CONS_BUFSIZE;
2221 /* start USB transfers */
2222 ucom_outwakeup(sc->sc_tty);
2224 UCOM_MTX_UNLOCK(sc);
2226 /* poll if necessary */
2228 if (kdb_active && sc->sc_callback->ucom_poll) {
2229 (sc->sc_callback->ucom_poll) (sc);
2230 /* simple flow control */
2237 /*------------------------------------------------------------------------*
2240 * This function will increment the super UCOM reference count.
2241 *------------------------------------------------------------------------*/
2243 ucom_ref(struct ucom_super_softc *ssc)
2245 lockmgr(&ucom_lock, LK_EXCLUSIVE);
2247 lockmgr(&ucom_lock, LK_RELEASE);
2250 /*------------------------------------------------------------------------*
2253 * This function will free the super UCOM's allocated unit
2254 * number. This function can be called on a zero-initialized
2255 * structure. This function can be called multiple times.
2256 *------------------------------------------------------------------------*/
2258 ucom_free_unit(struct ucom_super_softc *ssc)
2260 if (!(ssc->sc_flag & UCOM_FLAG_FREE_UNIT))
2263 ucom_unit_free(ssc->sc_unit);
2265 ssc->sc_flag &= ~UCOM_FLAG_FREE_UNIT;
2268 /*------------------------------------------------------------------------*
2271 * This function will decrement the super UCOM reference count.
2274 * 0: UCOM structures are still referenced.
2275 * Else: UCOM structures are no longer referenced.
2276 *------------------------------------------------------------------------*/
2278 ucom_unref(struct ucom_super_softc *ssc)
2282 lockmgr(&ucom_lock, LK_EXCLUSIVE);
2283 retval = (ssc->sc_refs < 2);
2285 lockmgr(&ucom_lock, LK_RELEASE);
2288 ucom_free_unit(ssc);
2294 * NOTE: Must be called with tp->t_token held.
2297 disc_optim(struct tty *tp, struct termios *t, struct ucom_softc *sc)
2299 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
2300 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
2301 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
2302 && (!(t->c_iflag & PARMRK)
2303 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
2304 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
2305 && linesw[tp->t_line].l_rint == ttyinput) {
2306 DPRINTF("disc_optim: bypass l_rint\n");
2307 tp->t_state |= TS_CAN_BYPASS_L_RINT;
2309 DPRINTF("disc_optim: can't bypass l_rint\n");
2310 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
2312 sc->hotchar = linesw[tp->t_line].l_hotchar;
2317 #include <gdb/gdb.h>
2319 static gdb_probe_f ucom_gdbprobe;
2320 static gdb_init_f ucom_gdbinit;
2321 static gdb_term_f ucom_gdbterm;
2322 static gdb_getc_f ucom_gdbgetc;
2323 static gdb_putc_f ucom_gdbputc;
2325 GDB_DBGPORT(sio, ucom_gdbprobe, ucom_gdbinit, ucom_gdbterm, ucom_gdbgetc, ucom_gdbputc);
2330 return ((ucom_cons_softc != NULL) ? 0 : -1);
2346 ucom_cnputc(NULL, c);
2352 return (ucom_cngetc(NULL));