PERFORCE change 98937 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sat Jun 10 20:57:22 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=98937
Change 98937 by hselasky at hselasky_mini_itx on 2006/06/10 20:54:54
Finished reworking "ucom.c" and "umodem.c".
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/ucom.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb/ucomvar.h#4 edit
.. //depot/projects/usb/src/sys/dev/usb/umodem.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_cdc.h#1 add
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/ucom.c#4 (text+ko) ====
@@ -1,0 +1,742 @@
+/* $NetBSD: ucom.c,v 1.40 2001/11/13 06:24:54 lukem Exp $ */
+
+/*-
+ * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart at augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/tty.h>
+#include <sys/serial.h>
+#include <sys/taskqueue.h>
+
+#include <dev/usb/usb_port.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_subr.h>
+#include <dev/usb/usb_quirks.h>
+#include <dev/usb/usb_cdc.h>
+
+#include <dev/usb/ucomvar.h>
+
+__FBSDID("$FreeBSD: src/sys/dev/usb/ucom.c $");
+
+#ifdef USB_DEBUG
+#define DPRINTF(n,fmt,...) \
+ do { if (ucom_debug > (n)) { \
+ printf("%s: " fmt, __FUNCTION__,## __VA_ARGS__); } } while (0)
+
+static int ucom_debug = 0;
+SYSCTL_NODE(_hw_usb, OID_AUTO, ucom, CTLFLAG_RW, 0, "USB ucom");
+SYSCTL_INT(_hw_usb_ucom, OID_AUTO, debug, CTLFLAG_RW,
+ &ucom_debug, 0, "ucom debug level");
+#else
+#define DPRINTF(...)
+#endif
+
+static void
+ucom_shutdown(struct ucom_softc *sc);
+
+static int
+ucom_open(struct tty *tp, struct cdev *dev);
+
+static void
+ucom_close(struct tty *tp);
+
+static int
+ucom_ioctl(struct tty *tp, u_long cmd, void *data,
+ int flag, struct thread *td);
+
+static int
+ucom_modem(struct tty *tp, int sigon, int sigoff);
+
+static void
+ucom_break(struct tty *tp, int onoff);
+
+static void
+ucom_dtr(struct ucom_softc *sc, u_int8_t onoff);
+
+static void
+ucom_rts(struct ucom_softc *sc, u_int8_t onoff);
+
+static void
+ucom_notify(void *arg, int pending);
+
+static int
+ucom_param(struct tty *tp, struct termios *t);
+
+static void
+ucom_start_write(struct tty *tp);
+
+static void
+ucom_stop_write(struct tty *tp, int fflags);
+
+devclass_t ucom_devclass;
+
+static moduledata_t ucom_mod = {
+ "ucom",
+ NULL,
+ NULL
+};
+
+DECLARE_MODULE(ucom, ucom_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
+MODULE_DEPEND(ucom, usb, 1, 1, 1);
+MODULE_VERSION(ucom, UCOM_MODVER);
+
+int
+ucom_attach(struct ucom_softc *sc, device_t dev)
+{
+ struct tty *tp;
+ int error = 0;
+ int unit;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ unit = device_get_unit(dev);
+
+ tp = ttyalloc();
+
+ if (tp == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
+
+ tp->t_sc = sc;
+ tp->t_oproc = ucom_start_write;
+ tp->t_param = ucom_param;
+ tp->t_stop = ucom_stop_write;
+ tp->t_break = ucom_break;
+ tp->t_open = ucom_open;
+ tp->t_close = ucom_close;
+ tp->t_modem = ucom_modem;
+ tp->t_ioctl = ucom_ioctl;
+
+ DPRINTF(0, "tp = %p\n", tp);
+
+ error = ttycreate(tp, TS_CALLOUT, "U%d", unit);
+ if (error) {
+ ttyfree(tp);
+ goto done;
+ }
+
+ sc->sc_tty = tp;
+
+ TASK_INIT(&(sc->sc_task), 0, &ucom_notify, sc);
+
+ DPRINTF(0, "ttycreate: ttyU%d\n", unit);
+
+ done:
+ return error;
+}
+
+void
+ucom_detach(struct ucom_softc *sc)
+{
+ struct tty *tp = sc->sc_tty;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ DPRINTF(0, "sc = %p, tp = %p\n", sc, sc->sc_tty);
+
+ sc->sc_flag |= UCOM_FLAG_GONE;
+
+ if (tp) {
+
+ ttygone(tp);
+
+ if (tp->t_state & TS_ISOPEN) {
+ ucom_close(tp);
+ }
+
+ /* make sure that read and write
+ * transfers are stopped
+ */
+ if (sc->sc_callback->ucom_stop_read) {
+ (sc->sc_callback->ucom_stop_read)(sc);
+ }
+
+ if (sc->sc_callback->ucom_stop_write) {
+ (sc->sc_callback->ucom_stop_write)(sc);
+ }
+
+ taskqueue_drain(taskqueue_swi_giant, &(sc->sc_task));
+
+ ttyfree(tp);
+ }
+ return;
+}
+
+static void
+ucom_shutdown(struct ucom_softc *sc)
+{
+ struct tty *tp = sc->sc_tty;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ DPRINTF(0, "\n");
+ /*
+ * Hang up if necessary:
+ */
+ if (tp->t_cflag & HUPCL) {
+ ucom_modem(tp, 0, SER_DTR);
+ }
+ return;
+}
+
+static int
+ucom_open(struct tty *tp, struct cdev *dev)
+{
+ struct ucom_softc *sc = tp->t_sc;
+ int error;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ if (sc->sc_flag & UCOM_FLAG_GONE) {
+ return ENXIO;
+ }
+
+ /*
+ * wait a little for previous commands
+ * to be flushed out:
+ */
+ error = ttysleep(tp, tp, PCATCH | TTIPRI, "ucomsd", hz);
+
+ if (error) {
+ return error;
+ }
+
+ DPRINTF(0, "tp = %p\n", tp);
+
+ sc->sc_poll = 0;
+ sc->sc_lsr = 0;
+ sc->sc_msr = 0;
+ sc->sc_mcr = 0;
+
+ ucom_modem(tp, SER_DTR | SER_RTS, 0);
+
+ /* device specific open */
+
+ if (sc->sc_callback->ucom_open) {
+
+ error = (sc->sc_callback->ucom_open)(sc);
+
+ if (error) {
+ ucom_shutdown(sc);
+ return error;
+ }
+ }
+
+ if (sc->sc_callback->ucom_start_read) {
+ (sc->sc_callback->ucom_start_read)(sc);
+ }
+
+ sc->sc_poll = 1;
+
+ return 0;
+}
+
+static void
+ucom_close(struct tty *tp)
+{
+ struct ucom_softc *sc = tp->t_sc;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ DPRINTF(0, "tp=%p\n", tp);
+
+ tp->t_state &= ~TS_BUSY;
+
+ ucom_shutdown(sc);
+
+ if (sc->sc_callback->ucom_stop_read) {
+ (sc->sc_callback->ucom_stop_read)(sc);
+ }
+
+ if (sc->sc_callback->ucom_stop_write) {
+ (sc->sc_callback->ucom_stop_write)(sc);
+ }
+
+ if (sc->sc_callback->ucom_close) {
+ (sc->sc_callback->ucom_close)(sc);
+ }
+ return;
+}
+
+static int
+ucom_ioctl(struct tty *tp, u_long cmd, void *data,
+ int flag, struct thread *td)
+{
+ struct ucom_softc *sc = tp->t_sc;
+ int error;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ if (sc->sc_flag & UCOM_FLAG_GONE) {
+ return EIO;
+ }
+
+ DPRINTF(0, "cmd = 0x%08lx\n", cmd);
+
+ error = ENOTTY;
+ if (sc->sc_callback->ucom_ioctl) {
+ error = (sc->sc_callback->ucom_ioctl)(sc, cmd, data, flag, td);
+ }
+ return error;
+}
+
+static int
+ucom_modem(struct tty *tp, int sigon, int sigoff)
+{
+ struct ucom_softc *sc = tp->t_sc;
+ u_int8_t onoff;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ if (sc->sc_flag & UCOM_FLAG_GONE) {
+ return 0;
+ }
+
+ if ((sigon == 0) && (sigoff == 0)) {
+
+ if (sc->sc_mcr & SER_DTR) {
+ sigon |= SER_DTR;
+ }
+ if (sc->sc_mcr & SER_RTS) {
+ sigon |= SER_RTS;
+ }
+
+ if (sc->sc_msr & SER_CTS) {
+ sigon |= SER_CTS;
+ }
+ if (sc->sc_msr & SER_DCD) {
+ sigon |= SER_DCD;
+ }
+ if (sc->sc_msr & SER_DSR) {
+ sigon |= SER_DSR;
+ }
+ if (sc->sc_msr & SER_RI) {
+ sigon |= SER_RI;
+ }
+ return sigon;
+ }
+
+ if (sigon & SER_DTR) {
+ sc->sc_mcr |= SER_DTR;
+ }
+ if (sigoff & SER_DTR) {
+ sc->sc_mcr &= ~SER_DTR;
+ }
+ if (sigon & SER_RTS) {
+ sc->sc_mcr |= SER_RTS;
+ }
+ if (sigoff & SER_RTS) {
+ sc->sc_mcr &= ~SER_RTS;
+ }
+
+ onoff = (sc->sc_mcr & SER_DTR) ? 1 : 0;
+ ucom_dtr(sc, onoff);
+
+ onoff = (sc->sc_mcr & SER_RTS) ? 1 : 0;
+ ucom_rts(sc, onoff);
+
+ return 0;
+}
+
+static void
+ucom_break(struct tty *tp, int onoff)
+{
+ struct ucom_softc *sc = tp->t_sc;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ if (sc->sc_flag & UCOM_FLAG_GONE) {
+ return;
+ }
+
+ DPRINTF(0, "onoff = %d\n", onoff);
+ if (sc->sc_callback->ucom_set_break) {
+ (sc->sc_callback->ucom_set_break)(sc, onoff);
+ }
+ return;
+}
+
+static void
+ucom_dtr(struct ucom_softc *sc, u_int8_t onoff)
+{
+ DPRINTF(0, "onoff = %d\n", onoff);
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ if (sc->sc_callback->ucom_set_dtr) {
+ (sc->sc_callback->ucom_set_dtr)(sc, onoff);
+ }
+ return;
+}
+
+static void
+ucom_rts(struct ucom_softc *sc, u_int8_t onoff)
+{
+ DPRINTF(0, "onoff = %d\n", onoff);
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ if (sc->sc_callback->ucom_set_rts) {
+ (sc->sc_callback->ucom_set_rts)(sc, onoff);
+ }
+ return;
+}
+
+void
+ucom_status_change(struct ucom_softc *sc)
+{
+ u_int8_t old_msr;
+ u_int8_t onoff;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ if (sc->sc_callback->ucom_get_status == NULL) {
+ sc->sc_lsr = 0;
+ sc->sc_msr = 0;
+ return;
+ }
+
+ old_msr = sc->sc_msr;
+
+ (sc->sc_callback->ucom_get_status)(sc, &(sc->sc_lsr), &(sc->sc_msr));
+
+ if ((sc->sc_msr ^ old_msr) & SER_DCD) {
+ if (sc->sc_poll == 0) {
+ return;
+ }
+ onoff = (sc->sc_msr & SER_DCD) ? 1 : 0;
+ DPRINTF(0, "DCD changed to %d\n", onoff);
+
+ sc->sc_last_status = onoff;
+
+ /* deferred notifying to the TTY layer */
+ taskqueue_enqueue(taskqueue_swi_giant, &(sc->sc_task));
+ }
+ return;
+}
+
+static void
+ucom_notify(void *arg, int pending)
+{
+ struct ucom_softc *sc = arg;
+ struct tty *tp = sc->sc_tty;
+
+ ttyld_modem(tp, sc->sc_last_status);
+
+ return;
+}
+
+static int
+ucom_param(struct tty *tp, struct termios *t)
+{
+ struct ucom_softc *sc = tp->t_sc;
+ int error;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ if (sc->sc_flag & UCOM_FLAG_GONE) {
+ return EIO;
+ }
+
+ DPRINTF(0, "sc = %p\n", sc);
+
+ /* Check requested parameters. */
+ if (t->c_ospeed < 0) {
+ DPRINTF(0, "negative ospeed\n");
+ return EINVAL;
+ }
+ if (t->c_ispeed && (t->c_ispeed != t->c_ospeed)) {
+ DPRINTF(0, "mismatch ispeed and ospeed\n");
+ return EINVAL;
+ }
+
+ /*
+ * If there were no changes, don't do anything. This avoids dropping
+ * input and improves performance when all we did was frob things like
+ * VMIN and VTIME.
+ */
+ if ((tp->t_ospeed == t->c_ospeed) &&
+ (tp->t_cflag == t->c_cflag)) {
+ return 0;
+ }
+
+ /* And copy to tty. */
+ tp->t_ispeed = 0;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = t->c_cflag;
+
+ if (sc->sc_callback->ucom_param == NULL) {
+ return 0;
+ }
+
+ if (sc->sc_callback->ucom_stop_read) {
+ (sc->sc_callback->ucom_stop_read)(sc);
+ }
+
+ error = (sc->sc_callback->ucom_param)(sc, t);
+ if (error) {
+ DPRINTF(0, "callback error = %d\n", error);
+ return error;
+ }
+
+ ttsetwater(tp);
+
+ if (t->c_cflag & CRTS_IFLOW) {
+ sc->sc_flag |= UCOM_FLAG_RTS_IFLOW;
+ } else if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW) {
+ sc->sc_flag &= ~UCOM_FLAG_RTS_IFLOW;
+ ucom_modem(tp, SER_RTS, 0);
+ }
+
+ ttyldoptim(tp);
+
+ if (sc->sc_callback->ucom_start_read) {
+ (sc->sc_callback->ucom_start_read)(sc);
+ }
+
+ return 0;
+}
+
+static void
+ucom_start_write(struct tty *tp)
+{
+ struct ucom_softc *sc = tp->t_sc;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ DPRINTF(0, "sc = %p\n", sc);
+
+ if (sc->sc_flag & UCOM_FLAG_GONE) {
+ return;
+ }
+
+ tp->t_state |= TS_BUSY;
+
+ if (sc->sc_callback->ucom_start_write) {
+ (sc->sc_callback->ucom_start_write)(sc);
+ }
+ return;
+}
+
+static void
+ucom_stop_write(struct tty *tp, int fflags)
+{
+ struct ucom_softc *sc = tp->t_sc;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ if (sc->sc_flag & UCOM_FLAG_GONE) {
+ return;
+ }
+
+ DPRINTF(0, "fflags=%d\n", fflags);
+
+ if (fflags & FWRITE) {
+ DPRINTF(0, "write\n");
+ if (tp->t_state & TS_BUSY) {
+ /* XXX do what? */
+ if (!(tp->t_state & TS_TTSTOP)) {
+ tp->t_state |= TS_FLUSH;
+ }
+ }
+ }
+
+ ucom_start_write(tp);
+
+ DPRINTF(0, "done\n");
+
+ return;
+}
+
+/*
+ * the following function returns
+ * 1 if data is available, else 0
+ */
+
+u_int8_t
+ucom_get_data(struct ucom_softc *sc, u_int8_t *buf, u_int32_t len,
+ u_int32_t *actlen)
+{
+ struct tty *tp = sc->sc_tty;
+ u_int32_t cnt;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ actlen[0] = 0;
+
+ if (tp->t_state & TS_TBLOCK) {
+ if ((sc->sc_mcr & SER_RTS) &&
+ (sc->sc_flag & UCOM_FLAG_RTS_IFLOW)) {
+ DPRINTF(0, "clear RTS\n");
+ ucom_modem(tp, 0, SER_RTS);
+ }
+ } else {
+ if (!(sc->sc_mcr & SER_RTS) &&
+ (tp->t_rawq.c_cc <= tp->t_ilowat) &&
+ (sc->sc_flag & UCOM_FLAG_RTS_IFLOW)) {
+ DPRINTF(0, "set RTS\n");
+ ucom_modem(tp, SER_RTS, 0);
+ }
+ }
+
+ if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
+ DPRINTF(0, "stopped\n");
+ goto done;
+ }
+
+ cnt = q_to_b(&(tp->t_outq), buf, len);
+
+ if (cnt > len) {
+ DPRINTF(0, "invalid length, %d bytes\n", cnt);
+ goto done;
+ }
+
+ if (cnt == 0) {
+ DPRINTF(0, "cnt == 0\n");
+ goto done;
+ }
+
+ actlen[0] = cnt;
+
+ ttwwakeup(tp);
+
+ return 1;
+
+ done:
+ tp->t_state &= ~(TS_BUSY | TS_FLUSH);
+
+ ttwwakeup(tp);
+
+ return 0;
+}
+
+void
+ucom_put_data(struct ucom_softc *sc, u_int8_t *ptr, u_int16_t len)
+{
+ struct tty *tp = sc->sc_tty;
+ u_int16_t lostcc;
+
+ mtx_assert(&Giant, MA_OWNED);
+
+ /* set a flag to prevent recursation */
+
+ if (len == 0) {
+ goto done;
+ }
+
+ if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
+ if (((tp->t_rawq.c_cc + len) > tp->t_ihiwat) &&
+ ((sc->sc_flag & UCOM_FLAG_RTS_IFLOW) ||
+ (tp->t_iflag & IXOFF)) &&
+ (!(tp->t_state & TS_TBLOCK))) {
+ ttyblock(tp);
+ }
+
+ lostcc = b_to_q(ptr, len, &(tp->t_rawq));
+
+ tp->t_rawcc += len;
+
+ ttwakeup(tp);
+
+ if ((tp->t_state & TS_TTSTOP) &&
+ ((tp->t_iflag & IXANY) ||
+ (tp->t_cc[VSTART] == tp->t_cc[VSTOP]))) {
+ tp->t_state &= ~TS_TTSTOP;
+ tp->t_lflag &= ~FLUSHO;
+ ucom_start_write(tp);
+ }
+ if (lostcc > 0) {
+ DPRINTF(0, "tp=%p, lost %d "
+ "chars\n", tp, lostcc);
+ }
+ } else {
+ /* pass characters to tty layer */
+ while (len) {
+ DPRINTF(7, "char = 0x%02x\n", *ptr);
+
+ if (ttyld_rint(tp, *ptr) == -1) {
+
+ /* XXX what should we do? */
+
+ DPRINTF(0, "tp=%p, lost %d "
+ "chars\n", tp, len);
+ break;
+ }
+ len--;
+ ptr++;
+ }
+ }
+
+ done:
+ if ((sc->sc_flag & UCOM_FLAG_RTS_IFLOW) &&
+ (!(sc->sc_mcr & SER_RTS)) &&
+ (!(tp->t_state & TS_TBLOCK))) {
+ ucom_modem(tp, SER_RTS, 0);
+ }
+ return;
+}
==== //depot/projects/usb/src/sys/dev/usb/ucomvar.h#4 (text+ko) ====
@@ -71,37 +71,22 @@
#define UCOM_PREFVER UCOM_MODVER
#define UCOM_MAXVER 1
-/* Macros to clear/set/test flags. */
-#define SET(t, f) (t) |= (f)
-#define CLR(t, f) (t) &= ~((unsigned)(f))
-#define ISSET(t, f) ((t) & (f))
-
-#define UCOM_CALLOUT_MASK 0x80
-
-#define UCOMUNIT_MASK 0x3ff7f
-#define UCOMDIALOUT_MASK 0x80000
-#define UCOMCALLUNIT_MASK 0x40000
-
-#define UCOMUNIT(x) (minor(x) & UCOMUNIT_MASK)
-#define UCOMDIALOUT(x) (minor(x) & UCOMDIALOUT_MASK)
-#define UCOMCALLUNIT(x) (minor(x) & UCOMCALLUNIT_MASK)
-
-#define UCOM_UNK_PORTNO -1 /* XXX */
-
struct ucom_softc;
+struct thread;
struct ucom_callback {
- void (*ucom_get_status)(void *, int, u_char *, u_char *);
- void (*ucom_set)(void *, int, int, int);
-#define UCOM_SET_DTR 1
-#define UCOM_SET_RTS 2
-#define UCOM_SET_BREAK 3
- int (*ucom_param)(void *, int, struct termios *);
- int (*ucom_ioctl)(void *, int, u_long, caddr_t, int, usb_proc_ptr);
- int (*ucom_open)(void *, int);
- void (*ucom_close)(void *, int);
- void (*ucom_read)(void *, int, u_char **, u_int32_t *);
- void (*ucom_write)(void *, int, u_char *, u_char *, u_int32_t *);
+ void (*ucom_get_status)(struct ucom_softc *, u_int8_t *, u_int8_t *);
+ void (*ucom_set_dtr)(struct ucom_softc *, u_int8_t);
+ void (*ucom_set_rts)(struct ucom_softc *, u_int8_t);
+ void (*ucom_set_break)(struct ucom_softc *, u_int8_t);
+ int (*ucom_param)(struct ucom_softc *, struct termios *);
+ int (*ucom_ioctl)(struct ucom_softc *, u_long, caddr_t, int, struct thread *);
+ int (*ucom_open)(struct ucom_softc *);
+ void (*ucom_close)(struct ucom_softc *);
+ void (*ucom_start_read)(struct ucom_softc *);
+ void (*ucom_stop_read)(struct ucom_softc *);
+ void (*ucom_start_write)(struct ucom_softc *);
+ void (*ucom_stop_write)(struct ucom_softc *);
};
/* line status register */
@@ -115,50 +100,41 @@
#define ULSR_RXRDY 0x01 /* Byte ready in Receive Buffer */
#define ULSR_RCV_MASK 0x1f /* Mask for incoming data or error */
-/* ucom state declarations */
-#define UCS_RXSTOP 0x0001 /* Rx stopped */
-#define UCS_RTS_IFLOW 0x0008 /* use RTS input flow control */
-
struct ucom_softc {
- USBBASEDEVICE sc_dev; /* base device */
- usbd_device_handle sc_udev; /* USB device */
- usbd_interface_handle sc_iface; /* data interface */
+ struct task sc_task;
- int sc_bulkin_no; /* bulk in endpoint address */
- usbd_pipe_handle sc_bulkin_pipe; /* bulk in pipe */
- usbd_xfer_handle sc_ixfer; /* read request */
- u_char *sc_ibuf; /* read buffer */
- u_int sc_ibufsize; /* read buffer size */
- u_int sc_ibufsizepad; /* read buffer size padded */
+ const struct ucom_callback * sc_callback;
+ struct tty * sc_tty;
+ void * sc_parent;
- int sc_bulkout_no; /* bulk out endpoint address */
- usbd_pipe_handle sc_bulkout_pipe;/* bulk out pipe */
- usbd_xfer_handle sc_oxfer; /* write request */
- u_char *sc_obuf; /* write buffer */
- u_int sc_obufsize; /* write buffer size */
- u_int sc_opkthdrlen; /* header length of
- output packet */
+ u_int16_t sc_portno;
- struct ucom_callback *sc_callback;
- void *sc_parent;
- int sc_portno;
+ u_int8_t sc_flag;
+#define UCOM_FLAG_RTS_IFLOW 0x01 /* use RTS input flow control */
+#define UCOM_FLAG_GONE 0x02 /* the device is gone */
- struct tty *sc_tty; /* our tty */
+ u_int8_t sc_lsr;
+ u_int8_t sc_msr;
+ u_int8_t sc_mcr;
+ u_int8_t sc_poll;
+ u_int8_t sc_last_status;
+};
- int sc_state;
+extern devclass_t ucom_devclass;
- int sc_poll;
+extern int
+ucom_attach(struct ucom_softc *sc, device_t dev);
- u_char sc_lsr;
- u_char sc_msr;
- u_char sc_mcr;
+extern void
+ucom_detach(struct ucom_softc *);
- u_char sc_dying; /* disconnecting */
+extern void
+ucom_status_change(struct ucom_softc *);
-};
+extern u_int8_t
+ucom_get_data(struct ucom_softc *sc, u_int8_t *buf, u_int32_t len,
+ u_int32_t *actlen);
-extern devclass_t ucom_devclass;
+extern void
+ucom_put_data(struct ucom_softc *sc, u_int8_t *ptr, u_int16_t len);
-int ucom_attach(struct ucom_softc *);
-int ucom_detach(struct ucom_softc *);
-void ucom_status_change(struct ucom_softc *);
==== //depot/projects/usb/src/sys/dev/usb/umodem.c#4 (text+ko) ====
@@ -1,0 +1,1147 @@
+/* $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $ */
+
+/*-
+ * Copyright (c) 2003, M. Warner Losh <imp at freebsd.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart at augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Comm Class spec: http://www.usb.org/developers/devclass_docs/usbccs10.pdf
+ * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
+ */
+
+/*
+ * TODO:
+ * - Add error recovery in various places; the big problem is what
+ * to do in a callback if there is an error.
+ * - Implement a Call Device for modems without multiplexed commands.
+ *
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/termios.h>
+#include <sys/serial.h>
+
+#include <dev/usb/usb_port.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_subr.h>
+#include <dev/usb/usb_quirks.h>
+#include <dev/usb/usb_cdc.h>
+
+#include <dev/usb/ucomvar.h>
+
+#include "usbdevs.h"
+
+__FBSDID("$FreeBSD: src/sys/dev/usb/umodem.c $");
+
+#ifdef USB_DEBUG
+#define DPRINTF(n,fmt,...) \
+ do { if (umodem_debug > (n)) { \
+ printf("%s: " fmt, __FUNCTION__,## __VA_ARGS__); } } while (0)
+
+static int umodem_debug = 0;
+SYSCTL_NODE(_hw_usb, OID_AUTO, umodem, CTLFLAG_RW, 0, "USB umodem");
+SYSCTL_INT(_hw_usb_umodem, OID_AUTO, debug, CTLFLAG_RW,
+ &umodem_debug, 0, "umodem debug level");
+#else
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list