Add experimental support for usb serial console and polled mode during DDB.
Submitted by: Hans Petter Selasky
This commit is contained in:
parent
d391f7f701
commit
13d838412e
@ -114,6 +114,7 @@ static void uark_cfg_get_status(struct ucom_softc *, uint8_t *,
|
||||
uint8_t *);
|
||||
static void uark_cfg_set_break(struct ucom_softc *, uint8_t);
|
||||
static void uark_cfg_write(struct uark_softc *, uint16_t, uint16_t);
|
||||
static void uark_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config
|
||||
uark_xfer_config[UARK_N_TRANSFER] = {
|
||||
@ -146,6 +147,7 @@ static const struct ucom_callback uark_callback = {
|
||||
.ucom_stop_read = &uark_stop_read,
|
||||
.ucom_start_write = &uark_start_write,
|
||||
.ucom_stop_write = &uark_stop_write,
|
||||
.ucom_poll = &uark_poll,
|
||||
};
|
||||
|
||||
static device_method_t uark_methods[] = {
|
||||
@ -431,3 +433,10 @@ uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value)
|
||||
"(ignored)\n", usbd_errstr(err));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
uark_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct uark_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UARK_N_TRANSFER);
|
||||
}
|
||||
|
@ -194,6 +194,7 @@ static void ubsa_start_write(struct ucom_softc *);
|
||||
static void ubsa_stop_write(struct ucom_softc *);
|
||||
static void ubsa_cfg_get_status(struct ucom_softc *, uint8_t *,
|
||||
uint8_t *);
|
||||
static void ubsa_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config ubsa_config[UBSA_N_TRANSFER] = {
|
||||
|
||||
@ -236,6 +237,7 @@ static const struct ucom_callback ubsa_callback = {
|
||||
.ucom_stop_read = &ubsa_stop_read,
|
||||
.ucom_start_write = &ubsa_start_write,
|
||||
.ucom_stop_write = &ubsa_stop_write,
|
||||
.ucom_poll = &ubsa_poll,
|
||||
};
|
||||
|
||||
static const struct usb_device_id ubsa_devs[] = {
|
||||
@ -659,3 +661,11 @@ ubsa_intr_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ubsa_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct ubsa_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UBSA_N_TRANSFER);
|
||||
|
||||
}
|
||||
|
@ -163,6 +163,7 @@ static void ubser_start_read(struct ucom_softc *);
|
||||
static void ubser_stop_read(struct ucom_softc *);
|
||||
static void ubser_start_write(struct ucom_softc *);
|
||||
static void ubser_stop_write(struct ucom_softc *);
|
||||
static void ubser_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config ubser_config[UBSER_N_TRANSFER] = {
|
||||
|
||||
@ -193,6 +194,7 @@ static const struct ucom_callback ubser_callback = {
|
||||
.ucom_stop_read = &ubser_stop_read,
|
||||
.ucom_start_write = &ubser_start_write,
|
||||
.ucom_stop_write = &ubser_stop_write,
|
||||
.ucom_poll = &ubser_poll,
|
||||
};
|
||||
|
||||
static device_method_t ubser_methods[] = {
|
||||
@ -535,3 +537,10 @@ ubser_stop_write(struct ucom_softc *ucom)
|
||||
|
||||
usbd_transfer_stop(sc->sc_xfer[UBSER_BULK_DT_WR]);
|
||||
}
|
||||
|
||||
static void
|
||||
ubser_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct ubser_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UBSER_N_TRANSFER);
|
||||
}
|
||||
|
@ -118,6 +118,7 @@ static void uch341_start_read(struct ucom_softc *);
|
||||
static void uch341_stop_read(struct ucom_softc *);
|
||||
static void uch341_start_write(struct ucom_softc *);
|
||||
static void uch341_stop_write(struct ucom_softc *);
|
||||
static void uch341_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config uch341_config[UCH341_N_TRANSFER] = {
|
||||
|
||||
@ -152,6 +153,7 @@ static const struct ucom_callback uch341_callback = {
|
||||
.ucom_stop_read = &uch341_stop_read,
|
||||
.ucom_start_write = &uch341_start_write,
|
||||
.ucom_stop_write = &uch341_stop_write,
|
||||
.ucom_poll = &uch341_poll,
|
||||
};
|
||||
|
||||
static device_method_t uch341_methods[] = {
|
||||
@ -519,3 +521,10 @@ uch341_stop_write(struct ucom_softc *ucom)
|
||||
|
||||
usbd_transfer_stop(sc->sc_xfer[UCH341_BULK_DT_WR]);
|
||||
}
|
||||
|
||||
static void
|
||||
uch341_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct uch341_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UCH341_N_TRANSFER);
|
||||
}
|
||||
|
@ -230,6 +230,7 @@ static void uchcom_set_dte_rate(struct uchcom_softc *, uint32_t);
|
||||
static void uchcom_set_line_control(struct uchcom_softc *, tcflag_t);
|
||||
static void uchcom_clear_chip(struct uchcom_softc *);
|
||||
static void uchcom_reset_chip(struct uchcom_softc *);
|
||||
static void uchcom_poll(struct ucom_softc *ucom);
|
||||
|
||||
static device_probe_t uchcom_probe;
|
||||
static device_attach_t uchcom_attach;
|
||||
@ -280,6 +281,7 @@ static struct ucom_callback uchcom_callback = {
|
||||
.ucom_stop_read = &uchcom_stop_read,
|
||||
.ucom_start_write = &uchcom_start_write,
|
||||
.ucom_stop_write = &uchcom_stop_write,
|
||||
.ucom_poll = &uchcom_poll,
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
@ -888,6 +890,13 @@ uchcom_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
uchcom_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct uchcom_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UCHCOM_N_TRANSFER);
|
||||
}
|
||||
|
||||
static device_method_t uchcom_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, uchcom_probe),
|
||||
|
@ -124,6 +124,7 @@ static void ucycom_stop_write(struct ucom_softc *);
|
||||
static void ucycom_cfg_write(struct ucycom_softc *, uint32_t, uint8_t);
|
||||
static int ucycom_pre_param(struct ucom_softc *, struct termios *);
|
||||
static void ucycom_cfg_param(struct ucom_softc *, struct termios *);
|
||||
static void ucycom_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config ucycom_config[UCYCOM_N_TRANSFER] = {
|
||||
|
||||
@ -154,6 +155,7 @@ static const struct ucom_callback ucycom_callback = {
|
||||
.ucom_stop_read = &ucycom_stop_read,
|
||||
.ucom_start_write = &ucycom_start_write,
|
||||
.ucom_stop_write = &ucycom_stop_write,
|
||||
.ucom_poll = &ucycom_poll,
|
||||
};
|
||||
|
||||
static device_method_t ucycom_methods[] = {
|
||||
@ -578,3 +580,10 @@ ucycom_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ucycom_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct ucycom_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UCYCOM_N_TRANSFER);
|
||||
}
|
||||
|
@ -230,13 +230,13 @@ static void ufoma_start_read(struct ucom_softc *);
|
||||
static void ufoma_stop_read(struct ucom_softc *);
|
||||
static void ufoma_start_write(struct ucom_softc *);
|
||||
static void ufoma_stop_write(struct ucom_softc *);
|
||||
static void ufoma_poll(struct ucom_softc *ucom);
|
||||
|
||||
/*sysctl stuff*/
|
||||
static int ufoma_sysctl_support(SYSCTL_HANDLER_ARGS);
|
||||
static int ufoma_sysctl_current(SYSCTL_HANDLER_ARGS);
|
||||
static int ufoma_sysctl_open(SYSCTL_HANDLER_ARGS);
|
||||
|
||||
|
||||
static const struct usb_config
|
||||
ufoma_ctrl_config[UFOMA_CTRL_ENDPT_MAX] = {
|
||||
|
||||
@ -304,6 +304,7 @@ static const struct ucom_callback ufoma_callback = {
|
||||
.ucom_stop_read = &ufoma_stop_read,
|
||||
.ucom_start_write = &ufoma_start_write,
|
||||
.ucom_stop_write = &ufoma_stop_write,
|
||||
.ucom_poll = &ufoma_poll,
|
||||
};
|
||||
|
||||
static device_method_t ufoma_methods[] = {
|
||||
@ -1241,3 +1242,11 @@ static int ufoma_sysctl_open(SYSCTL_HANDLER_ARGS)
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
static void
|
||||
ufoma_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct ufoma_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_ctrl_xfer, UFOMA_CTRL_ENDPT_MAX);
|
||||
usbd_transfer_poll(sc->sc_bulk_xfer, UFOMA_BULK_ENDPT_MAX);
|
||||
}
|
||||
|
@ -156,6 +156,7 @@ static void uftdi_stop_read(struct ucom_softc *);
|
||||
static void uftdi_start_write(struct ucom_softc *);
|
||||
static void uftdi_stop_write(struct ucom_softc *);
|
||||
static uint8_t uftdi_8u232am_getrate(uint32_t, uint16_t *);
|
||||
static void uftdi_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config uftdi_config[UFTDI_N_TRANSFER] = {
|
||||
|
||||
@ -190,6 +191,7 @@ static const struct ucom_callback uftdi_callback = {
|
||||
.ucom_stop_read = &uftdi_stop_read,
|
||||
.ucom_start_write = &uftdi_start_write,
|
||||
.ucom_stop_write = &uftdi_stop_write,
|
||||
.ucom_poll = &uftdi_poll,
|
||||
};
|
||||
|
||||
static device_method_t uftdi_methods[] = {
|
||||
@ -808,3 +810,10 @@ uftdi_8u232am_getrate(uint32_t speed, uint16_t *rate)
|
||||
*rate = result;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
uftdi_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct uftdi_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UFTDI_N_TRANSFER);
|
||||
}
|
||||
|
@ -110,9 +110,9 @@ static void ugensa_start_read(struct ucom_softc *);
|
||||
static void ugensa_stop_read(struct ucom_softc *);
|
||||
static void ugensa_start_write(struct ucom_softc *);
|
||||
static void ugensa_stop_write(struct ucom_softc *);
|
||||
static void ugensa_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config
|
||||
ugensa_xfer_config[UGENSA_N_TRANSFER] = {
|
||||
static const struct usb_config ugensa_xfer_config[UGENSA_N_TRANSFER] = {
|
||||
|
||||
[UGENSA_BULK_DT_WR] = {
|
||||
.type = UE_BULK,
|
||||
@ -138,6 +138,7 @@ static const struct ucom_callback ugensa_callback = {
|
||||
.ucom_stop_read = &ugensa_stop_read,
|
||||
.ucom_start_write = &ugensa_start_write,
|
||||
.ucom_stop_write = &ugensa_stop_write,
|
||||
.ucom_poll = &ugensa_poll,
|
||||
};
|
||||
|
||||
static device_method_t ugensa_methods[] = {
|
||||
@ -369,3 +370,12 @@ ugensa_stop_write(struct ucom_softc *ucom)
|
||||
|
||||
usbd_transfer_stop(ssc->sc_xfer[UGENSA_BULK_DT_WR]);
|
||||
}
|
||||
|
||||
static void
|
||||
ugensa_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct ugensa_softc *sc = ucom->sc_parent;
|
||||
struct ugensa_sub_softc *ssc = sc->sc_sub + ucom->sc_portno;
|
||||
|
||||
usbd_transfer_poll(ssc->sc_xfer, UGENSA_N_TRANSFER);
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ static void uipaq_stop_write(struct ucom_softc *);
|
||||
static void uipaq_cfg_set_dtr(struct ucom_softc *, uint8_t);
|
||||
static void uipaq_cfg_set_rts(struct ucom_softc *, uint8_t);
|
||||
static void uipaq_cfg_set_break(struct ucom_softc *, uint8_t);
|
||||
static void uipaq_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config uipaq_config_data[UIPAQ_N_TRANSFER] = {
|
||||
|
||||
@ -152,6 +153,7 @@ static const struct ucom_callback uipaq_callback = {
|
||||
.ucom_stop_read = &uipaq_stop_read,
|
||||
.ucom_start_write = &uipaq_start_write,
|
||||
.ucom_stop_write = &uipaq_stop_write,
|
||||
.ucom_poll = &uipaq_poll,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1342,3 +1344,10 @@ uipaq_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
uipaq_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct uipaq_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UIPAQ_N_TRANSFER);
|
||||
}
|
||||
|
@ -142,6 +142,7 @@ static void umct_start_read(struct ucom_softc *);
|
||||
static void umct_stop_read(struct ucom_softc *);
|
||||
static void umct_start_write(struct ucom_softc *);
|
||||
static void umct_stop_write(struct ucom_softc *);
|
||||
static void umct_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config umct_config[UMCT_N_TRANSFER] = {
|
||||
|
||||
@ -186,6 +187,7 @@ static const struct ucom_callback umct_callback = {
|
||||
.ucom_stop_read = &umct_stop_read,
|
||||
.ucom_start_write = &umct_start_write,
|
||||
.ucom_stop_write = &umct_stop_write,
|
||||
.ucom_poll = &umct_poll,
|
||||
};
|
||||
|
||||
static const struct usb_device_id umct_devs[] = {
|
||||
@ -603,3 +605,10 @@ umct_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
umct_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct umct_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UMCT_N_TRANSFER);
|
||||
}
|
||||
|
@ -196,6 +196,7 @@ static void umodem_cfg_set_break(struct ucom_softc *, uint8_t);
|
||||
static void *umodem_get_desc(struct usb_attach_arg *, uint8_t, uint8_t);
|
||||
static usb_error_t umodem_set_comm_feature(struct usb_device *, uint8_t,
|
||||
uint16_t, uint16_t);
|
||||
static void umodem_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config umodem_config[UMODEM_N_TRANSFER] = {
|
||||
|
||||
@ -242,6 +243,7 @@ static const struct ucom_callback umodem_callback = {
|
||||
.ucom_stop_read = &umodem_stop_read,
|
||||
.ucom_start_write = &umodem_start_write,
|
||||
.ucom_stop_write = &umodem_stop_write,
|
||||
.ucom_poll = &umodem_poll,
|
||||
};
|
||||
|
||||
static device_method_t umodem_methods[] = {
|
||||
@ -810,3 +812,10 @@ umodem_detach(device_t dev)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
umodem_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct umodem_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UMODEM_N_TRANSFER);
|
||||
}
|
||||
|
@ -210,6 +210,7 @@ static void umoscom_start_read(struct ucom_softc *);
|
||||
static void umoscom_stop_read(struct ucom_softc *);
|
||||
static void umoscom_start_write(struct ucom_softc *);
|
||||
static void umoscom_stop_write(struct ucom_softc *);
|
||||
static void umoscom_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config umoscom_config_data[UMOSCOM_N_TRANSFER] = {
|
||||
|
||||
@ -257,6 +258,7 @@ static const struct ucom_callback umoscom_callback = {
|
||||
.ucom_stop_read = &umoscom_stop_read,
|
||||
.ucom_start_write = &umoscom_start_write,
|
||||
.ucom_stop_write = &umoscom_stop_write,
|
||||
.ucom_poll = &umoscom_poll,
|
||||
};
|
||||
|
||||
static device_method_t umoscom_methods[] = {
|
||||
@ -694,3 +696,10 @@ umoscom_intr_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
umoscom_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct umoscom_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UMOSCOM_N_TRANSFER);
|
||||
}
|
||||
|
@ -186,6 +186,7 @@ static void uplcom_start_write(struct ucom_softc *);
|
||||
static void uplcom_stop_write(struct ucom_softc *);
|
||||
static void uplcom_cfg_get_status(struct ucom_softc *, uint8_t *,
|
||||
uint8_t *);
|
||||
static void uplcom_poll(struct ucom_softc *ucom);
|
||||
|
||||
static device_probe_t uplcom_probe;
|
||||
static device_attach_t uplcom_attach;
|
||||
@ -239,6 +240,7 @@ static struct ucom_callback uplcom_callback = {
|
||||
.ucom_stop_read = &uplcom_stop_read,
|
||||
.ucom_start_write = &uplcom_start_write,
|
||||
.ucom_stop_write = &uplcom_stop_write,
|
||||
.ucom_poll = &uplcom_poll,
|
||||
};
|
||||
|
||||
#define USB_UPL(v,p,rl,rh,t) \
|
||||
@ -862,3 +864,10 @@ uplcom_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
uplcom_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct uplcom_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UPLCOM_N_TRANSFER);
|
||||
}
|
||||
|
@ -86,6 +86,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/callout.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/cons.h>
|
||||
#include <sys/kdb.h>
|
||||
|
||||
#include <dev/usb/usb.h>
|
||||
#include <dev/usb/usbdi.h>
|
||||
@ -98,14 +100,40 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <dev/usb/serial/usb_serial.h>
|
||||
|
||||
#include "opt_gdb.h"
|
||||
|
||||
SYSCTL_NODE(_hw_usb, OID_AUTO, ucom, CTLFLAG_RW, 0, "USB ucom");
|
||||
|
||||
#if USB_DEBUG
|
||||
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");
|
||||
#endif
|
||||
|
||||
#define UCOM_CONS_BUFSIZE 1024
|
||||
|
||||
static uint8_t ucom_cons_rx_buf[UCOM_CONS_BUFSIZE];
|
||||
static uint8_t ucom_cons_tx_buf[UCOM_CONS_BUFSIZE];
|
||||
|
||||
static unsigned int ucom_cons_rx_low = 0;
|
||||
static unsigned int ucom_cons_rx_high = 0;
|
||||
|
||||
static unsigned int ucom_cons_tx_low = 0;
|
||||
static unsigned int ucom_cons_tx_high = 0;
|
||||
|
||||
static int ucom_cons_unit = -1;
|
||||
static int ucom_cons_baud = 9600;
|
||||
static struct ucom_softc *ucom_cons_softc = NULL;
|
||||
|
||||
TUNABLE_INT("hw.usb.ucom.cons_unit", &ucom_cons_unit);
|
||||
SYSCTL_INT(_hw_usb_ucom, OID_AUTO, cons_unit, CTLFLAG_RW,
|
||||
&ucom_cons_unit, 0, "console unit number");
|
||||
|
||||
TUNABLE_INT("hw.usb.ucom.cons_baud", &ucom_cons_baud);
|
||||
SYSCTL_INT(_hw_usb_ucom, OID_AUTO, cons_baud, CTLFLAG_RW,
|
||||
&ucom_cons_baud, 0, "console baud rate");
|
||||
|
||||
static usb_proc_callback_t ucom_cfg_start_transfers;
|
||||
static usb_proc_callback_t ucom_cfg_open;
|
||||
static usb_proc_callback_t ucom_cfg_close;
|
||||
@ -121,6 +149,7 @@ static void ucom_queue_command(struct ucom_softc *,
|
||||
usb_proc_callback_t *, struct termios *pt,
|
||||
struct usb_proc_msg *t0, struct usb_proc_msg *t1);
|
||||
static void ucom_shutdown(struct ucom_softc *);
|
||||
static void ucom_ring(struct ucom_softc *, uint8_t);
|
||||
static void ucom_break(struct ucom_softc *, uint8_t);
|
||||
static void ucom_dtr(struct ucom_softc *, uint8_t);
|
||||
static void ucom_rts(struct ucom_softc *, uint8_t);
|
||||
@ -147,7 +176,7 @@ static struct ttydevsw ucom_class = {
|
||||
MODULE_DEPEND(ucom, usb, 1, 1, 1);
|
||||
MODULE_VERSION(ucom, 1);
|
||||
|
||||
#define UCOM_UNIT_MAX 0x1000 /* exclusive */
|
||||
#define UCOM_UNIT_MAX 0x200 /* exclusive */
|
||||
#define UCOM_SUB_UNIT_MAX 0x100 /* exclusive */
|
||||
|
||||
static uint8_t ucom_bitmap[(UCOM_UNIT_MAX + 7) / 8];
|
||||
@ -346,6 +375,29 @@ ucom_attach_tty(struct ucom_softc *sc, uint32_t sub_units)
|
||||
DPRINTF("ttycreate: %s\n", buf);
|
||||
cv_init(&sc->sc_cv, "ucom");
|
||||
|
||||
/* Check if this device should be a console */
|
||||
if ((ucom_cons_softc == NULL) &&
|
||||
(sc->sc_unit == ucom_cons_unit)) {
|
||||
|
||||
struct termios t;
|
||||
|
||||
ucom_cons_softc = sc;
|
||||
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.c_ispeed = ucom_cons_baud;
|
||||
t.c_ospeed = t.c_ispeed;
|
||||
t.c_cflag = CS8;
|
||||
|
||||
mtx_lock(ucom_cons_softc->sc_mtx);
|
||||
ucom_cons_rx_low = 0;
|
||||
ucom_cons_rx_high = 0;
|
||||
ucom_cons_tx_low = 0;
|
||||
ucom_cons_tx_high = 0;
|
||||
sc->sc_flag |= UCOM_FLAG_CONSOLE;
|
||||
ucom_open(ucom_cons_softc->sc_tty);
|
||||
ucom_param(ucom_cons_softc->sc_tty, &t);
|
||||
mtx_unlock(ucom_cons_softc->sc_mtx);
|
||||
}
|
||||
done:
|
||||
return (error);
|
||||
}
|
||||
@ -357,12 +409,18 @@ ucom_detach_tty(struct ucom_softc *sc)
|
||||
|
||||
DPRINTF("sc = %p, tp = %p\n", sc, sc->sc_tty);
|
||||
|
||||
if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
|
||||
mtx_lock(ucom_cons_softc->sc_mtx);
|
||||
ucom_close(ucom_cons_softc->sc_tty);
|
||||
mtx_unlock(ucom_cons_softc->sc_mtx);
|
||||
ucom_cons_softc = NULL;
|
||||
}
|
||||
|
||||
/* the config thread has been stopped when we get here */
|
||||
|
||||
mtx_lock(sc->sc_mtx);
|
||||
sc->sc_flag |= UCOM_FLAG_GONE;
|
||||
sc->sc_flag &= ~(UCOM_FLAG_HL_READY |
|
||||
UCOM_FLAG_LL_READY);
|
||||
sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_LL_READY);
|
||||
mtx_unlock(sc->sc_mtx);
|
||||
if (tp) {
|
||||
tty_lock(tp);
|
||||
@ -588,6 +646,8 @@ ucom_open(struct tty *tp)
|
||||
|
||||
ucom_modem(tp, SER_DTR | SER_RTS, 0);
|
||||
|
||||
ucom_ring(sc, 0);
|
||||
|
||||
ucom_break(sc, 0);
|
||||
|
||||
ucom_status_change(sc);
|
||||
@ -653,6 +713,16 @@ ucom_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
|
||||
DPRINTF("cmd = 0x%08lx\n", cmd);
|
||||
|
||||
switch (cmd) {
|
||||
#if 0
|
||||
case TIOCSRING:
|
||||
ucom_ring(sc, 1);
|
||||
error = 0;
|
||||
break;
|
||||
case TIOCCRING:
|
||||
ucom_ring(sc, 0);
|
||||
error = 0;
|
||||
break;
|
||||
#endif
|
||||
case TIOCSBRK:
|
||||
ucom_break(sc, 1);
|
||||
error = 0;
|
||||
@ -751,6 +821,8 @@ ucom_cfg_line_state(struct usb_proc_msg *_task)
|
||||
mask |= UCOM_LS_RTS;
|
||||
if (sc->sc_callback->ucom_cfg_set_break)
|
||||
mask |= UCOM_LS_BREAK;
|
||||
if (sc->sc_callback->ucom_cfg_set_ring)
|
||||
mask |= UCOM_LS_RING;
|
||||
|
||||
/* compute the bits we are to program */
|
||||
notch_bits = (sc->sc_pls_set & sc->sc_pls_clr) & mask;
|
||||
@ -773,6 +845,9 @@ ucom_cfg_line_state(struct usb_proc_msg *_task)
|
||||
if (notch_bits & UCOM_LS_BREAK)
|
||||
sc->sc_callback->ucom_cfg_set_break(sc,
|
||||
(prev_value & UCOM_LS_BREAK) ? 1 : 0);
|
||||
if (notch_bits & UCOM_LS_RING)
|
||||
sc->sc_callback->ucom_cfg_set_ring(sc,
|
||||
(prev_value & UCOM_LS_RING) ? 1 : 0);
|
||||
|
||||
/* set last value */
|
||||
if (any_bits & UCOM_LS_DTR)
|
||||
@ -784,6 +859,9 @@ ucom_cfg_line_state(struct usb_proc_msg *_task)
|
||||
if (any_bits & UCOM_LS_BREAK)
|
||||
sc->sc_callback->ucom_cfg_set_break(sc,
|
||||
(last_value & UCOM_LS_BREAK) ? 1 : 0);
|
||||
if (any_bits & UCOM_LS_RING)
|
||||
sc->sc_callback->ucom_cfg_set_ring(sc,
|
||||
(last_value & UCOM_LS_RING) ? 1 : 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -810,6 +888,17 @@ ucom_line_state(struct ucom_softc *sc,
|
||||
&sc->sc_line_state_task[1].hdr);
|
||||
}
|
||||
|
||||
static void
|
||||
ucom_ring(struct ucom_softc *sc, uint8_t onoff)
|
||||
{
|
||||
DPRINTF("onoff = %d\n", onoff);
|
||||
|
||||
if (onoff)
|
||||
ucom_line_state(sc, UCOM_LS_RING, 0);
|
||||
else
|
||||
ucom_line_state(sc, 0, UCOM_LS_RING);
|
||||
}
|
||||
|
||||
static void
|
||||
ucom_break(struct ucom_softc *sc, uint8_t onoff)
|
||||
{
|
||||
@ -895,6 +984,9 @@ ucom_status_change(struct ucom_softc *sc)
|
||||
{
|
||||
mtx_assert(sc->sc_mtx, MA_OWNED);
|
||||
|
||||
if (sc->sc_flag & UCOM_FLAG_CONSOLE)
|
||||
return; /* not supported */
|
||||
|
||||
if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
|
||||
return;
|
||||
}
|
||||
@ -1033,6 +1125,38 @@ ucom_get_data(struct ucom_softc *sc, struct usb_page_cache *pc,
|
||||
|
||||
mtx_assert(sc->sc_mtx, MA_OWNED);
|
||||
|
||||
if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
|
||||
unsigned int temp;
|
||||
|
||||
/* get total TX length */
|
||||
|
||||
temp = ucom_cons_tx_high - ucom_cons_tx_low;
|
||||
temp %= UCOM_CONS_BUFSIZE;
|
||||
|
||||
/* limit TX length */
|
||||
|
||||
if (temp > (UCOM_CONS_BUFSIZE - ucom_cons_tx_low))
|
||||
temp = (UCOM_CONS_BUFSIZE - ucom_cons_tx_low);
|
||||
|
||||
if (temp > len)
|
||||
temp = len;
|
||||
|
||||
/* copy in data */
|
||||
|
||||
usbd_copy_in(pc, offset, ucom_cons_tx_buf + ucom_cons_tx_low, temp);
|
||||
|
||||
/* update counters */
|
||||
|
||||
ucom_cons_tx_low += temp;
|
||||
ucom_cons_tx_low %= UCOM_CONS_BUFSIZE;
|
||||
|
||||
/* store actual length */
|
||||
|
||||
*actlen = temp;
|
||||
|
||||
return (temp ? 1 : 0);
|
||||
}
|
||||
|
||||
if (tty_gone(tp) ||
|
||||
!(sc->sc_flag & UCOM_FLAG_GP_DATA)) {
|
||||
actlen[0] = 0;
|
||||
@ -1080,6 +1204,34 @@ ucom_put_data(struct ucom_softc *sc, struct usb_page_cache *pc,
|
||||
|
||||
mtx_assert(sc->sc_mtx, MA_OWNED);
|
||||
|
||||
if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
|
||||
unsigned int temp;
|
||||
|
||||
/* get maximum RX length */
|
||||
|
||||
temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_rx_high + ucom_cons_rx_low;
|
||||
temp %= UCOM_CONS_BUFSIZE;
|
||||
|
||||
/* limit RX length */
|
||||
|
||||
if (temp > (UCOM_CONS_BUFSIZE - ucom_cons_rx_high))
|
||||
temp = (UCOM_CONS_BUFSIZE - ucom_cons_rx_high);
|
||||
|
||||
if (temp > len)
|
||||
temp = len;
|
||||
|
||||
/* copy out data */
|
||||
|
||||
usbd_copy_out(pc, offset, ucom_cons_rx_buf + ucom_cons_rx_high, temp);
|
||||
|
||||
/* update counters */
|
||||
|
||||
ucom_cons_rx_high += temp;
|
||||
ucom_cons_rx_high %= UCOM_CONS_BUFSIZE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (tty_gone(tp))
|
||||
return; /* multiport device polling */
|
||||
|
||||
@ -1136,3 +1288,138 @@ ucom_free(void *xsc)
|
||||
cv_signal(&sc->sc_cv);
|
||||
mtx_unlock(sc->sc_mtx);
|
||||
}
|
||||
|
||||
static cn_probe_t ucom_cnprobe;
|
||||
static cn_init_t ucom_cninit;
|
||||
static cn_term_t ucom_cnterm;
|
||||
static cn_getc_t ucom_cngetc;
|
||||
static cn_putc_t ucom_cnputc;
|
||||
|
||||
CONSOLE_DRIVER(ucom);
|
||||
|
||||
static void
|
||||
ucom_cnprobe(struct consdev *cp)
|
||||
{
|
||||
cp->cn_pri = CN_NORMAL;
|
||||
}
|
||||
|
||||
static void
|
||||
ucom_cninit(struct consdev *cp)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
ucom_cnterm(struct consdev *cp)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
ucom_cngetc(struct consdev *cd)
|
||||
{
|
||||
struct ucom_softc *sc = ucom_cons_softc;
|
||||
int c;
|
||||
|
||||
if (sc == NULL)
|
||||
return (-1);
|
||||
|
||||
mtx_lock(sc->sc_mtx);
|
||||
|
||||
if (ucom_cons_rx_low != ucom_cons_rx_high) {
|
||||
c = ucom_cons_rx_buf[ucom_cons_rx_low];
|
||||
ucom_cons_rx_low ++;
|
||||
ucom_cons_rx_low %= UCOM_CONS_BUFSIZE;
|
||||
} else {
|
||||
c = -1;
|
||||
}
|
||||
|
||||
/* start USB transfers */
|
||||
ucom_outwakeup(sc->sc_tty);
|
||||
|
||||
mtx_unlock(sc->sc_mtx);
|
||||
|
||||
/* poll if necessary */
|
||||
if (kdb_active && sc->sc_callback->ucom_poll)
|
||||
(sc->sc_callback->ucom_poll) (sc);
|
||||
|
||||
return (c);
|
||||
}
|
||||
|
||||
static void
|
||||
ucom_cnputc(struct consdev *cd, int c)
|
||||
{
|
||||
struct ucom_softc *sc = ucom_cons_softc;
|
||||
unsigned int temp;
|
||||
|
||||
if (sc == NULL)
|
||||
return;
|
||||
|
||||
repeat:
|
||||
|
||||
mtx_lock(sc->sc_mtx);
|
||||
|
||||
/* compute maximum TX length */
|
||||
|
||||
temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_tx_high + ucom_cons_tx_low;
|
||||
temp %= UCOM_CONS_BUFSIZE;
|
||||
|
||||
if (temp) {
|
||||
ucom_cons_tx_buf[ucom_cons_tx_high] = c;
|
||||
ucom_cons_tx_high ++;
|
||||
ucom_cons_tx_high %= UCOM_CONS_BUFSIZE;
|
||||
}
|
||||
|
||||
/* start USB transfers */
|
||||
ucom_outwakeup(sc->sc_tty);
|
||||
|
||||
mtx_unlock(sc->sc_mtx);
|
||||
|
||||
/* poll if necessary */
|
||||
if (kdb_active && sc->sc_callback->ucom_poll) {
|
||||
(sc->sc_callback->ucom_poll) (sc);
|
||||
/* simple flow control */
|
||||
if (temp == 0)
|
||||
goto repeat;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(GDB)
|
||||
|
||||
#include <gdb/gdb.h>
|
||||
|
||||
static gdb_probe_f ucom_gdbprobe;
|
||||
static gdb_init_f ucom_gdbinit;
|
||||
static gdb_term_f ucom_gdbterm;
|
||||
static gdb_getc_f ucom_gdbgetc;
|
||||
static gdb_putc_f ucom_gdbputc;
|
||||
|
||||
GDB_DBGPORT(sio, ucom_gdbprobe, ucom_gdbinit, ucom_gdbterm, ucom_gdbgetc, ucom_gdbputc);
|
||||
|
||||
static int
|
||||
ucom_gdbprobe(void)
|
||||
{
|
||||
return ((ucom_cons_softc != NULL) ? 0 : -1);
|
||||
}
|
||||
|
||||
static void
|
||||
ucom_gdbinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
ucom_gdbterm(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
ucom_gdbputc(int c)
|
||||
{
|
||||
ucom_cnputc(NULL, c);
|
||||
}
|
||||
|
||||
static int
|
||||
ucom_gdbgetc(void)
|
||||
{
|
||||
return (ucom_cngetc(NULL));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -94,6 +94,7 @@ struct ucom_callback {
|
||||
void (*ucom_cfg_set_dtr) (struct ucom_softc *, uint8_t);
|
||||
void (*ucom_cfg_set_rts) (struct ucom_softc *, uint8_t);
|
||||
void (*ucom_cfg_set_break) (struct ucom_softc *, uint8_t);
|
||||
void (*ucom_cfg_set_ring) (struct ucom_softc *, uint8_t);
|
||||
void (*ucom_cfg_param) (struct ucom_softc *, struct termios *);
|
||||
void (*ucom_cfg_open) (struct ucom_softc *);
|
||||
void (*ucom_cfg_close) (struct ucom_softc *);
|
||||
@ -105,6 +106,7 @@ struct ucom_callback {
|
||||
void (*ucom_start_write) (struct ucom_softc *);
|
||||
void (*ucom_stop_write) (struct ucom_softc *);
|
||||
void (*ucom_tty_name) (struct ucom_softc *, char *pbuf, uint16_t buflen, uint16_t local_subunit);
|
||||
void (*ucom_poll) (struct ucom_softc *);
|
||||
};
|
||||
|
||||
/* Line status register */
|
||||
@ -162,13 +164,14 @@ struct ucom_softc {
|
||||
uint32_t sc_unit;
|
||||
uint32_t sc_local_unit;
|
||||
uint16_t sc_portno;
|
||||
uint8_t sc_flag;
|
||||
uint16_t sc_flag;
|
||||
#define UCOM_FLAG_RTS_IFLOW 0x01 /* use RTS input flow control */
|
||||
#define UCOM_FLAG_GONE 0x02 /* the device is gone */
|
||||
#define UCOM_FLAG_ATTACHED 0x04 /* set if attached */
|
||||
#define UCOM_FLAG_GP_DATA 0x08 /* set if get and put data is possible */
|
||||
#define UCOM_FLAG_LL_READY 0x20 /* set if low layer is ready */
|
||||
#define UCOM_FLAG_HL_READY 0x40 /* set if high layer is ready */
|
||||
#define UCOM_FLAG_CONSOLE 0x80 /* set if device is a console */
|
||||
uint8_t sc_lsr;
|
||||
uint8_t sc_msr;
|
||||
uint8_t sc_mcr;
|
||||
@ -180,6 +183,7 @@ struct ucom_softc {
|
||||
#define UCOM_LS_DTR 0x01
|
||||
#define UCOM_LS_RTS 0x02
|
||||
#define UCOM_LS_BREAK 0x04
|
||||
#define UCOM_LS_RING 0x08
|
||||
};
|
||||
|
||||
#define ucom_cfg_do_request(udev,com,req,ptr,flags,timo) \
|
||||
|
@ -135,6 +135,7 @@ static void uslcom_start_read(struct ucom_softc *);
|
||||
static void uslcom_stop_read(struct ucom_softc *);
|
||||
static void uslcom_start_write(struct ucom_softc *);
|
||||
static void uslcom_stop_write(struct ucom_softc *);
|
||||
static void uslcom_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config uslcom_config[USLCOM_N_TRANSFER] = {
|
||||
|
||||
@ -170,6 +171,7 @@ static struct ucom_callback uslcom_callback = {
|
||||
.ucom_stop_read = &uslcom_stop_read,
|
||||
.ucom_start_write = &uslcom_start_write,
|
||||
.ucom_stop_write = &uslcom_stop_write,
|
||||
.ucom_poll = &uslcom_poll,
|
||||
};
|
||||
|
||||
static const struct usb_device_id uslcom_devs[] = {
|
||||
@ -562,3 +564,10 @@ uslcom_stop_write(struct ucom_softc *ucom)
|
||||
|
||||
usbd_transfer_stop(sc->sc_xfer[USLCOM_BULK_DT_WR]);
|
||||
}
|
||||
|
||||
static void
|
||||
uslcom_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct uslcom_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, USLCOM_N_TRANSFER);
|
||||
}
|
||||
|
@ -185,6 +185,7 @@ static void uvscom_cfg_get_status(struct ucom_softc *, uint8_t *,
|
||||
uint8_t *);
|
||||
static void uvscom_cfg_write(struct uvscom_softc *, uint8_t, uint16_t);
|
||||
static uint16_t uvscom_cfg_read_status(struct uvscom_softc *);
|
||||
static void uvscom_poll(struct ucom_softc *ucom);
|
||||
|
||||
static const struct usb_config uvscom_config[UVSCOM_N_TRANSFER] = {
|
||||
|
||||
@ -230,6 +231,7 @@ static const struct ucom_callback uvscom_callback = {
|
||||
.ucom_stop_read = &uvscom_stop_read,
|
||||
.ucom_start_write = &uvscom_start_write,
|
||||
.ucom_stop_write = &uvscom_stop_write,
|
||||
.ucom_poll = &uvscom_poll,
|
||||
};
|
||||
|
||||
static const struct usb_device_id uvscom_devs[] = {
|
||||
@ -734,3 +736,10 @@ uvscom_cfg_read_status(struct uvscom_softc *sc)
|
||||
}
|
||||
return (data[0] | (data[1] << 8));
|
||||
}
|
||||
|
||||
static void
|
||||
uvscom_poll(struct ucom_softc *ucom)
|
||||
{
|
||||
struct uvscom_softc *sc = ucom->sc_parent;
|
||||
usbd_transfer_poll(sc->sc_xfer, UVSCOM_N_TRANSFER);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user