Author: n_hibma
Date: Wed Nov  3 21:50:49 2010
New Revision: 214761
URL: http://svn.freebsd.org/changeset/base/214761

Log:
  - 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

Modified:
  head/sys/dev/usb/net/uhso.c
  head/sys/dev/usb/serial/u3g.c
  head/sys/dev/usb/serial/uark.c
  head/sys/dev/usb/serial/ubsa.c
  head/sys/dev/usb/serial/ubser.c
  head/sys/dev/usb/serial/uchcom.c
  head/sys/dev/usb/serial/ucycom.c
  head/sys/dev/usb/serial/ufoma.c
  head/sys/dev/usb/serial/uftdi.c
  head/sys/dev/usb/serial/ugensa.c
  head/sys/dev/usb/serial/uipaq.c
  head/sys/dev/usb/serial/umct.c
  head/sys/dev/usb/serial/umodem.c
  head/sys/dev/usb/serial/umoscom.c
  head/sys/dev/usb/serial/uplcom.c
  head/sys/dev/usb/serial/usb_serial.c
  head/sys/dev/usb/serial/usb_serial.h
  head/sys/dev/usb/serial/uslcom.c
  head/sys/dev/usb/serial/uvisor.c
  head/sys/dev/usb/serial/uvscom.c

Modified: head/sys/dev/usb/net/uhso.c
==============================================================================
--- head/sys/dev/usb/net/uhso.c Wed Nov  3 21:40:57 2010        (r214760)
+++ head/sys/dev/usb/net/uhso.c Wed Nov  3 21:50:49 2010        (r214761)
@@ -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 *
 {
        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 *u
        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 
        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 *
 
        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]);

Modified: head/sys/dev/usb/serial/u3g.c
==============================================================================
--- head/sys/dev/usb/serial/u3g.c       Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/u3g.c       Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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;
 }
 

Modified: head/sys/dev/usb/serial/uark.c
==============================================================================
--- head/sys/dev/usb/serial/uark.c      Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/uark.c      Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/ubsa.c
==============================================================================
--- head/sys/dev/usb/serial/ubsa.c      Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/ubsa.c      Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/ubser.c
==============================================================================
--- head/sys/dev/usb/serial/ubser.c     Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/ubser.c     Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/uchcom.c
==============================================================================
--- head/sys/dev/usb/serial/uchcom.c    Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/uchcom.c    Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/ucycom.c
==============================================================================
--- head/sys/dev/usb/serial/ucycom.c    Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/ucycom.c    Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/ufoma.c
==============================================================================
--- head/sys/dev/usb/serial/ufoma.c     Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/ufoma.c     Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/uftdi.c
==============================================================================
--- head/sys/dev/usb/serial/uftdi.c     Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/uftdi.c     Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/ugensa.c
==============================================================================
--- head/sys/dev/usb/serial/ugensa.c    Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/ugensa.c    Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);

Modified: head/sys/dev/usb/serial/uipaq.c
==============================================================================
--- head/sys/dev/usb/serial/uipaq.c     Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/uipaq.c     Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/umct.c
==============================================================================
--- head/sys/dev/usb/serial/umct.c      Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/umct.c      Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/umodem.c
==============================================================================
--- head/sys/dev/usb/serial/umodem.c    Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/umodem.c    Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/umoscom.c
==============================================================================
--- head/sys/dev/usb/serial/umoscom.c   Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/umoscom.c   Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/uplcom.c
==============================================================================
--- head/sys/dev/usb/serial/uplcom.c    Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/uplcom.c    Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/usb_serial.c
==============================================================================
--- head/sys/dev/usb/serial/usb_serial.c        Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/usb_serial.c        Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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
 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, uint
  */
 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
  * 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) {
-
-                       ucom_detach_tty(sc);
+       for (subunit = 0; subunit <= ssc->sc_subunits; subunit++) {
+               if (sc[subunit].sc_flag & UCOM_FLAG_ATTACHED) {
 
-                       ucom_units_free(sc->sc_unit, 1);
+                       ucom_detach_tty(&sc[subunit]);
 
-                       /* 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, u
 
        /* 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, u
                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;
        }

Modified: head/sys/dev/usb/serial/usb_serial.h
==============================================================================
--- head/sys/dev/usb/serial/usb_serial.h        Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/usb_serial.h        Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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 *);

Modified: head/sys/dev/usb/serial/uslcom.c
==============================================================================
--- head/sys/dev/usb/serial/uslcom.c    Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/uslcom.c    Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/uvisor.c
==============================================================================
--- head/sys/dev/usb/serial/uvisor.c    Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/uvisor.c    Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 

Modified: head/sys/dev/usb/serial/uvscom.c
==============================================================================
--- head/sys/dev/usb/serial/uvscom.c    Wed Nov  3 21:40:57 2010        
(r214760)
+++ head/sys/dev/usb/serial/uvscom.c    Wed Nov  3 21:50:49 2010        
(r214761)
@@ -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);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to