- Simplify the way unit/subunit allocation is done in ucom.

- hw.usb.ucom.cons_unit is now split into
  hw.usb.ucom.cons_unit/...cons_subunit.

Note: The tunable/sysctl hw.usb.ucom.cons_unit needs to be reviewed if

a) a console was defined a USB serial devices, and a USB device with
more than 1 subunit is present, and this device is attached before the
device functioning as a console

or

b) a console was defined on a USB device with more than 1 subunit

Reviewed by:	hps
MFC after:	2 weeks
This commit is contained in:
Nick Hibma 2010-11-03 21:50:49 +00:00
parent 770c6c3310
commit 015bb88ff2
20 changed files with 119 additions and 157 deletions

View File

@ -633,11 +633,10 @@ uhso_attach(device_t self)
ht->ht_name[0] = 0;
if (sc->sc_ttys == 1)
snprintf(ht->ht_name, 32, "cuaU%d", ucom->sc_unit);
snprintf(ht->ht_name, 32, "cuaU%d", ucom->sc_super->sc_unit);
else {
snprintf(ht->ht_name, 32, "cuaU%d.%d",
ucom->sc_unit - ucom->sc_local_unit,
ucom->sc_local_unit);
ucom->sc_super->sc_unit, ucom->sc_subunit);
}
desc = uhso_port_type[port];
@ -666,7 +665,7 @@ uhso_detach(device_t self)
usbd_transfer_unsetup(sc->sc_xfer, 3);
usbd_transfer_unsetup(sc->sc_ctrl_xfer, UHSO_CTRL_MAX);
if (sc->sc_ttys > 0) {
ucom_detach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_ttys);
ucom_detach(&sc->sc_super_ucom, sc->sc_ucom);
for (i = 0; i < sc->sc_ttys; i++) {
if (sc->sc_tty[i].ht_muxport != -1) {
@ -1448,11 +1447,11 @@ uhso_ucom_start_read(struct ucom_softc *ucom)
{
struct uhso_softc *sc = ucom->sc_parent;
UHSO_DPRINTF(3, "unit=%d, local_unit=%d\n",
ucom->sc_unit, ucom->sc_local_unit);
UHSO_DPRINTF(3, "unit=%d, subunit=%d\n",
ucom->sc_super->sc_unit, ucom->sc_subunit);
if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
sc->sc_tty[ucom->sc_local_unit].ht_open = 1;
sc->sc_tty[ucom->sc_subunit].ht_open = 1;
usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
}
else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
@ -1470,9 +1469,9 @@ uhso_ucom_stop_read(struct ucom_softc *ucom)
struct uhso_softc *sc = ucom->sc_parent;
if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
sc->sc_tty[ucom->sc_local_unit].ht_open = 0;
sc->sc_tty[ucom->sc_subunit].ht_open = 0;
usbd_transfer_stop(
sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_READ]);
sc->sc_tty[ucom->sc_subunit].ht_xfer[UHSO_CTRL_READ]);
}
else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
sc->sc_tty[0].ht_open = 0;
@ -1488,15 +1487,15 @@ uhso_ucom_start_write(struct ucom_softc *ucom)
struct uhso_softc *sc = ucom->sc_parent;
if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
UHSO_DPRINTF(3, "local unit %d\n", ucom->sc_local_unit);
UHSO_DPRINTF(3, "local unit %d\n", ucom->sc_subunit);
usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
usbd_xfer_set_priv(
sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_WRITE],
&sc->sc_tty[ucom->sc_local_unit]);
sc->sc_tty[ucom->sc_subunit].ht_xfer[UHSO_CTRL_WRITE],
&sc->sc_tty[ucom->sc_subunit]);
usbd_transfer_start(
sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_WRITE]);
sc->sc_tty[ucom->sc_subunit].ht_xfer[UHSO_CTRL_WRITE]);
}
else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
@ -1511,7 +1510,7 @@ uhso_ucom_stop_write(struct ucom_softc *ucom)
if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
usbd_transfer_stop(
sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_WRITE]);
sc->sc_tty[ucom->sc_subunit].ht_xfer[UHSO_CTRL_WRITE]);
}
else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
usbd_transfer_stop(sc->sc_xfer[UHSO_BULK_ENDPT_WRITE]);

View File

@ -831,15 +831,15 @@ static int
u3g_detach(device_t dev)
{
struct u3g_softc *sc = device_get_softc(dev);
uint8_t m;
uint8_t subunit;
DPRINTF("sc=%p\n", sc);
/* NOTE: It is not dangerous to detach more ports than attached! */
ucom_detach(&sc->sc_super_ucom, sc->sc_ucom, U3G_MAXPORTS);
ucom_detach(&sc->sc_super_ucom, sc->sc_ucom);
for (m = 0; m != U3G_MAXPORTS; m++)
usbd_transfer_unsetup(sc->sc_xfer[m], U3G_N_TRANSFER);
for (subunit = 0; subunit != U3G_MAXPORTS; subunit++)
usbd_transfer_unsetup(sc->sc_xfer[subunit], U3G_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);
return (0);
@ -851,7 +851,7 @@ u3g_start_read(struct ucom_softc *ucom)
struct u3g_softc *sc = ucom->sc_parent;
/* start read endpoint */
usbd_transfer_start(sc->sc_xfer[ucom->sc_local_unit][U3G_BULK_RD]);
usbd_transfer_start(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_RD]);
return;
}
@ -861,7 +861,7 @@ u3g_stop_read(struct ucom_softc *ucom)
struct u3g_softc *sc = ucom->sc_parent;
/* stop read endpoint */
usbd_transfer_stop(sc->sc_xfer[ucom->sc_local_unit][U3G_BULK_RD]);
usbd_transfer_stop(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_RD]);
return;
}
@ -870,7 +870,7 @@ u3g_start_write(struct ucom_softc *ucom)
{
struct u3g_softc *sc = ucom->sc_parent;
usbd_transfer_start(sc->sc_xfer[ucom->sc_local_unit][U3G_BULK_WR]);
usbd_transfer_start(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_WR]);
return;
}
@ -879,7 +879,7 @@ u3g_stop_write(struct ucom_softc *ucom)
{
struct u3g_softc *sc = ucom->sc_parent;
usbd_transfer_stop(sc->sc_xfer[ucom->sc_local_unit][U3G_BULK_WR]);
usbd_transfer_stop(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_WR]);
return;
}

View File

@ -239,7 +239,7 @@ uark_detach(device_t dev)
{
struct uark_softc *sc = device_get_softc(dev);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -345,7 +345,7 @@ ubsa_detach(device_t dev)
DPRINTF("sc=%p\n", sc);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UBSA_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -317,7 +317,7 @@ ubser_detach(device_t dev)
DPRINTF("\n");
ucom_detach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_numser);
ucom_detach(&sc->sc_super_ucom, sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UBSER_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -368,7 +368,7 @@ uchcom_detach(device_t dev)
DPRINTFN(11, "\n");
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UCHCOM_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -294,7 +294,7 @@ ucycom_detach(device_t dev)
{
struct ucycom_softc *sc = device_get_softc(dev);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UCYCOM_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -466,7 +466,7 @@ ufoma_attach(device_t dev)
CTLFLAG_RW|CTLTYPE_STRING, sc, 0, ufoma_sysctl_open,
"A", "Mode to transit when port is opened");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "comunit",
CTLFLAG_RD, &(sc->sc_ucom.sc_unit), 0,
CTLFLAG_RD, &(sc->sc_super_ucom.sc_unit), 0,
"Unit number as USB serial");
return (0); /* success */
@ -481,7 +481,7 @@ ufoma_detach(device_t dev)
{
struct ufoma_softc *sc = device_get_softc(dev);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_ctrl_xfer, UFOMA_CTRL_ENDPT_MAX);
usbd_transfer_unsetup(sc->sc_bulk_xfer, UFOMA_BULK_ENDPT_MAX);

View File

@ -344,7 +344,7 @@ uftdi_detach(device_t dev)
{
struct uftdi_softc *sc = device_get_softc(dev);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UFTDI_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -260,7 +260,7 @@ ugensa_detach(device_t dev)
struct ugensa_softc *sc = device_get_softc(dev);
uint8_t x;
ucom_detach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_niface);
ucom_detach(&sc->sc_super_ucom, sc->sc_ucom);
for (x = 0; x < sc->sc_niface; x++) {
usbd_transfer_unsetup(sc->sc_sub[x].sc_xfer, UGENSA_N_TRANSFER);

View File

@ -1173,7 +1173,7 @@ uipaq_detach(device_t dev)
{
struct uipaq_softc *sc = device_get_softc(dev);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UIPAQ_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -309,7 +309,7 @@ umct_detach(device_t dev)
{
struct umct_softc *sc = device_get_softc(dev);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UMCT_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -816,7 +816,7 @@ umodem_detach(device_t dev)
DPRINTF("sc=%p\n", sc);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UMODEM_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -351,7 +351,7 @@ umoscom_detach(device_t dev)
{
struct umoscom_softc *sc = device_get_softc(dev);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UMOSCOM_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -459,7 +459,7 @@ uplcom_detach(device_t dev)
DPRINTF("sc=%p\n", sc);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UPLCOM_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -123,13 +123,16 @@ 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_subunit = 0;
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_subunit", &ucom_cons_subunit);
SYSCTL_INT(_hw_usb_ucom, OID_AUTO, cons_subunit, CTLFLAG_RW,
&ucom_cons_subunit, 0, "console subunit 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");
@ -141,9 +144,9 @@ static usb_proc_callback_t ucom_cfg_line_state;
static usb_proc_callback_t ucom_cfg_status_change;
static usb_proc_callback_t ucom_cfg_param;
static uint8_t ucom_units_alloc(uint32_t, uint32_t *);
static void ucom_units_free(uint32_t, uint32_t);
static int ucom_attach_tty(struct ucom_softc *, uint32_t);
static int ucom_unit_alloc(void);
static void ucom_unit_free(int);
static int ucom_attach_tty(struct ucom_super_softc *, struct ucom_softc *);
static void ucom_detach_tty(struct ucom_softc *);
static void ucom_queue_command(struct ucom_softc *,
usb_proc_callback_t *, struct termios *pt,
@ -176,84 +179,52 @@ static struct ttydevsw ucom_class = {
MODULE_DEPEND(ucom, usb, 1, 1, 1);
MODULE_VERSION(ucom, 1);
#define UCOM_UNIT_MAX 0x200 /* exclusive */
#define UCOM_SUB_UNIT_MAX 0x100 /* exclusive */
#define UCOM_UNIT_MAX 128 /* limits size of ucom_bitmap */
static uint8_t ucom_bitmap[(UCOM_UNIT_MAX + 7) / 8];
static struct mtx ucom_bitmap_mtx;
MTX_SYSINIT(ucom_bitmap_mtx, &ucom_bitmap_mtx, "ucom bitmap", MTX_DEF);
static uint8_t
ucom_units_alloc(uint32_t sub_units, uint32_t *p_root_unit)
/*
* Mark a unit number (the X in cuaUX) as in use.
*
* Note that devices using a different naming scheme (see ucom_tty_name()
* callback) still use this unit allocation.
*/
static int
ucom_unit_alloc(void)
{
uint32_t n;
uint32_t o;
uint32_t x;
uint32_t max = UCOM_UNIT_MAX - (UCOM_UNIT_MAX % sub_units);
uint8_t error = 1;
int unit;
mtx_lock(&ucom_bitmap_mtx);
for (n = 0; n < max; n += sub_units) {
/* check for free consecutive bits */
for (o = 0; o < sub_units; o++) {
x = n + o;
if (ucom_bitmap[x / 8] & (1 << (x % 8))) {
goto skip;
}
}
/* allocate */
for (o = 0; o < sub_units; o++) {
x = n + o;
ucom_bitmap[x / 8] |= (1 << (x % 8));
}
error = 0;
break;
skip: ;
}
for (unit = 0; unit < UCOM_UNIT_MAX; unit++)
if ((ucom_bitmap[unit / 8] & (1 << (unit % 8))) == 0)
break;
mtx_unlock(&ucom_bitmap_mtx);
/*
* Always set the variable pointed to by "p_root_unit" so that
* the compiler does not think that it is used uninitialised:
*/
*p_root_unit = n;
return (error);
if (unit == UCOM_UNIT_MAX)
return -1;
else
return unit;
}
/*
* Mark the unit number as not in use.
*/
static void
ucom_units_free(uint32_t root_unit, uint32_t sub_units)
ucom_unit_free(int unit)
{
uint32_t x;
mtx_lock(&ucom_bitmap_mtx);
while (sub_units--) {
x = root_unit + sub_units;
ucom_bitmap[x / 8] &= ~(1 << (x % 8));
}
ucom_bitmap[unit / 8] &= ~(1 << (unit % 8));
mtx_unlock(&ucom_bitmap_mtx);
}
/*
* "N" sub_units are setup at a time. All sub-units will
* be given sequential unit numbers. The number of
* sub-units can be used to differentiate among
* different types of devices.
* Setup a group of one or more serial ports.
*
* The mutex pointed to by "mtx" is applied before all
* callbacks are called back. Also "mtx" must be applied
@ -261,47 +232,47 @@ ucom_units_free(uint32_t root_unit, uint32_t sub_units)
*/
int
ucom_attach(struct ucom_super_softc *ssc, struct ucom_softc *sc,
uint32_t sub_units, void *parent,
uint32_t subunits, void *parent,
const struct ucom_callback *callback, struct mtx *mtx)
{
uint32_t n;
uint32_t root_unit;
uint32_t subunit;
int error = 0;
if ((sc == NULL) ||
(sub_units == 0) ||
(sub_units > UCOM_SUB_UNIT_MAX) ||
(subunits == 0) ||
(callback == NULL)) {
return (EINVAL);
}
/* XXX unit management does not really belong here */
if (ucom_units_alloc(sub_units, &root_unit)) {
ssc->sc_unit = ucom_unit_alloc();
if (ssc->sc_unit == -1)
return (ENOMEM);
}
error = usb_proc_create(&ssc->sc_tq, mtx, "ucom", USB_PRI_MED);
if (error) {
ucom_units_free(root_unit, sub_units);
ucom_unit_free(ssc->sc_unit);
return (error);
}
ssc->sc_subunits = subunits;
for (n = 0; n != sub_units; n++, sc++) {
sc->sc_unit = root_unit + n;
sc->sc_local_unit = n;
sc->sc_super = ssc;
sc->sc_mtx = mtx;
sc->sc_parent = parent;
sc->sc_callback = callback;
for (subunit = 0; subunit != ssc->sc_subunits; subunit++) {
sc[subunit].sc_subunit = subunit;
sc[subunit].sc_super = ssc;
sc[subunit].sc_mtx = mtx;
sc[subunit].sc_parent = parent;
sc[subunit].sc_callback = callback;
error = ucom_attach_tty(sc, sub_units);
error = ucom_attach_tty(ssc, &sc[subunit]);
if (error) {
ucom_detach(ssc, sc - n, n);
ucom_units_free(root_unit + n, sub_units - n);
ucom_detach(ssc, &sc[0]);
return (error);
}
sc->sc_flag |= UCOM_FLAG_ATTACHED;
sc[subunit].sc_flag |= UCOM_FLAG_ATTACHED;
}
DPRINTF("tp = %p, unit = %d, subunits = %d, device name subunit 0 = %s\n",
sc->sc_tty, ssc->sc_unit, ssc->sc_subunits, sc[0].sc_devname);
return (0);
}
@ -310,62 +281,50 @@ ucom_attach(struct ucom_super_softc *ssc, struct ucom_softc *sc,
* the structure pointed to by "ssc" and "sc" is zero.
*/
void
ucom_detach(struct ucom_super_softc *ssc, struct ucom_softc *sc,
uint32_t sub_units)
ucom_detach(struct ucom_super_softc *ssc, struct ucom_softc *sc)
{
uint32_t n;
uint32_t subunit;
usb_proc_drain(&ssc->sc_tq);
for (n = 0; n != sub_units; n++, sc++) {
if (sc->sc_flag & UCOM_FLAG_ATTACHED) {
for (subunit = 0; subunit <= ssc->sc_subunits; subunit++) {
if (sc[subunit].sc_flag & UCOM_FLAG_ATTACHED) {
ucom_detach_tty(sc);
ucom_detach_tty(&sc[subunit]);
ucom_units_free(sc->sc_unit, 1);
/* avoid duplicate detach: */
sc->sc_flag &= ~UCOM_FLAG_ATTACHED;
/* avoid duplicate detach */
sc[subunit].sc_flag &= ~UCOM_FLAG_ATTACHED;
}
}
ucom_unit_free(ssc->sc_unit);
usb_proc_free(&ssc->sc_tq);
}
static int
ucom_attach_tty(struct ucom_softc *sc, uint32_t sub_units)
ucom_attach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc)
{
struct tty *tp;
int error = 0;
char buf[32]; /* temporary TTY device name buffer */
char buf[10]; /* temporary TTY device name buffer */
tp = tty_alloc_mutex(&ucom_class, sc, sc->sc_mtx);
if (tp == NULL) {
error = ENOMEM;
goto done;
}
DPRINTF("tp = %p, unit = %d\n", tp, sc->sc_unit);
buf[0] = 0; /* set some default value */
if (tp == NULL)
return (ENOMEM);
/* Check if the client has a custom TTY name */
buf[0] = '\0';
if (sc->sc_callback->ucom_tty_name) {
sc->sc_callback->ucom_tty_name(sc, buf,
sizeof(buf), sc->sc_local_unit);
sizeof(buf), ssc->sc_unit, sc->sc_subunit);
}
if (buf[0] == 0) {
/* Use default TTY name */
if (sub_units > 1) {
if (ssc->sc_subunits > 1) {
/* multiple modems in one */
if (snprintf(buf, sizeof(buf), "U%u.%u",
sc->sc_unit - sc->sc_local_unit,
sc->sc_local_unit)) {
/* ignore */
}
snprintf(buf, sizeof(buf), "U%u.%u",
ssc->sc_unit, sc->sc_subunit);
} else {
/* single modem */
if (snprintf(buf, sizeof(buf), "U%u", sc->sc_unit)) {
/* ignore */
}
snprintf(buf, sizeof(buf), "U%u", ssc->sc_unit);
}
}
tty_makedev(tp, NULL, "%s", buf);
@ -377,10 +336,12 @@ ucom_attach_tty(struct ucom_softc *sc, uint32_t sub_units)
/* Check if this device should be a console */
if ((ucom_cons_softc == NULL) &&
(sc->sc_unit == ucom_cons_unit)) {
(ssc->sc_unit == ucom_cons_unit) &&
(sc->sc_subunit == ucom_cons_subunit)) {
struct termios t;
DPRINTF("unit %d subunit %d is console", ssc->sc_unit, sc->sc_subunit);
ucom_cons_softc = sc;
memset(&t, 0, sizeof(t));
@ -398,8 +359,8 @@ ucom_attach_tty(struct ucom_softc *sc, uint32_t sub_units)
ucom_param(ucom_cons_softc->sc_tty, &t);
mtx_unlock(ucom_cons_softc->sc_mtx);
}
done:
return (error);
return (0);
}
static void
@ -412,6 +373,7 @@ ucom_detach_tty(struct ucom_softc *sc)
if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
mtx_lock(ucom_cons_softc->sc_mtx);
ucom_close(ucom_cons_softc->sc_tty);
sc->sc_flag &= ~UCOM_FLAG_CONSOLE;
mtx_unlock(ucom_cons_softc->sc_mtx);
ucom_cons_softc = NULL;
}

View File

@ -104,7 +104,7 @@ struct ucom_callback {
void (*ucom_stop_read) (struct ucom_softc *);
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_tty_name) (struct ucom_softc *, char *pbuf, uint16_t buflen, uint16_t unit, uint16_t subunit);
void (*ucom_poll) (struct ucom_softc *);
};
@ -132,6 +132,8 @@ struct ucom_param_task {
struct ucom_super_softc {
struct usb_process sc_tq;
uint32_t sc_unit;
uint32_t sc_subunits;
};
struct ucom_softc {
@ -158,10 +160,10 @@ struct ucom_softc {
const struct ucom_callback *sc_callback;
struct ucom_super_softc *sc_super;
struct tty *sc_tty;
char sc_devname[10];
struct mtx *sc_mtx;
void *sc_parent;
uint32_t sc_unit;
uint32_t sc_local_unit;
uint32_t sc_subunit;
uint16_t sc_portno;
uint16_t sc_flag;
#define UCOM_FLAG_RTS_IFLOW 0x01 /* use RTS input flow control */
@ -191,8 +193,7 @@ struct ucom_softc {
int ucom_attach(struct ucom_super_softc *,
struct ucom_softc *, uint32_t, void *,
const struct ucom_callback *callback, struct mtx *);
void ucom_detach(struct ucom_super_softc *,
struct ucom_softc *, uint32_t);
void ucom_detach(struct ucom_super_softc *, struct ucom_softc *);
void ucom_status_change(struct ucom_softc *);
uint8_t ucom_get_data(struct ucom_softc *, struct usb_page_cache *,
uint32_t, uint32_t, uint32_t *);

View File

@ -338,7 +338,7 @@ uslcom_detach(device_t dev)
DPRINTF("sc=%p\n", sc);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, USLCOM_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -361,7 +361,7 @@ uvisor_detach(device_t dev)
DPRINTF("sc=%p\n", sc);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UVISOR_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);

View File

@ -345,7 +345,7 @@ uvscom_detach(device_t dev)
if (sc->sc_xfer[UVSCOM_INTR_DT_RD])
usbd_transfer_stop(sc->sc_xfer[UVSCOM_INTR_DT_RD]);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UVSCOM_N_TRANSFER);
mtx_destroy(&sc->sc_mtx);