1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * USB Serial CDC ACM driver
  29  *
  30  * 1. General Concepts
  31  * -------------------
  32  *
  33  * 1.1 Overview
  34  * ------------
  35  * This driver supports devices that comply with the USB Communication
  36  * Device Class Abstract Control Model (USB CDC ACM) specification,
  37  * which is available at http://www.usb.org. Given the broad nature
  38  * of communication equipment, this driver supports the following
  39  * types of devices:
  40  *      + Telecommunications devices: analog modems, mobile phones;
  41  *      + Networking devices: cable modems;
  42  * Except the above mentioned acm devices, this driver also supports
  43  * some devices which provide modem-like function and have pairs of
  44  * bulk in/out pipes.
  45  *
  46  * There are three classes that make up the definition for communication
  47  * devices: the Communication Device Class, the Communication Interface
  48  * Class and the Data Interface Class. The Communication Device Class
  49  * is a device level definition and is used by the host to properly
  50  * identify a communication device that may present several different
  51  * types of interfaces. The Communication Interface Class defines a
  52  * general-purpose mechanism that can be used to enable all types of
  53  * communication services on the Universal Serial Bus (USB). The Data
  54  * Interface Class defines a general-purpose mechanism to enable bulk
  55  * transfer on the USB when the data does not meet the requirements
  56  * for any other class.
  57  *
  58  * 1.2 Interface Definitions
  59  * -------------------------
  60  * Communication Class Interface is used for device management and,
  61  * optionally, call management. Device management includes the requests
  62  * that manage the operational state of a device, the device responses,
  63  * and event notifications. In Abstract Control Model, the device can
  64  * provide an internal implementation of call management over the Data
  65  * Class interface or the Communication Class interface.
  66  *
  67  * The Data Class defines a data interface as an interface with a class
  68  * type of Data Class. Data transmission on a communication device is
  69  * not restricted to interfaces using the Data Class. Rather, a data
  70  * interface is used to transmit and/or receive data that is not
  71  * defined by any other class. The data could be:
  72  *      + Some form of raw data from a communication line.
  73  *      + Legacy modem data.
  74  *      + Data using a proprietary format.
  75  *
  76  * 1.3 Endpoint Requirements
  77  * -------------------------
  78  * The Communication Class interface requires one endpoint, the management
  79  * element. Optionally, it can have an additional endpoint, the notification
  80  * element. The management element uses the default endpoint for all
  81  * standard and Communication Class-specific requests. The notification
  82  * element normally uses an interrupt endpoint.
  83  *
  84  * The type of endpoints belonging to a Data Class interface are restricted
  85  * to bulk, and are expected to exist in pairs of the same type (one In and
  86  * one Out).
  87  *
  88  * 1.4 ACM Function Characteristics
  89  * --------------------------------
  90  * With Abstract Control Model, the USB device understands standard
  91  * V.25ter (AT) commands. The device contains a Datapump and micro-
  92  * controller that handles the AT commands and relay controls. The
  93  * device uses both a Data Class interface and a Communication Class.
  94  * interface.
  95  *
  96  * A Communication Class interface of type Abstract Control Model will
  97  * consist of a minimum of two pipes; one is used to implement the
  98  * management element and the other to implement a notification element.
  99  * In addition, the device can use two pipes to implement channels over
 100  * which to carry unspecified data, typically over a Data Class interface.
 101  *
 102  * 1.5 ACM Serial Emulation
 103  * ------------------------
 104  * The Abstract Control Model can bridge the gap between legacy modem
 105  * devices and USB devices. To support certain types of legacy applications,
 106  * two problems need to be addressed. The first is supporting specific
 107  * legacy control signals and state variables which are addressed
 108  * directly by the various carrier modulation standards. To support these
 109  * requirement, additional requests and notifications have been created.
 110  * Please refer to macro, beginning with USB_CDC_REQ_* and
 111  * USB_CDC_NOTIFICATION_*.
 112  *
 113  * The second significant item which is needed to bridge the gap between
 114  * legacy modem designs and the Abstract Control Model is a means to
 115  * multiplex call control (AT commands) on the Data Class interface.
 116  * Legacy modem designs are limited by only supporting one channel for
 117  * both "AT" commands and the actual data. To allow this type of
 118  * functionality, the device must have a means to specify this limitation
 119  * to the host.
 120  *
 121  * When describing this type of device, the Communication Class interface
 122  * would still specify a Abstract Control Model, but call control would
 123  * actually occur over the Data Class interface. To describe this
 124  * particular characteristic, the Call Management Functional Descriptor
 125  * would have bit D1 of bmCapabilities set.
 126  *
 127  * 1.6 Other Bulk In/Out Devices
 128  * -----------------------------
 129  * Some devices don't conform to USB CDC specification, but they provide
 130  * modem-like function and have pairs of bulk in/out pipes. This driver
 131  * supports this kind of device and exports term nodes by their pipes.
 132  *
 133  * 2. Implementation
 134  * -----------------
 135  *
 136  * 2.1 Overview
 137  * ------------
 138  * It is a device-specific driver (DSD) working with USB generic serial
 139  * driver (GSD). It implements the USB-to-serial device-specific driver
 140  * interface (DSDI) which is offered by GSD. The interface is defined
 141  * by ds_ops_t structure.
 142  *
 143  * 2.2 Port States
 144  * ---------------
 145  * For USB CDC ACM devices, this driver is attached to its interface,
 146  * and exports one port for each interface. For other modem-like devices,
 147  * this driver can dynamically find the ports in the current device,
 148  * and export one port for each pair bulk in/out pipes. Each port can
 149  * be operated independently.
 150  *
 151  * port_state:
 152  *
 153  *              attach_ports
 154  *                  |
 155  *                  |
 156  *                  |
 157  *                  v
 158  *          USBSACM_PORT_CLOSED
 159  *              |           ^
 160  *              |           |
 161  *              V           |
 162  *         open_port    close_port
 163  *              |           ^
 164  *              |           |
 165  *              V           |
 166  *            USBSACM_PORT_OPEN
 167  *
 168  *
 169  * 2.3 Pipe States
 170  * ---------------
 171  * Each port has its own bulk in/out pipes and some ports could also have
 172  * its own interrupt pipes (traced by usbsacm_port structure), which are
 173  * opened during attach. The pipe status is as following:
 174  *
 175  * pipe_state:
 176  *
 177  *              usbsacm_init_alloc_ports  usbsacm_free_ports
 178  *                              |               ^
 179  *                              v               |
 180  *                |---->------ USBSACM_PORT_CLOSED ------>------+
 181  *                ^                                             |
 182  *                |                             reconnect/resume/open_port
 183  *                |                                             |
 184  *    disconnect/suspend/close_port                             |
 185  *                |                                             v
 186  *                +------<------ USBSACM_PIPE_IDLE ------<------|
 187  *                                  |           |
 188  *                                  V           ^
 189  *                                  |           |
 190  *                +-----------------+           +-----------+
 191  *                |                                         |
 192  *                V                                         ^
 193  *                |                                         |
 194  *      rx_start/tx_start----->------failed------->---------|
 195  *                |                                         |
 196  *                |                             bulkin_cb/bulkout_cb
 197  *                V                                         |
 198  *                |                                         ^
 199  *                |                                         |
 200  *                +----->----- USBSACM_PIPE_BUSY ---->------+
 201  *
 202  *
 203  * To get its status in a timely way, acm driver can get the status
 204  * of the device by polling the interrupt pipe.
 205  *
 206  */
 207 
 208 #include <sys/types.h>
 209 #include <sys/param.h>
 210 #include <sys/conf.h>
 211 #include <sys/stream.h>
 212 #include <sys/strsun.h>
 213 #include <sys/termio.h>
 214 #include <sys/termiox.h>
 215 #include <sys/ddi.h>
 216 #include <sys/sunddi.h>
 217 #include <sys/byteorder.h>
 218 #define USBDRV_MAJOR_VER        2
 219 #define USBDRV_MINOR_VER        0
 220 #include <sys/usb/usba.h>
 221 #include <sys/usb/usba/usba_types.h>
 222 #include <sys/usb/clients/usbser/usbser.h>
 223 #include <sys/usb/clients/usbser/usbser_dsdi.h>
 224 #include <sys/usb/clients/usbcdc/usb_cdc.h>
 225 #include <sys/usb/clients/usbser/usbsacm/usbsacm.h>
 226 
 227 /* devops entry points */
 228 static int      usbsacm_attach(dev_info_t *, ddi_attach_cmd_t);
 229 static int      usbsacm_detach(dev_info_t *, ddi_detach_cmd_t);
 230 static int      usbsacm_getinfo(dev_info_t *, ddi_info_cmd_t, void *,
 231                 void **);
 232 static int      usbsacm_open(queue_t *, dev_t *, int, int, cred_t *);
 233 
 234 /* DSD operations */
 235 static int      usbsacm_ds_attach(ds_attach_info_t *);
 236 static void     usbsacm_ds_detach(ds_hdl_t);
 237 static int      usbsacm_ds_register_cb(ds_hdl_t, uint_t, ds_cb_t *);
 238 static void     usbsacm_ds_unregister_cb(ds_hdl_t, uint_t);
 239 static int      usbsacm_ds_open_port(ds_hdl_t, uint_t);
 240 static int      usbsacm_ds_close_port(ds_hdl_t, uint_t);
 241 
 242 /* standard UART operations */
 243 static int      usbsacm_ds_set_port_params(ds_hdl_t, uint_t,
 244                 ds_port_params_t *);
 245 static int      usbsacm_ds_set_modem_ctl(ds_hdl_t, uint_t, int, int);
 246 static int      usbsacm_ds_get_modem_ctl(ds_hdl_t, uint_t, int, int *);
 247 static int      usbsacm_ds_break_ctl(ds_hdl_t, uint_t, int);
 248 
 249 /* data xfer */
 250 static int      usbsacm_ds_tx(ds_hdl_t, uint_t, mblk_t *);
 251 static mblk_t   *usbsacm_ds_rx(ds_hdl_t, uint_t);
 252 static void     usbsacm_ds_stop(ds_hdl_t, uint_t, int);
 253 static void     usbsacm_ds_start(ds_hdl_t, uint_t, int);
 254 
 255 /* fifo operations */
 256 static int      usbsacm_ds_fifo_flush(ds_hdl_t, uint_t, int);
 257 static int      usbsacm_ds_fifo_drain(ds_hdl_t, uint_t, int);
 258 static int      usbsacm_wait_tx_drain(usbsacm_port_t *, int);
 259 static int      usbsacm_fifo_flush_locked(usbsacm_state_t *, uint_t, int);
 260 
 261 /* power management and CPR */
 262 static int      usbsacm_ds_suspend(ds_hdl_t);
 263 static int      usbsacm_ds_resume(ds_hdl_t);
 264 static int      usbsacm_ds_disconnect(ds_hdl_t);
 265 static int      usbsacm_ds_reconnect(ds_hdl_t);
 266 static int      usbsacm_ds_usb_power(ds_hdl_t, int, int, int *);
 267 static int      usbsacm_create_pm_components(usbsacm_state_t *);
 268 static void     usbsacm_destroy_pm_components(usbsacm_state_t *);
 269 static void     usbsacm_pm_set_busy(usbsacm_state_t *);
 270 static void     usbsacm_pm_set_idle(usbsacm_state_t *);
 271 static int      usbsacm_pwrlvl0(usbsacm_state_t *);
 272 static int      usbsacm_pwrlvl1(usbsacm_state_t *);
 273 static int      usbsacm_pwrlvl2(usbsacm_state_t *);
 274 static int      usbsacm_pwrlvl3(usbsacm_state_t *);
 275 
 276 /* event handling */
 277 /* pipe callbacks */
 278 static void     usbsacm_bulkin_cb(usb_pipe_handle_t, usb_bulk_req_t *);
 279 static void     usbsacm_bulkout_cb(usb_pipe_handle_t, usb_bulk_req_t *);
 280 
 281 /* interrupt pipe */
 282 static void     usbsacm_pipe_start_polling(usbsacm_port_t *acmp);
 283 static void     usbsacm_intr_cb(usb_pipe_handle_t ph, usb_intr_req_t *req);
 284 static void     usbsacm_intr_ex_cb(usb_pipe_handle_t ph, usb_intr_req_t *req);
 285 static void     usbsacm_parse_intr_data(usbsacm_port_t *acmp, mblk_t *data);
 286 
 287 /* Utility functions */
 288 /* data transfer routines */
 289 static int      usbsacm_rx_start(usbsacm_port_t *);
 290 static void     usbsacm_tx_start(usbsacm_port_t *);
 291 static int      usbsacm_send_data(usbsacm_port_t *, mblk_t *);
 292 
 293 /* Initialize or release resources */
 294 static int      usbsacm_init_alloc_ports(usbsacm_state_t *);
 295 static void     usbsacm_free_ports(usbsacm_state_t *);
 296 static void     usbsacm_cleanup(usbsacm_state_t *);
 297 
 298 /* analysis functional descriptors */
 299 static int      usbsacm_get_descriptors(usbsacm_state_t *);
 300 
 301 /* hotplug */
 302 static int      usbsacm_restore_device_state(usbsacm_state_t *);
 303 static int      usbsacm_restore_port_state(usbsacm_state_t *);
 304 
 305 /* pipe operations */
 306 static int      usbsacm_open_port_pipes(usbsacm_port_t *);
 307 static void     usbsacm_close_port_pipes(usbsacm_port_t *);
 308 static void     usbsacm_close_pipes(usbsacm_state_t *);
 309 static void     usbsacm_disconnect_pipes(usbsacm_state_t *);
 310 static int      usbsacm_reconnect_pipes(usbsacm_state_t *);
 311 
 312 /* vendor-specific commands */
 313 static int      usbsacm_req_write(usbsacm_port_t *, uchar_t, uint16_t,
 314                 mblk_t **);
 315 static int      usbsacm_set_line_coding(usbsacm_port_t *,
 316                 usb_cdc_line_coding_t *);
 317 static void     usbsacm_mctl2reg(int mask, int val, uint8_t *);
 318 static int      usbsacm_reg2mctl(uint8_t);
 319 
 320 /* misc */
 321 static void     usbsacm_put_tail(mblk_t **, mblk_t *);
 322 static void     usbsacm_put_head(mblk_t **, mblk_t *);
 323 
 324 
 325 /*
 326  * Standard STREAMS driver definitions
 327  */
 328 struct module_info usbsacm_modinfo = {
 329         0,                      /* module id */
 330         "usbsacm",              /* module name */
 331         USBSER_MIN_PKTSZ,       /* min pkt size */
 332         USBSER_MAX_PKTSZ,       /* max pkt size */
 333         USBSER_HIWAT,           /* hi watermark */
 334         USBSER_LOWAT            /* low watermark */
 335 };
 336 
 337 static struct qinit usbsacm_rinit = {
 338         NULL,
 339         usbser_rsrv,
 340         usbsacm_open,
 341         usbser_close,
 342         NULL,
 343         &usbsacm_modinfo,
 344         NULL
 345 };
 346 
 347 static struct qinit usbsacm_winit = {
 348         usbser_wput,
 349         usbser_wsrv,
 350         NULL,
 351         NULL,
 352         NULL,
 353         &usbsacm_modinfo,
 354         NULL
 355 };
 356 
 357 
 358 struct streamtab usbsacm_str_info = {
 359         &usbsacm_rinit, &usbsacm_winit, NULL, NULL
 360 };
 361 
 362 /* cb_ops structure */
 363 static struct cb_ops usbsacm_cb_ops = {
 364         nodev,                  /* cb_open */
 365         nodev,                  /* cb_close */
 366         nodev,                  /* cb_strategy */
 367         nodev,                  /* cb_print */
 368         nodev,                  /* cb_dump */
 369         nodev,                  /* cb_read */
 370         nodev,                  /* cb_write */
 371         nodev,                  /* cb_ioctl */
 372         nodev,                  /* cb_devmap */
 373         nodev,                  /* cb_mmap */
 374         nodev,                  /* cb_segmap */
 375         nochpoll,               /* cb_chpoll */
 376         ddi_prop_op,            /* cb_prop_op */
 377         &usbsacm_str_info,  /* cb_stream */
 378         (int)(D_64BIT | D_NEW | D_MP | D_HOTPLUG)       /* cb_flag */
 379 };
 380 
 381 /* dev_ops structure */
 382 struct dev_ops usbsacm_ops = {
 383         DEVO_REV,               /* devo_rev */
 384         0,                      /* devo_refcnt */
 385         usbsacm_getinfo,        /* devo_getinfo */
 386         nulldev,                /* devo_identify */
 387         nulldev,                /* devo_probe */
 388         usbsacm_attach,         /* devo_attach */
 389         usbsacm_detach,         /* devo_detach */
 390         nodev,                  /* devo_reset */
 391         &usbsacm_cb_ops,    /* devo_cb_ops */
 392         (struct bus_ops *)NULL, /* devo_bus_ops */
 393         usbser_power,           /* devo_power */
 394         ddi_quiesce_not_needed, /* devo_quiesce */
 395 };
 396 
 397 extern struct mod_ops mod_driverops;
 398 /* modldrv structure */
 399 static struct modldrv modldrv = {
 400         &mod_driverops,             /* type of module - driver */
 401         "USB Serial CDC ACM driver",
 402         &usbsacm_ops,
 403 };
 404 
 405 /* modlinkage structure */
 406 static struct modlinkage modlinkage = {
 407         MODREV_1,
 408         &modldrv,
 409         NULL
 410 };
 411 
 412 static void     *usbsacm_statep;        /* soft state */
 413 
 414 /*
 415  * DSD definitions
 416  */
 417 static ds_ops_t usbsacm_ds_ops = {
 418         DS_OPS_VERSION,
 419         usbsacm_ds_attach,
 420         usbsacm_ds_detach,
 421         usbsacm_ds_register_cb,
 422         usbsacm_ds_unregister_cb,
 423         usbsacm_ds_open_port,
 424         usbsacm_ds_close_port,
 425         usbsacm_ds_usb_power,
 426         usbsacm_ds_suspend,
 427         usbsacm_ds_resume,
 428         usbsacm_ds_disconnect,
 429         usbsacm_ds_reconnect,
 430         usbsacm_ds_set_port_params,
 431         usbsacm_ds_set_modem_ctl,
 432         usbsacm_ds_get_modem_ctl,
 433         usbsacm_ds_break_ctl,
 434         NULL,                   /* NULL if h/w doesn't support loopback */
 435         usbsacm_ds_tx,
 436         usbsacm_ds_rx,
 437         usbsacm_ds_stop,
 438         usbsacm_ds_start,
 439         usbsacm_ds_fifo_flush,
 440         usbsacm_ds_fifo_drain
 441 };
 442 
 443 /*
 444  * baud code -> baud rate (0 means unsupported rate)
 445  */
 446 static int usbsacm_speedtab[] = {
 447         0,      /* B0 */
 448         50,     /* B50 */
 449         75,     /* B75 */
 450         110,    /* B110 */
 451         134,    /* B134 */
 452         150,    /* B150 */
 453         200,    /* B200 */
 454         300,    /* B300 */
 455         600,    /* B600 */
 456         1200,   /* B1200 */
 457         1800,   /* B1800 */
 458         2400,   /* B2400 */
 459         4800,   /* B4800 */
 460         9600,   /* B9600 */
 461         19200,  /* B19200 */
 462         38400,  /* B38400 */
 463         57600,  /* B57600 */
 464         76800,  /* B76800 */
 465         115200, /* B115200 */
 466         153600, /* B153600 */
 467         230400, /* B230400 */
 468         307200, /* B307200 */
 469         460800, /* B460800 */
 470         921600  /* B921600 */
 471 };
 472 
 473 
 474 static uint_t   usbsacm_errlevel = USB_LOG_L4;
 475 static uint_t   usbsacm_errmask = 0xffffffff;
 476 static uint_t   usbsacm_instance_debug = (uint_t)-1;
 477 
 478 
 479 /*
 480  * usbsacm driver's entry points
 481  * -----------------------------
 482  */
 483 /*
 484  * Module-wide initialization routine.
 485  */
 486 int
 487 _init(void)
 488 {
 489         int    error;
 490 
 491         if ((error = mod_install(&modlinkage)) == 0) {
 492 
 493                 error = ddi_soft_state_init(&usbsacm_statep,
 494                     usbser_soft_state_size(), 1);
 495         }
 496 
 497         return (error);
 498 }
 499 
 500 
 501 /*
 502  * Module-wide tear-down routine.
 503  */
 504 int
 505 _fini(void)
 506 {
 507         int    error;
 508 
 509         if ((error = mod_remove(&modlinkage)) == 0) {
 510                 ddi_soft_state_fini(&usbsacm_statep);
 511         }
 512 
 513         return (error);
 514 }
 515 
 516 
 517 int
 518 _info(struct modinfo *modinfop)
 519 {
 520         return (mod_info(&modlinkage, modinfop));
 521 }
 522 
 523 
 524 /*
 525  * Device configuration entry points
 526  */
 527 static int
 528 usbsacm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 529 {
 530         return (usbser_attach(dip, cmd, usbsacm_statep, &usbsacm_ds_ops));
 531 }
 532 
 533 
 534 static int
 535 usbsacm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 536 {
 537         return (usbser_detach(dip, cmd, usbsacm_statep));
 538 }
 539 
 540 
 541 int
 542 usbsacm_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
 543                 void **result)
 544 {
 545         return (usbser_getinfo(dip, infocmd, arg, result, usbsacm_statep));
 546 }
 547 
 548 
 549 static int
 550 usbsacm_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr)
 551 {
 552         return (usbser_open(rq, dev, flag, sflag, cr, usbsacm_statep));
 553 }
 554 
 555 /*
 556  * usbsacm_ds_detach:
 557  *      attach device instance, called from GSD attach
 558  *      initialize state and device, including:
 559  *              state variables, locks, device node
 560  *              device registration with system
 561  *              power management
 562  */
 563 static int
 564 usbsacm_ds_attach(ds_attach_info_t *aip)
 565 {
 566         usbsacm_state_t *acmp;
 567 
 568         acmp = (usbsacm_state_t *)kmem_zalloc(sizeof (usbsacm_state_t),
 569             KM_SLEEP);
 570         acmp->acm_dip = aip->ai_dip;
 571         acmp->acm_usb_events = aip->ai_usb_events;
 572         acmp->acm_ports = NULL;
 573         *aip->ai_hdl = (ds_hdl_t)acmp;
 574 
 575         /* registers usbsacm with the USBA framework */
 576         if (usb_client_attach(acmp->acm_dip, USBDRV_VERSION,
 577             0) != USB_SUCCESS) {
 578 
 579                 goto fail;
 580         }
 581 
 582         /* Get the configuration information of device */
 583         if (usb_get_dev_data(acmp->acm_dip, &acmp->acm_dev_data,
 584             USB_PARSE_LVL_CFG, 0) != USB_SUCCESS) {
 585 
 586                 goto fail;
 587         }
 588         acmp->acm_def_ph = acmp->acm_dev_data->dev_default_ph;
 589         acmp->acm_dev_state = USB_DEV_ONLINE;
 590         mutex_init(&acmp->acm_mutex, NULL, MUTEX_DRIVER,
 591             acmp->acm_dev_data->dev_iblock_cookie);
 592 
 593         acmp->acm_lh = usb_alloc_log_hdl(acmp->acm_dip, "usbsacm",
 594             &usbsacm_errlevel, &usbsacm_errmask, &usbsacm_instance_debug, 0);
 595 
 596         /* Create power management components */
 597         if (usbsacm_create_pm_components(acmp) != USB_SUCCESS) {
 598                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
 599                     "usbsacm_ds_attach: create pm components failed.");
 600 
 601                 goto fail;
 602         }
 603 
 604         /* Register to get callbacks for USB events */
 605         if (usb_register_event_cbs(acmp->acm_dip, acmp->acm_usb_events, 0)
 606             != USB_SUCCESS) {
 607                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
 608                     "usbsacm_ds_attach: register event callback failed.");
 609 
 610                 goto fail;
 611         }
 612 
 613         /*
 614          * If devices conform to acm spec, driver will attach using class id;
 615          * if not, using device id.
 616          */
 617         if ((strcmp(DEVI(acmp->acm_dip)->devi_binding_name,
 618             "usbif,class2.2") == 0) ||
 619             ((strcmp(DEVI(acmp->acm_dip)->devi_binding_name,
 620             "usb,class2.2.0") == 0))) {
 621 
 622                 acmp->acm_compatibility = B_TRUE;
 623         } else {
 624                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
 625                     "usbsacm_ds_attach: A nonstandard device is attaching to "
 626                     "usbsacm driver. This device doesn't conform to "
 627                     "usb cdc spec.");
 628 
 629                 acmp->acm_compatibility = B_FALSE;
 630         }
 631 
 632         /* initialize state variables */
 633         if (usbsacm_init_alloc_ports(acmp) != USB_SUCCESS) {
 634                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
 635                     "usbsacm_ds_attach: initialize port structure failed.");
 636 
 637                 goto fail;
 638         }
 639         *aip->ai_port_cnt = acmp->acm_port_cnt;
 640 
 641         /* Get max data size of bulk transfer */
 642         if (usb_pipe_get_max_bulk_transfer_size(acmp->acm_dip,
 643             &acmp->acm_xfer_sz) != USB_SUCCESS) {
 644                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
 645                     "usbsacm_ds_attach: get max size of transfer failed.");
 646 
 647                 goto fail;
 648         }
 649 
 650         return (USB_SUCCESS);
 651 fail:
 652         usbsacm_cleanup(acmp);
 653 
 654         return (USB_FAILURE);
 655 }
 656 
 657 
 658 /*
 659  * usbsacm_ds_detach:
 660  *      detach device instance, called from GSD detach
 661  */
 662 static void
 663 usbsacm_ds_detach(ds_hdl_t hdl)
 664 {
 665         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
 666 
 667         USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
 668             "usbsacm_ds_detach:");
 669 
 670         usbsacm_close_pipes(acmp);
 671         usbsacm_cleanup(acmp);
 672 }
 673 
 674 
 675 /*
 676  * usbsacm_ds_register_cb:
 677  *      GSD routine call ds_register_cb to register interrupt callbacks
 678  *      for the given port
 679  */
 680 /*ARGSUSED*/
 681 static int
 682 usbsacm_ds_register_cb(ds_hdl_t hdl, uint_t port_num, ds_cb_t *cb)
 683 {
 684         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
 685         usbsacm_port_t  *acm_port;
 686 
 687         USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh,
 688             "usbsacm_ds_register_cb: acmp = 0x%p port_num = %d",
 689             (void *)acmp, port_num);
 690 
 691         /* Check if port number is greater than actual port number. */
 692         if (port_num >= acmp->acm_port_cnt) {
 693                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
 694                     "usbsacm_ds_register_cb: port number is wrong.");
 695 
 696                 return (USB_FAILURE);
 697         }
 698         acm_port = &acmp->acm_ports[port_num];
 699         acm_port->acm_cb = *cb;
 700 
 701         return (USB_SUCCESS);
 702 }
 703 
 704 
 705 /*
 706  * usbsacm_ds_unregister_cb:
 707  *      GSD routine call ds_unregister_cb to unregister
 708  *      interrupt callbacks for the given port
 709  */
 710 /*ARGSUSED*/
 711 static void
 712 usbsacm_ds_unregister_cb(ds_hdl_t hdl, uint_t port_num)
 713 {
 714         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
 715         usbsacm_port_t  *acm_port;
 716 
 717         USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
 718             "usbsacm_ds_unregister_cb: ");
 719 
 720         if (port_num < acmp->acm_port_cnt) {
 721                 /* Release callback function */
 722                 acm_port = &acmp->acm_ports[port_num];
 723                 bzero(&acm_port->acm_cb, sizeof (acm_port->acm_cb));
 724         }
 725 }
 726 
 727 
 728 /*
 729  * usbsacm_ds_open_port:
 730  *      GSD routine call ds_open_port
 731  *      to open the given port
 732  */
 733 /*ARGSUSED*/
 734 static int
 735 usbsacm_ds_open_port(ds_hdl_t hdl, uint_t port_num)
 736 {
 737         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
 738         usbsacm_port_t  *acm_port = &acmp->acm_ports[port_num];
 739 
 740         USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh,
 741             "usbsacm_ds_open_port: port_num = %d", port_num);
 742 
 743         mutex_enter(&acm_port->acm_port_mutex);
 744         /* Check the status of the given port and device */
 745         if ((acmp->acm_dev_state == USB_DEV_DISCONNECTED) ||
 746             (acm_port->acm_port_state != USBSACM_PORT_CLOSED)) {
 747                 mutex_exit(&acm_port->acm_port_mutex);
 748 
 749                 return (USB_FAILURE);
 750         }
 751         mutex_exit(&acm_port->acm_port_mutex);
 752 
 753         usbsacm_pm_set_busy(acmp);
 754 
 755         /* open pipes of port */
 756         if (usbsacm_open_port_pipes(acm_port) != USB_SUCCESS) {
 757                 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
 758                     "usbsacm_ds_open_port: open pipes failed.");
 759 
 760                 return (USB_FAILURE);
 761         }
 762 
 763         mutex_enter(&acm_port->acm_port_mutex);
 764         /* data receipt */
 765         if (usbsacm_rx_start(acm_port) != USB_SUCCESS) {
 766                 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
 767                     "usbsacm_ds_open_port: start receive data failed.");
 768                 mutex_exit(&acm_port->acm_port_mutex);
 769 
 770                 return (USB_FAILURE);
 771         }
 772         acm_port->acm_port_state = USBSACM_PORT_OPEN;
 773 
 774         mutex_exit(&acm_port->acm_port_mutex);
 775 
 776         return (USB_SUCCESS);
 777 }
 778 
 779 
 780 /*
 781  * usbsacm_ds_close_port:
 782  *      GSD routine call ds_close_port
 783  *      to close the given port
 784  */
 785 /*ARGSUSED*/
 786 static int
 787 usbsacm_ds_close_port(ds_hdl_t hdl, uint_t port_num)
 788 {
 789         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
 790         usbsacm_port_t  *acm_port = &acmp->acm_ports[port_num];
 791         int             rval = USB_SUCCESS;
 792 
 793         USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
 794             "usbsacm_ds_close_port: acmp = 0x%p", (void *)acmp);
 795 
 796         mutex_enter(&acm_port->acm_port_mutex);
 797         acm_port->acm_port_state = USBSACM_PORT_CLOSED;
 798         mutex_exit(&acm_port->acm_port_mutex);
 799 
 800         usbsacm_close_port_pipes(acm_port);
 801 
 802         mutex_enter(&acm_port->acm_port_mutex);
 803         rval = usbsacm_fifo_flush_locked(acmp, port_num, DS_TX | DS_RX);
 804         mutex_exit(&acm_port->acm_port_mutex);
 805 
 806         usbsacm_pm_set_idle(acmp);
 807 
 808         return (rval);
 809 }
 810 
 811 
 812 /*
 813  * usbsacm_ds_usb_power:
 814  *      GSD routine call ds_usb_power
 815  *      to set power level of the component
 816  */
 817 /*ARGSUSED*/
 818 static int
 819 usbsacm_ds_usb_power(ds_hdl_t hdl, int comp, int level, int *new_state)
 820 {
 821         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
 822         usbsacm_pm_t    *pm = acmp->acm_pm;
 823         int             rval = USB_SUCCESS;
 824 
 825         USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
 826             "usbsacm_ds_usb_power: ");
 827 
 828         /* check if pm is NULL */
 829         if (pm == NULL) {
 830                 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
 831                     "usbsacm_ds_usb_power: pm is NULL.");
 832 
 833                 return (USB_FAILURE);
 834         }
 835 
 836         mutex_enter(&acmp->acm_mutex);
 837         /*
 838          * check if we are transitioning to a legal power level
 839          */
 840         if (USB_DEV_PWRSTATE_OK(pm->pm_pwr_states, level)) {
 841                 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
 842                     "usbsacm_ds_usb_power: "
 843                     "illegal power level %d, pwr_states=%x",
 844                     level, pm->pm_pwr_states);
 845                 mutex_exit(&acmp->acm_mutex);
 846 
 847                 return (USB_FAILURE);
 848         }
 849 
 850         /*
 851          * if we are about to raise power and asked to lower power, fail
 852          */
 853         if (pm->pm_raise_power && (level < (int)pm->pm_cur_power)) {
 854                 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
 855                     "usbsacm_ds_usb_power: wrong condition.");
 856                 mutex_exit(&acmp->acm_mutex);
 857 
 858                 return (USB_FAILURE);
 859         }
 860 
 861         /*
 862          * Set the power status of device by request level.
 863          */
 864         switch (level) {
 865         case USB_DEV_OS_PWR_OFF:
 866                 rval = usbsacm_pwrlvl0(acmp);
 867 
 868                 break;
 869         case USB_DEV_OS_PWR_1:
 870                 rval = usbsacm_pwrlvl1(acmp);
 871 
 872                 break;
 873         case USB_DEV_OS_PWR_2:
 874                 rval = usbsacm_pwrlvl2(acmp);
 875 
 876                 break;
 877         case USB_DEV_OS_FULL_PWR:
 878                 rval = usbsacm_pwrlvl3(acmp);
 879                 /*
 880                  * If usbser dev_state is DISCONNECTED or SUSPENDED, it shows
 881                  * that the usb serial device is disconnected/suspended while it
 882                  * is under power down state, now the device is powered up
 883                  * before it is reconnected/resumed. xxx_pwrlvl3() will set dev
 884                  * state to ONLINE, we need to set the dev state back to
 885                  * DISCONNECTED/SUSPENDED.
 886                  */
 887                 if ((rval == USB_SUCCESS) &&
 888                     ((*new_state == USB_DEV_DISCONNECTED) ||
 889                     (*new_state == USB_DEV_SUSPENDED))) {
 890                         acmp->acm_dev_state = *new_state;
 891                 }
 892 
 893                 break;
 894         }
 895 
 896         *new_state = acmp->acm_dev_state;
 897         mutex_exit(&acmp->acm_mutex);
 898 
 899         return (rval);
 900 }
 901 
 902 
 903 /*
 904  * usbsacm_ds_suspend:
 905  *      GSD routine call ds_suspend
 906  *      during CPR suspend
 907  */
 908 static int
 909 usbsacm_ds_suspend(ds_hdl_t hdl)
 910 {
 911         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
 912         int             state = USB_DEV_SUSPENDED;
 913 
 914         USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
 915             "usbsacm_ds_suspend: ");
 916         /*
 917          * If the device is suspended while it is under PWRED_DOWN state, we
 918          * need to keep the PWRED_DOWN state so that it could be powered up
 919          * later. In the mean while, usbser dev state will be changed to
 920          * SUSPENDED state.
 921          */
 922         mutex_enter(&acmp->acm_mutex);
 923         if (acmp->acm_dev_state != USB_DEV_PWRED_DOWN) {
 924                 /* set device status to suspend */
 925                 acmp->acm_dev_state = USB_DEV_SUSPENDED;
 926         }
 927         mutex_exit(&acmp->acm_mutex);
 928 
 929         usbsacm_disconnect_pipes(acmp);
 930 
 931         return (state);
 932 }
 933 
 934 /*
 935  * usbsacm_ds_resume:
 936  *      GSD routine call ds_resume
 937  *      during CPR resume
 938  */
 939 /*ARGSUSED*/
 940 static int
 941 usbsacm_ds_resume(ds_hdl_t hdl)
 942 {
 943         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
 944         int             current_state;
 945         int             ret;
 946 
 947         USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
 948             "usbsacm_ds_resume: ");
 949 
 950         mutex_enter(&acmp->acm_mutex);
 951         current_state = acmp->acm_dev_state;
 952         mutex_exit(&acmp->acm_mutex);
 953 
 954         /* restore the status of device */
 955         if (current_state != USB_DEV_ONLINE) {
 956                 ret = usbsacm_restore_device_state(acmp);
 957         } else {
 958                 ret = USB_DEV_ONLINE;
 959         }
 960 
 961         return (ret);
 962 }
 963 
 964 /*
 965  * usbsacm_ds_disconnect:
 966  *      GSD routine call ds_disconnect
 967  *      to disconnect USB device
 968  */
 969 static int
 970 usbsacm_ds_disconnect(ds_hdl_t hdl)
 971 {
 972         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
 973         int             state = USB_DEV_DISCONNECTED;
 974 
 975         USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
 976             "usbsacm_ds_disconnect: ");
 977 
 978         /*
 979          * If the device is disconnected while it is under PWRED_DOWN state, we
 980          * need to keep the PWRED_DOWN state so that it could be powered up
 981          * later. In the mean while, usbser dev state will be changed to
 982          * DISCONNECTED state.
 983          */
 984         mutex_enter(&acmp->acm_mutex);
 985         if (acmp->acm_dev_state != USB_DEV_PWRED_DOWN) {
 986                 /* set device status to disconnected */
 987                 acmp->acm_dev_state = USB_DEV_DISCONNECTED;
 988         }
 989         mutex_exit(&acmp->acm_mutex);
 990 
 991         usbsacm_disconnect_pipes(acmp);
 992 
 993         return (state);
 994 }
 995 
 996 
 997 /*
 998  * usbsacm_ds_reconnect:
 999  *      GSD routine call ds_reconnect
1000  *      to reconnect USB device
1001  */
1002 /*ARGSUSED*/
1003 static int
1004 usbsacm_ds_reconnect(ds_hdl_t hdl)
1005 {
1006         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
1007 
1008         USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh,
1009             "usbsacm_ds_reconnect: ");
1010 
1011         return (usbsacm_restore_device_state(acmp));
1012 }
1013 
1014 
1015 /*
1016  * usbsacm_ds_set_port_params:
1017  *      GSD routine call ds_set_port_params
1018  *      to set one or more port parameters
1019  */
1020 /*ARGSUSED*/
1021 static int
1022 usbsacm_ds_set_port_params(ds_hdl_t hdl, uint_t port_num, ds_port_params_t *tp)
1023 {
1024         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
1025         usbsacm_port_t  *acm_port = &acmp->acm_ports[port_num];
1026         int             i;
1027         uint_t          ui;
1028         ds_port_param_entry_t *pe;
1029         usb_cdc_line_coding_t lc;
1030         int             ret;
1031 
1032         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
1033             "usbsacm_ds_set_port_params: acmp = 0x%p", (void *)acmp);
1034 
1035         mutex_enter(&acm_port->acm_port_mutex);
1036         /*
1037          * If device conform to acm spec, check if it support to set port param.
1038          */
1039         if ((acm_port->acm_cap & USB_CDC_ACM_CAP_SERIAL_LINE) == 0 &&
1040             acmp->acm_compatibility == B_TRUE) {
1041 
1042                 mutex_exit(&acm_port->acm_port_mutex);
1043                 USB_DPRINTF_L2(PRINT_MASK_ALL, acmp->acm_lh,
1044                     "usbsacm_ds_set_port_params: "
1045                     "don't support Set_Line_Coding.");
1046 
1047                 return (USB_FAILURE);
1048         }
1049 
1050         lc = acm_port->acm_line_coding;
1051         mutex_exit(&acm_port->acm_port_mutex);
1052         pe = tp->tp_entries;
1053         /* Get parameter information from ds_port_params_t */
1054         for (i = 0; i < tp->tp_cnt; i++, pe++) {
1055                 switch (pe->param) {
1056                 case DS_PARAM_BAUD:
1057                         /* Data terminal rate, in bits per second. */
1058                         ui = pe->val.ui;
1059 
1060                         /* if we don't support this speed, return USB_FAILURE */
1061                         if ((ui >= NELEM(usbsacm_speedtab)) ||
1062                             ((ui > 0) && (usbsacm_speedtab[ui] == 0))) {
1063                                 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
1064                                     "usbsacm_ds_set_port_params: "
1065                                     " error baud rate");
1066 
1067                                 return (USB_FAILURE);
1068                         }
1069                         lc.dwDTERate = LE_32(usbsacm_speedtab[ui]);
1070 
1071                         break;
1072                 case DS_PARAM_PARITY:
1073                         /* Parity Type */
1074                         if (pe->val.ui & PARENB) {
1075                                 if (pe->val.ui & PARODD) {
1076                                         lc.bParityType = USB_CDC_PARITY_ODD;
1077                                 } else {
1078                                         lc.bParityType = USB_CDC_PARITY_EVEN;
1079                                 }
1080                         } else {
1081                                 lc.bParityType = USB_CDC_PARITY_NO;
1082                         }
1083 
1084                         break;
1085                 case DS_PARAM_STOPB:
1086                         /* Stop bit */
1087                         if (pe->val.ui & CSTOPB) {
1088                                 lc.bCharFormat = USB_CDC_STOP_BITS_2;
1089                         } else {
1090                                 lc.bCharFormat = USB_CDC_STOP_BITS_1;
1091                         }
1092 
1093                         break;
1094                 case DS_PARAM_CHARSZ:
1095                         /* Data Bits */
1096                         switch (pe->val.ui) {
1097                         case CS5:
1098                                 lc.bDataBits = 5;
1099                                 break;
1100                         case CS6:
1101                                 lc.bDataBits = 6;
1102                                 break;
1103                         case CS7:
1104                                 lc.bDataBits = 7;
1105                                 break;
1106                         case CS8:
1107                         default:
1108                                 lc.bDataBits = 8;
1109                                 break;
1110                         }
1111 
1112                         break;
1113                 default:
1114                         USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
1115                             "usbsacm_ds_set_port_params: "
1116                             "parameter 0x%x isn't supported",
1117                             pe->param);
1118 
1119                         break;
1120                 }
1121         }
1122 
1123         if ((ret = usbsacm_set_line_coding(acm_port, &lc)) == USB_SUCCESS) {
1124                 mutex_enter(&acm_port->acm_port_mutex);
1125                 acm_port->acm_line_coding = lc;
1126                 mutex_exit(&acm_port->acm_port_mutex);
1127         }
1128 
1129         /*
1130          * If device don't conform to acm spec, return success directly.
1131          */
1132         if (acmp->acm_compatibility != B_TRUE) {
1133                 ret = USB_SUCCESS;
1134         }
1135 
1136         return (ret);
1137 }
1138 
1139 
1140 /*
1141  * usbsacm_ds_set_modem_ctl:
1142  *      GSD routine call ds_set_modem_ctl
1143  *      to set modem control of the given port
1144  */
1145 /*ARGSUSED*/
1146 static int
1147 usbsacm_ds_set_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int val)
1148 {
1149         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
1150         usbsacm_port_t  *acm_port = &acmp->acm_ports[port_num];
1151         uint8_t         new_mctl;
1152         int             ret;
1153 
1154         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
1155             "usbsacm_ds_set_modem_ctl: mask = 0x%x val = 0x%x",
1156             mask, val);
1157 
1158         mutex_enter(&acm_port->acm_port_mutex);
1159         /*
1160          * If device conform to acm spec, check if it support to set modem
1161          * controls.
1162          */
1163         if ((acm_port->acm_cap & USB_CDC_ACM_CAP_SERIAL_LINE) == 0 &&
1164             acmp->acm_compatibility == B_TRUE) {
1165 
1166                 mutex_exit(&acm_port->acm_port_mutex);
1167                 USB_DPRINTF_L2(PRINT_MASK_ALL, acmp->acm_lh,
1168                     "usbsacm_ds_set_modem_ctl: "
1169                     "don't support Set_Control_Line_State.");
1170 
1171                 return (USB_FAILURE);
1172         }
1173 
1174         new_mctl = acm_port->acm_mctlout;
1175         mutex_exit(&acm_port->acm_port_mutex);
1176 
1177         usbsacm_mctl2reg(mask, val, &new_mctl);
1178 
1179         if ((acmp->acm_compatibility == B_FALSE) || ((ret =
1180             usbsacm_req_write(acm_port, USB_CDC_REQ_SET_CONTROL_LINE_STATE,
1181             new_mctl, NULL)) == USB_SUCCESS)) {
1182                 mutex_enter(&acm_port->acm_port_mutex);
1183                 acm_port->acm_mctlout = new_mctl;
1184                 mutex_exit(&acm_port->acm_port_mutex);
1185         }
1186 
1187         /*
1188          * If device don't conform to acm spec, return success directly.
1189          */
1190         if (acmp->acm_compatibility != B_TRUE) {
1191                 ret = USB_SUCCESS;
1192         }
1193 
1194         return (ret);
1195 }
1196 
1197 
1198 /*
1199  * usbsacm_ds_get_modem_ctl:
1200  *      GSD routine call ds_get_modem_ctl
1201  *      to get modem control/status of the given port
1202  */
1203 /*ARGSUSED*/
1204 static int
1205 usbsacm_ds_get_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int *valp)
1206 {
1207         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
1208         usbsacm_port_t  *acm_port = &acmp->acm_ports[port_num];
1209 
1210         mutex_enter(&acm_port->acm_port_mutex);
1211         *valp = usbsacm_reg2mctl(acm_port->acm_mctlout) & mask;
1212         /*
1213          * If device conform to acm spec, polling function can modify the value
1214          * of acm_mctlin; else set to default value.
1215          */
1216         if (acmp->acm_compatibility) {
1217                 *valp |= usbsacm_reg2mctl(acm_port->acm_mctlin) & mask;
1218                 *valp |= (mask & (TIOCM_CD | TIOCM_CTS));
1219         } else {
1220                 *valp |= (mask & (TIOCM_CD | TIOCM_CTS | TIOCM_DSR | TIOCM_RI));
1221         }
1222         mutex_exit(&acm_port->acm_port_mutex);
1223 
1224         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
1225             "usbsacm_ds_get_modem_ctl: val = 0x%x", *valp);
1226 
1227         return (USB_SUCCESS);
1228 }
1229 
1230 
1231 /*
1232  * usbsacm_ds_tx:
1233  *      GSD routine call ds_break_ctl
1234  *      to set/clear break
1235  */
1236 /*ARGSUSED*/
1237 static int
1238 usbsacm_ds_break_ctl(ds_hdl_t hdl, uint_t port_num, int ctl)
1239 {
1240         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
1241         usbsacm_port_t  *acm_port = &acmp->acm_ports[port_num];
1242 
1243         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
1244             "usbsacm_ds_break_ctl: ");
1245 
1246         mutex_enter(&acm_port->acm_port_mutex);
1247         /*
1248          * If device conform to acm spec, check if it support to send break.
1249          */
1250         if ((acm_port->acm_cap & USB_CDC_ACM_CAP_SEND_BREAK) == 0 &&
1251             acmp->acm_compatibility == B_TRUE) {
1252 
1253                 mutex_exit(&acm_port->acm_port_mutex);
1254                 USB_DPRINTF_L2(PRINT_MASK_ALL, acmp->acm_lh,
1255                     "usbsacm_ds_break_ctl: don't support send break.");
1256 
1257                 return (USB_FAILURE);
1258         }
1259         mutex_exit(&acm_port->acm_port_mutex);
1260 
1261         return (usbsacm_req_write(acm_port, USB_CDC_REQ_SEND_BREAK,
1262             ((ctl == DS_ON) ? 0xffff : 0), NULL));
1263 }
1264 
1265 
1266 /*
1267  * usbsacm_ds_tx:
1268  *      GSD routine call ds_tx
1269  *      to data transmit
1270  */
1271 /*ARGSUSED*/
1272 static int
1273 usbsacm_ds_tx(ds_hdl_t hdl, uint_t port_num, mblk_t *mp)
1274 {
1275         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
1276         usbsacm_port_t  *acm_port = &acmp->acm_ports[port_num];
1277 
1278         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
1279             "usbsacm_ds_tx: mp = 0x%p acmp = 0x%p", (void *)mp, (void *)acmp);
1280 
1281         /* sanity checks */
1282         if (mp == NULL) {
1283 
1284                 return (USB_SUCCESS);
1285         }
1286         if (MBLKL(mp) < 1) {
1287                 freemsg(mp);
1288 
1289                 return (USB_SUCCESS);
1290         }
1291 
1292         mutex_enter(&acm_port->acm_port_mutex);
1293         /* put mblk to tail of mblk chain */
1294         usbsacm_put_tail(&acm_port->acm_tx_mp, mp);
1295         usbsacm_tx_start(acm_port);
1296         mutex_exit(&acm_port->acm_port_mutex);
1297 
1298         return (USB_SUCCESS);
1299 }
1300 
1301 
1302 /*
1303  * usbsacm_ds_rx:
1304  *      GSD routine call ds_rx;
1305  *      to data receipt
1306  */
1307 /*ARGSUSED*/
1308 static mblk_t *
1309 usbsacm_ds_rx(ds_hdl_t hdl, uint_t port_num)
1310 {
1311         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
1312         usbsacm_port_t  *acm_port = &acmp->acm_ports[port_num];
1313         mblk_t          *mp;
1314 
1315         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
1316             "usbsacm_ds_rx: acmp = 0x%p", (void *)acmp);
1317 
1318         mutex_enter(&acm_port->acm_port_mutex);
1319 
1320         mp = acm_port->acm_rx_mp;
1321         acm_port->acm_rx_mp = NULL;
1322         mutex_exit(&acm_port->acm_port_mutex);
1323 
1324         return (mp);
1325 }
1326 
1327 
1328 /*
1329  * usbsacm_ds_stop:
1330  *      GSD routine call ds_stop;
1331  *      but acm spec don't define this function
1332  */
1333 /*ARGSUSED*/
1334 static void
1335 usbsacm_ds_stop(ds_hdl_t hdl, uint_t port_num, int dir)
1336 {
1337         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
1338 
1339         USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
1340             "usbsacm_ds_stop: don't support!");
1341 }
1342 
1343 
1344 /*
1345  * usbsacm_ds_start:
1346  *      GSD routine call ds_start;
1347  *      but acm spec don't define this function
1348  */
1349 /*ARGSUSED*/
1350 static void
1351 usbsacm_ds_start(ds_hdl_t hdl, uint_t port_num, int dir)
1352 {
1353         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
1354 
1355         USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
1356             "usbsacm_ds_start: don't support!");
1357 }
1358 
1359 
1360 /*
1361  * usbsacm_ds_fifo_flush:
1362  *      GSD routine call ds_fifo_flush
1363  *      to flush FIFOs
1364  */
1365 /*ARGSUSED*/
1366 static int
1367 usbsacm_ds_fifo_flush(ds_hdl_t hdl, uint_t port_num, int dir)
1368 {
1369         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
1370         usbsacm_port_t  *acm_port = &acmp->acm_ports[port_num];
1371         int             ret = USB_SUCCESS;
1372 
1373         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
1374             "usbsacm_ds_fifo_flush: ");
1375 
1376         mutex_enter(&acm_port->acm_port_mutex);
1377         ret = usbsacm_fifo_flush_locked(acmp, port_num, dir);
1378         mutex_exit(&acm_port->acm_port_mutex);
1379 
1380         return (ret);
1381 }
1382 
1383 
1384 /*
1385  * usbsacm_ds_fifo_drain:
1386  *      GSD routine call ds_fifo_drain
1387  *      to wait until empty output FIFO
1388  */
1389 /*ARGSUSED*/
1390 static int
1391 usbsacm_ds_fifo_drain(ds_hdl_t hdl, uint_t port_num, int timeout)
1392 {
1393         usbsacm_state_t *acmp = (usbsacm_state_t *)hdl;
1394         usbsacm_port_t  *acm_port = &acmp->acm_ports[port_num];
1395         int             rval = USB_SUCCESS;
1396 
1397         USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh,
1398             "usbsacm_ds_fifo_drain: ");
1399 
1400         mutex_enter(&acm_port->acm_port_mutex);
1401         ASSERT(acm_port->acm_port_state == USBSACM_PORT_OPEN);
1402 
1403         if (usbsacm_wait_tx_drain(acm_port, timeout) != USB_SUCCESS) {
1404                 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
1405                     "usbsacm_ds_fifo_drain: fifo drain failed.");
1406                 mutex_exit(&acm_port->acm_port_mutex);
1407 
1408                 return (USB_FAILURE);
1409         }
1410 
1411         mutex_exit(&acm_port->acm_port_mutex);
1412 
1413         return (rval);
1414 }
1415 
1416 
1417 /*
1418  * usbsacm_fifo_flush_locked:
1419  *      flush FIFOs of the given ports
1420  */
1421 /*ARGSUSED*/
1422 static int
1423 usbsacm_fifo_flush_locked(usbsacm_state_t *acmp, uint_t port_num, int dir)
1424 {
1425         usbsacm_port_t  *acm_port = &acmp->acm_ports[port_num];
1426 
1427         USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh,
1428             "usbsacm_fifo_flush_locked: ");
1429 
1430         /* flush transmit FIFO if DS_TX is set */
1431         if ((dir & DS_TX) && acm_port->acm_tx_mp) {
1432                 freemsg(acm_port->acm_tx_mp);
1433                 acm_port->acm_tx_mp = NULL;
1434         }
1435         /* flush received FIFO if DS_RX is set */
1436         if ((dir & DS_RX) && acm_port->acm_rx_mp) {
1437                 freemsg(acm_port->acm_rx_mp);
1438                 acm_port->acm_rx_mp = NULL;
1439         }
1440 
1441         return (USB_SUCCESS);
1442 }
1443 
1444 
1445 /*
1446  * usbsacm_get_bulk_pipe_number:
1447  *      Calculate the number of bulk in or out pipes in current device.
1448  */
1449 static int
1450 usbsacm_get_bulk_pipe_number(usbsacm_state_t *acmp, uint_t dir)
1451 {
1452         int             count = 0;
1453         int             i, skip;
1454         usb_if_data_t   *cur_if;
1455         int             ep_num;
1456         int             if_num;
1457 
1458         USB_DPRINTF_L4(PRINT_MASK_ATTA, acmp->acm_lh,
1459             "usbsacm_get_bulk_pipe_number: ");
1460 
1461         cur_if = acmp->acm_dev_data->dev_curr_cfg->cfg_if;
1462         if_num = acmp->acm_dev_data->dev_curr_cfg->cfg_n_if;
1463 
1464         /* search each interface which have bulk endpoint */
1465         for (i = 0; i < if_num; i++) {
1466                 ep_num = cur_if->if_alt->altif_n_ep;
1467 
1468                 /*
1469                  * search endpoints in current interface,
1470                  * which type is input parameter 'dir'
1471                  */
1472                 for (skip = 0; skip < ep_num; skip++) {
1473                         if (usb_lookup_ep_data(acmp->acm_dip,
1474                             acmp->acm_dev_data, i, 0, skip,
1475                             USB_EP_ATTR_BULK, dir) == NULL) {
1476 
1477                                 /*
1478                                  * If not found, skip the internal loop
1479                                  * and search the next interface.
1480                                  */
1481                                 break;
1482                         }
1483                         count++;
1484                 }
1485 
1486                 cur_if++;
1487         }
1488 
1489         return (count);
1490 }
1491 
1492 
1493 /*
1494  * port management
1495  * ---------------
1496  *      initialize, release port.
1497  *
1498  *
1499  * usbsacm_init_ports_status:
1500  *      Initialize the port status for the current device.
1501  */
1502 static int
1503 usbsacm_init_ports_status(usbsacm_state_t *acmp)
1504 {
1505         usbsacm_port_t  *cur_port;
1506         int             i, skip;
1507         int             if_num;
1508         int             intr_if_no = 0;
1509         int             ep_num;
1510         usb_if_data_t   *cur_if;
1511 
1512         USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh,
1513             "usbsacm_init_ports_status: acmp = 0x%p", (void *)acmp);
1514 
1515         /* Initialize the port status to default value */
1516         for (i = 0; i < acmp->acm_port_cnt; i++) {
1517                 cur_port = &acmp->acm_ports[i];
1518 
1519                 cv_init(&cur_port->acm_tx_cv, NULL, CV_DRIVER, NULL);
1520 
1521                 cur_port->acm_port_state = USBSACM_PORT_CLOSED;
1522 
1523                 cur_port->acm_line_coding.dwDTERate = LE_32((uint32_t)9600);
1524                 cur_port->acm_line_coding.bCharFormat = 0;
1525                 cur_port->acm_line_coding.bParityType = USB_CDC_PARITY_NO;
1526                 cur_port->acm_line_coding.bDataBits = 8;
1527                 cur_port->acm_device = acmp;
1528                 mutex_init(&cur_port->acm_port_mutex, NULL, MUTEX_DRIVER,
1529                     acmp->acm_dev_data->dev_iblock_cookie);
1530         }
1531 
1532         /*
1533          * If device conform to cdc acm spec, parse function descriptors.
1534          */
1535         if (acmp->acm_compatibility == B_TRUE) {
1536 
1537                 if (usbsacm_get_descriptors(acmp) != USB_SUCCESS) {
1538 
1539                         return (USB_FAILURE);
1540                 }
1541 
1542                 return (USB_SUCCESS);
1543         }
1544 
1545         /*
1546          * If device don't conform to spec, search pairs of bulk in/out
1547          * endpoints and fill port structure.
1548          */
1549         cur_if = acmp->acm_dev_data->dev_curr_cfg->cfg_if;
1550         if_num = acmp->acm_dev_data->dev_curr_cfg->cfg_n_if;
1551         cur_port = acmp->acm_ports;
1552 
1553         /* search each interface which have bulk in and out */
1554         for (i = 0; i < if_num; i++) {
1555                 ep_num = cur_if->if_alt->altif_n_ep;
1556 
1557                 for (skip = 0; skip < ep_num; skip++) {
1558 
1559                 /* search interrupt pipe. */
1560                 if ((usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1561                     i, 0, skip, USB_EP_ATTR_INTR, USB_EP_DIR_IN) != NULL)) {
1562 
1563                         intr_if_no = i;
1564                 }
1565 
1566                 /* search pair of bulk in/out endpoints. */
1567                 if ((usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1568                     i, 0, skip, USB_EP_ATTR_BULK, USB_EP_DIR_IN) == NULL) ||
1569                     (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1570                     i, 0, skip, USB_EP_ATTR_BULK, USB_EP_DIR_OUT) == NULL)) {
1571 
1572                         continue;
1573                 }
1574 
1575                 cur_port->acm_data_if_no = i;
1576                 cur_port->acm_ctrl_if_no = intr_if_no;
1577                 cur_port->acm_data_port_no = skip;
1578                 cur_port++;
1579                 intr_if_no = 0;
1580                 }
1581 
1582                 cur_if++;
1583         }
1584 
1585         return (USB_SUCCESS);
1586 }
1587 
1588 
1589 /*
1590  * usbsacm_init_alloc_ports:
1591  *      Allocate memory and initialize the port state for the current device.
1592  */
1593 static int
1594 usbsacm_init_alloc_ports(usbsacm_state_t *acmp)
1595 {
1596         int             rval = USB_SUCCESS;
1597         int             count_in = 0, count_out = 0;
1598 
1599         if (acmp->acm_compatibility) {
1600                 acmp->acm_port_cnt = 1;
1601         } else {
1602                 /* Calculate the number of the bulk in/out endpoints */
1603                 count_in = usbsacm_get_bulk_pipe_number(acmp, USB_EP_DIR_IN);
1604                 count_out = usbsacm_get_bulk_pipe_number(acmp, USB_EP_DIR_OUT);
1605 
1606                 USB_DPRINTF_L3(PRINT_MASK_OPEN, acmp->acm_lh,
1607                     "usbsacm_init_alloc_ports: count_in = %d, count_out = %d",
1608                     count_in, count_out);
1609 
1610                 acmp->acm_port_cnt = min(count_in, count_out);
1611         }
1612 
1613         /* return if not found any pair of bulk in/out endpoint. */
1614         if (acmp->acm_port_cnt == 0) {
1615                 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
1616                     "usbsacm_init_alloc_ports: port count is zero.");
1617 
1618                 return (USB_FAILURE);
1619         }
1620 
1621         /* allocate memory for ports */
1622         acmp->acm_ports = (usbsacm_port_t *)kmem_zalloc(acmp->acm_port_cnt *
1623             sizeof (usbsacm_port_t), KM_SLEEP);
1624         if (acmp->acm_ports == NULL) {
1625                 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
1626                     "usbsacm_init_alloc_ports: allocate memory failed.");
1627 
1628                 return (USB_FAILURE);
1629         }
1630 
1631         /* fill the status of port structure. */
1632         rval = usbsacm_init_ports_status(acmp);
1633         if (rval != USB_SUCCESS) {
1634                 usbsacm_free_ports(acmp);
1635         }
1636 
1637         return (rval);
1638 }
1639 
1640 
1641 /*
1642  * usbsacm_free_ports:
1643  *      Release ports and deallocate memory.
1644  */
1645 static void
1646 usbsacm_free_ports(usbsacm_state_t *acmp)
1647 {
1648         int             i;
1649 
1650         USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
1651             "usbsacm_free_ports: ");
1652 
1653         /* Release memory and data structure for each port */
1654         for (i = 0; i < acmp->acm_port_cnt; i++) {
1655                 cv_destroy(&acmp->acm_ports[i].acm_tx_cv);
1656                 mutex_destroy(&acmp->acm_ports[i].acm_port_mutex);
1657         }
1658         kmem_free((caddr_t)acmp->acm_ports, sizeof (usbsacm_port_t) *
1659             acmp->acm_port_cnt);
1660         acmp->acm_ports = NULL;
1661 }
1662 
1663 
1664 /*
1665  * usbsacm_get_descriptors:
1666  *      analysis functional descriptors of acm device
1667  */
1668 static int
1669 usbsacm_get_descriptors(usbsacm_state_t *acmp)
1670 {
1671         int                     i;
1672         usb_cfg_data_t          *cfg;
1673         usb_alt_if_data_t       *altif;
1674         usb_cvs_data_t          *cvs;
1675         int                     mgmt_cap = 0;
1676         int                     master_if = -1, slave_if = -1;
1677         usbsacm_port_t          *acm_port = acmp->acm_ports;
1678 
1679         USB_DPRINTF_L4(PRINT_MASK_ATTA, acmp->acm_lh,
1680             "usbsacm_get_descriptors: ");
1681 
1682         cfg = acmp->acm_dev_data->dev_curr_cfg;
1683         /* set default control and data interface */
1684         acm_port->acm_ctrl_if_no = acm_port->acm_data_if_no = 0;
1685 
1686         /* get current interfaces */
1687         acm_port->acm_ctrl_if_no = acmp->acm_dev_data->dev_curr_if;
1688         if (cfg->cfg_if[acm_port->acm_ctrl_if_no].if_n_alt == 0) {
1689                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1690                     "usbsacm_get_descriptors: elements in if_alt is %d",
1691                     cfg->cfg_if[acm_port->acm_ctrl_if_no].if_n_alt);
1692 
1693                 return (USB_FAILURE);
1694         }
1695 
1696         altif = &cfg->cfg_if[acm_port->acm_ctrl_if_no].if_alt[0];
1697 
1698         /*
1699          * Based on CDC specification, ACM devices usually include the
1700          * following function descriptors: Header, ACM, Union and Call
1701          * Management function descriptors. This loop search tree data
1702          * structure for each acm class descriptor.
1703          */
1704         for (i = 0; i < altif->altif_n_cvs; i++) {
1705 
1706                 cvs = &altif->altif_cvs[i];
1707 
1708                 if ((cvs->cvs_buf == NULL) ||
1709                     (cvs->cvs_buf[1] != USB_CDC_CS_INTERFACE)) {
1710                         continue;
1711                 }
1712 
1713                 switch (cvs->cvs_buf[2]) {
1714                 case USB_CDC_DESCR_TYPE_CALL_MANAGEMENT:
1715                         /* parse call management functional descriptor. */
1716                         if (cvs->cvs_buf_len >= 5) {
1717                                 mgmt_cap = cvs->cvs_buf[3];
1718                                 acm_port->acm_data_if_no = cvs->cvs_buf[4];
1719                         }
1720                         break;
1721                 case USB_CDC_DESCR_TYPE_ACM:
1722                         /* parse ACM functional descriptor. */
1723                         if (cvs->cvs_buf_len >= 4) {
1724                                 acm_port->acm_cap = cvs->cvs_buf[3];
1725                         }
1726                         break;
1727                 case USB_CDC_DESCR_TYPE_UNION:
1728                         /* parse Union functional descriptor. */
1729                         if (cvs->cvs_buf_len >= 5) {
1730                                 master_if = cvs->cvs_buf[3];
1731                                 slave_if = cvs->cvs_buf[4];
1732                         }
1733                         break;
1734                 default:
1735                         break;
1736                 }
1737         }
1738 
1739         /* For usb acm devices, it must satisfy the following options. */
1740         if (cfg->cfg_n_if < 2) {
1741                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1742                     "usbsacm_get_descriptors: # of interfaces %d < 2",
1743                     cfg->cfg_n_if);
1744 
1745                 return (USB_FAILURE);
1746         }
1747 
1748         if (acm_port->acm_data_if_no == 0 &&
1749             slave_if != acm_port->acm_data_if_no) {
1750                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1751                     "usbsacm_get_descriptors: Device hasn't call management "
1752                     "descriptor and use Union Descriptor.");
1753 
1754                 acm_port->acm_data_if_no = slave_if;
1755         }
1756 
1757         if ((master_if != acm_port->acm_ctrl_if_no) ||
1758             (slave_if != acm_port->acm_data_if_no)) {
1759                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1760                     "usbsacm_get_descriptors: control interface or "
1761                     "data interface don't match.");
1762 
1763                 return (USB_FAILURE);
1764         }
1765 
1766         /*
1767          * We usually need both call and data capabilities, but
1768          * some devices, such as Nokia mobile phones, don't provide
1769          * call management descriptor, so we just give a warning
1770          * message.
1771          */
1772         if (((mgmt_cap & USB_CDC_CALL_MGMT_CAP_CALL_MGMT) == 0) ||
1773             ((mgmt_cap & USB_CDC_CALL_MGMT_CAP_DATA_INTERFACE) == 0)) {
1774                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1775                     "usbsacm_get_descriptors: "
1776                     "insufficient mgmt capabilities %x",
1777                     mgmt_cap);
1778         }
1779 
1780         if ((acm_port->acm_ctrl_if_no >= cfg->cfg_n_if) ||
1781             (acm_port->acm_data_if_no >= cfg->cfg_n_if)) {
1782                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1783                     "usbsacm_get_descriptors: control interface %d or "
1784                     "data interface %d out of range.",
1785                     acm_port->acm_ctrl_if_no, acm_port->acm_data_if_no);
1786 
1787                 return (USB_FAILURE);
1788         }
1789 
1790         /* control interface must have interrupt endpoint */
1791         if (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1792             acm_port->acm_ctrl_if_no, 0, 0, USB_EP_ATTR_INTR,
1793             USB_EP_DIR_IN) == NULL) {
1794                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1795                     "usbsacm_get_descriptors: "
1796                     "ctrl interface %d has no interrupt endpoint",
1797                     acm_port->acm_data_if_no);
1798 
1799                 return (USB_FAILURE);
1800         }
1801 
1802         /* data interface must have bulk in and out */
1803         if (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1804             acm_port->acm_data_if_no, 0, 0, USB_EP_ATTR_BULK,
1805             USB_EP_DIR_IN) == NULL) {
1806                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1807                     "usbsacm_get_descriptors: "
1808                     "data interface %d has no bulk in endpoint",
1809                     acm_port->acm_data_if_no);
1810 
1811                 return (USB_FAILURE);
1812         }
1813         if (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1814             acm_port->acm_data_if_no, 0, 0, USB_EP_ATTR_BULK,
1815             USB_EP_DIR_OUT) == NULL) {
1816                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1817                     "usbsacm_get_descriptors: "
1818                     "data interface %d has no bulk out endpoint",
1819                     acm_port->acm_data_if_no);
1820 
1821                 return (USB_FAILURE);
1822         }
1823 
1824         return (USB_SUCCESS);
1825 }
1826 
1827 
1828 /*
1829  * usbsacm_cleanup:
1830  *      Release resources of current device during detach.
1831  */
1832 static void
1833 usbsacm_cleanup(usbsacm_state_t *acmp)
1834 {
1835         USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
1836             "usbsacm_cleanup: ");
1837 
1838         if (acmp != NULL) {
1839                 /* free ports */
1840                 if (acmp->acm_ports != NULL) {
1841                         usbsacm_free_ports(acmp);
1842                 }
1843 
1844                 /* unregister callback function */
1845                 if (acmp->acm_usb_events != NULL) {
1846                         usb_unregister_event_cbs(acmp->acm_dip,
1847                             acmp->acm_usb_events);
1848                 }
1849 
1850                 /* destroy power management components */
1851                 if (acmp->acm_pm != NULL) {
1852                         usbsacm_destroy_pm_components(acmp);
1853                 }
1854 
1855                 /* free description of device tree. */
1856                 if (acmp->acm_def_ph != NULL) {
1857                         mutex_destroy(&acmp->acm_mutex);
1858 
1859                         usb_free_descr_tree(acmp->acm_dip, acmp->acm_dev_data);
1860                         acmp->acm_def_ph = NULL;
1861                 }
1862 
1863                 if (acmp->acm_lh != NULL) {
1864                         usb_free_log_hdl(acmp->acm_lh);
1865                         acmp->acm_lh = NULL;
1866                 }
1867 
1868                 /* detach client device */
1869                 if (acmp->acm_dev_data != NULL) {
1870                         usb_client_detach(acmp->acm_dip, acmp->acm_dev_data);
1871                 }
1872 
1873                 kmem_free((caddr_t)acmp, sizeof (usbsacm_state_t));
1874         }
1875 }
1876 
1877 
1878 /*
1879  * usbsacm_restore_device_state:
1880  *      restore device state after CPR resume or reconnect
1881  */
1882 static int
1883 usbsacm_restore_device_state(usbsacm_state_t *acmp)
1884 {
1885         int     state;
1886 
1887         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
1888             "usbsacm_restore_device_state: ");
1889 
1890         mutex_enter(&acmp->acm_mutex);
1891         state = acmp->acm_dev_state;
1892         mutex_exit(&acmp->acm_mutex);
1893 
1894         /* Check device status */
1895         if ((state != USB_DEV_DISCONNECTED) && (state != USB_DEV_SUSPENDED)) {
1896 
1897                 return (state);
1898         }
1899 
1900         /* Check if we are talking to the same device */
1901         if (usb_check_same_device(acmp->acm_dip, acmp->acm_lh, USB_LOG_L0,
1902             -1, USB_CHK_ALL, NULL) != USB_SUCCESS) {
1903                 mutex_enter(&acmp->acm_mutex);
1904                 state = acmp->acm_dev_state = USB_DEV_DISCONNECTED;
1905                 mutex_exit(&acmp->acm_mutex);
1906 
1907                 return (state);
1908         }
1909 
1910         if (state == USB_DEV_DISCONNECTED) {
1911                 USB_DPRINTF_L1(PRINT_MASK_ALL, acmp->acm_lh,
1912                     "usbsacm_restore_device_state: Device has been reconnected "
1913                     "but data may have been lost");
1914         }
1915 
1916         /* reconnect pipes */
1917         if (usbsacm_reconnect_pipes(acmp) != USB_SUCCESS) {
1918 
1919                 return (state);
1920         }
1921 
1922         /*
1923          * init device state
1924          */
1925         mutex_enter(&acmp->acm_mutex);
1926         state = acmp->acm_dev_state = USB_DEV_ONLINE;
1927         mutex_exit(&acmp->acm_mutex);
1928 
1929         if ((usbsacm_restore_port_state(acmp) != USB_SUCCESS)) {
1930                 USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1931                     "usbsacm_restore_device_state: failed");
1932         }
1933 
1934         return (state);
1935 }
1936 
1937 
1938 /*
1939  * usbsacm_restore_port_state:
1940  *      restore ports state after CPR resume or reconnect
1941  */
1942 static int
1943 usbsacm_restore_port_state(usbsacm_state_t *acmp)
1944 {
1945         int             i, ret = USB_SUCCESS;
1946         usbsacm_port_t  *cur_port;
1947 
1948         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
1949             "usbsacm_restore_port_state: ");
1950 
1951         /* restore status of all ports */
1952         for (i = 0; i < acmp->acm_port_cnt; i++) {
1953                 cur_port = &acmp->acm_ports[i];
1954                 mutex_enter(&cur_port->acm_port_mutex);
1955                 if (cur_port->acm_port_state != USBSACM_PORT_OPEN) {
1956                         mutex_exit(&cur_port->acm_port_mutex);
1957 
1958                         continue;
1959                 }
1960                 mutex_exit(&cur_port->acm_port_mutex);
1961 
1962                 if ((ret = usbsacm_set_line_coding(cur_port,
1963                     &cur_port->acm_line_coding)) != USB_SUCCESS) {
1964                         USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1965                             "usbsacm_restore_port_state: failed.");
1966                 }
1967         }
1968 
1969         return (ret);
1970 }
1971 
1972 
1973 /*
1974  * pipe management
1975  * ---------------
1976  *
1977  *
1978  * usbsacm_open_port_pipes:
1979  *      Open pipes of one port and set port structure;
1980  *      Each port includes three pipes: bulk in, bulk out and interrupt.
1981  */
1982 static int
1983 usbsacm_open_port_pipes(usbsacm_port_t *acm_port)
1984 {
1985         int             rval = USB_SUCCESS;
1986         usbsacm_state_t *acmp = acm_port->acm_device;
1987         usb_ep_data_t   *in_data, *out_data, *intr_pipe;
1988         usb_pipe_policy_t policy;
1989 
1990         USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh,
1991             "usbsacm_open_port_pipes: acmp = 0x%p", (void *)acmp);
1992 
1993         /* Get bulk and interrupt endpoint data */
1994         intr_pipe = usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1995             acm_port->acm_ctrl_if_no, 0, 0,
1996             USB_EP_ATTR_INTR, USB_EP_DIR_IN);
1997         in_data = usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1998             acm_port->acm_data_if_no, 0, acm_port->acm_data_port_no,
1999             USB_EP_ATTR_BULK, USB_EP_DIR_IN);
2000         out_data = usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
2001             acm_port->acm_data_if_no, 0, acm_port->acm_data_port_no,
2002             USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
2003 
2004         /* Bulk in and out must exist meanwhile. */
2005         if ((in_data == NULL) || (out_data == NULL)) {
2006                 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2007                     "usbsacm_open_port_pipes: look up bulk pipe failed in "
2008                     "interface %d port %d",
2009                     acm_port->acm_data_if_no, acm_port->acm_data_port_no);
2010 
2011                 return (USB_FAILURE);
2012         }
2013 
2014         /*
2015          * If device conform to acm spec, it must have an interrupt pipe
2016          * for this port.
2017          */
2018         if (acmp->acm_compatibility == B_TRUE && intr_pipe == NULL) {
2019                 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2020                     "usbsacm_open_port_pipes: look up interrupt pipe failed in "
2021                     "interface %d", acm_port->acm_ctrl_if_no);
2022 
2023                 return (USB_FAILURE);
2024         }
2025 
2026         policy.pp_max_async_reqs = 2;
2027 
2028         /* Open bulk in endpoint */
2029         if (usb_pipe_open(acmp->acm_dip, &in_data->ep_descr, &policy,
2030             USB_FLAGS_SLEEP, &acm_port->acm_bulkin_ph) != USB_SUCCESS) {
2031                 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2032                     "usbsacm_open_port_pipes: open bulkin pipe failed!");
2033 
2034                 return (USB_FAILURE);
2035         }
2036 
2037         /* Open bulk out endpoint */
2038         if (usb_pipe_open(acmp->acm_dip, &out_data->ep_descr, &policy,
2039             USB_FLAGS_SLEEP, &acm_port->acm_bulkout_ph) != USB_SUCCESS) {
2040                 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2041                     "usbsacm_open_port_pipes: open bulkout pipe failed!");
2042 
2043                 usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkin_ph,
2044                     USB_FLAGS_SLEEP, NULL, NULL);
2045 
2046                 return (USB_FAILURE);
2047         }
2048 
2049         /* Open interrupt endpoint if found. */
2050         if (intr_pipe != NULL) {
2051 
2052                 if (usb_pipe_open(acmp->acm_dip, &intr_pipe->ep_descr, &policy,
2053                     USB_FLAGS_SLEEP, &acm_port->acm_intr_ph) != USB_SUCCESS) {
2054                         USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2055                             "usbsacm_open_port_pipes: "
2056                             "open control pipe failed");
2057 
2058                         usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkin_ph,
2059                             USB_FLAGS_SLEEP, NULL, NULL);
2060                         usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkout_ph,
2061                             USB_FLAGS_SLEEP, NULL, NULL);
2062 
2063                         return (USB_FAILURE);
2064                 }
2065         }
2066 
2067         /* initialize the port structure. */
2068         mutex_enter(&acm_port->acm_port_mutex);
2069         acm_port->acm_bulkin_size = in_data->ep_descr.wMaxPacketSize;
2070         acm_port->acm_bulkin_state = USBSACM_PIPE_IDLE;
2071         acm_port->acm_bulkout_state = USBSACM_PIPE_IDLE;
2072         if (acm_port->acm_intr_ph != NULL) {
2073                 acm_port->acm_intr_state = USBSACM_PIPE_IDLE;
2074                 acm_port->acm_intr_ep_descr = intr_pipe->ep_descr;
2075         }
2076         mutex_exit(&acm_port->acm_port_mutex);
2077 
2078         if (acm_port->acm_intr_ph != NULL) {
2079 
2080                 usbsacm_pipe_start_polling(acm_port);
2081         }
2082 
2083         return (rval);
2084 }
2085 
2086 
2087 /*
2088  * usbsacm_close_port_pipes:
2089  *      Close pipes of one port and reset port structure to closed;
2090  *      Each port includes three pipes: bulk in, bulk out and interrupt.
2091  */
2092 static void
2093 usbsacm_close_port_pipes(usbsacm_port_t *acm_port)
2094 {
2095         usbsacm_state_t *acmp = acm_port->acm_device;
2096 
2097         mutex_enter(&acm_port->acm_port_mutex);
2098         USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
2099             "usbsacm_close_port_pipes: acm_bulkin_state = %d",
2100             acm_port->acm_bulkin_state);
2101 
2102         /*
2103          * Check the status of the given port. If port is closing or closed,
2104          * return directly.
2105          */
2106         if ((acm_port->acm_bulkin_state == USBSACM_PIPE_CLOSED) ||
2107             (acm_port->acm_bulkin_state == USBSACM_PIPE_CLOSING)) {
2108                 USB_DPRINTF_L2(PRINT_MASK_CLOSE, acmp->acm_lh,
2109                     "usbsacm_close_port_pipes: port is closing or has closed");
2110                 mutex_exit(&acm_port->acm_port_mutex);
2111 
2112                 return;
2113         }
2114 
2115         acm_port->acm_bulkin_state = USBSACM_PIPE_CLOSING;
2116         mutex_exit(&acm_port->acm_port_mutex);
2117 
2118         /* Close pipes */
2119         usb_pipe_reset(acmp->acm_dip, acm_port->acm_bulkin_ph,
2120             USB_FLAGS_SLEEP, 0, 0);
2121         usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkin_ph,
2122             USB_FLAGS_SLEEP, 0, 0);
2123         usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkout_ph,
2124             USB_FLAGS_SLEEP, 0, 0);
2125         if (acm_port->acm_intr_ph != NULL) {
2126                 usb_pipe_stop_intr_polling(acm_port->acm_intr_ph,
2127                     USB_FLAGS_SLEEP);
2128                 usb_pipe_close(acmp->acm_dip, acm_port->acm_intr_ph,
2129                     USB_FLAGS_SLEEP, 0, 0);
2130         }
2131 
2132         mutex_enter(&acm_port->acm_port_mutex);
2133         /* Reset the status of pipes to closed */
2134         acm_port->acm_bulkin_state = USBSACM_PIPE_CLOSED;
2135         acm_port->acm_bulkin_ph = NULL;
2136         acm_port->acm_bulkout_state = USBSACM_PIPE_CLOSED;
2137         acm_port->acm_bulkout_ph = NULL;
2138         if (acm_port->acm_intr_ph != NULL) {
2139                 acm_port->acm_intr_state = USBSACM_PIPE_CLOSED;
2140                 acm_port->acm_intr_ph = NULL;
2141         }
2142 
2143         mutex_exit(&acm_port->acm_port_mutex);
2144 
2145         USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
2146             "usbsacm_close_port_pipes: port has been closed.");
2147 }
2148 
2149 
2150 /*
2151  * usbsacm_close_pipes:
2152  *      close all opened pipes of current devices.
2153  */
2154 static void
2155 usbsacm_close_pipes(usbsacm_state_t *acmp)
2156 {
2157         int             i;
2158 
2159         USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
2160             "usbsacm_close_pipes: ");
2161 
2162         /* Close all ports */
2163         for (i = 0; i < acmp->acm_port_cnt; i++) {
2164                 usbsacm_close_port_pipes(&acmp->acm_ports[i]);
2165         }
2166 }
2167 
2168 
2169 /*
2170  * usbsacm_disconnect_pipes:
2171  *      this function just call usbsacm_close_pipes.
2172  */
2173 static void
2174 usbsacm_disconnect_pipes(usbsacm_state_t *acmp)
2175 {
2176         USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
2177             "usbsacm_disconnect_pipes: ");
2178 
2179         usbsacm_close_pipes(acmp);
2180 }
2181 
2182 
2183 /*
2184  * usbsacm_reconnect_pipes:
2185  *      reconnect pipes in CPR resume or reconnect
2186  */
2187 static int
2188 usbsacm_reconnect_pipes(usbsacm_state_t *acmp)
2189 {
2190         usbsacm_port_t  *cur_port = acmp->acm_ports;
2191         int             i;
2192 
2193         USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh,
2194             "usbsacm_reconnect_pipes: ");
2195 
2196         /* reopen all ports of current device. */
2197         for (i = 0; i < acmp->acm_port_cnt; i++) {
2198                 cur_port = &acmp->acm_ports[i];
2199 
2200                 mutex_enter(&cur_port->acm_port_mutex);
2201                 /*
2202                  * If port status is open, reopen it;
2203                  * else retain the current status.
2204                  */
2205                 if (cur_port->acm_port_state == USBSACM_PORT_OPEN) {
2206 
2207                         mutex_exit(&cur_port->acm_port_mutex);
2208                         if (usbsacm_open_port_pipes(cur_port) != USB_SUCCESS) {
2209                                 USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh,
2210                                     "usbsacm_reconnect_pipes: "
2211                                     "open port %d failed.", i);
2212 
2213                                 return (USB_FAILURE);
2214                         }
2215                         mutex_enter(&cur_port->acm_port_mutex);
2216                 }
2217                 mutex_exit(&cur_port->acm_port_mutex);
2218         }
2219 
2220         return (USB_SUCCESS);
2221 }
2222 
2223 /*
2224  * usbsacm_bulkin_cb:
2225  *      Bulk In regular and exeception callback;
2226  *      USBA framework will call this callback
2227  *      after deal with bulkin request.
2228  */
2229 /*ARGSUSED*/
2230 static void
2231 usbsacm_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
2232 {
2233         usbsacm_port_t  *acm_port = (usbsacm_port_t *)req->bulk_client_private;
2234         usbsacm_state_t *acmp = acm_port->acm_device;
2235         mblk_t          *data;
2236         int             data_len;
2237 
2238         data = req->bulk_data;
2239         data_len = (data) ? MBLKL(data) : 0;
2240 
2241         mutex_enter(&acm_port->acm_port_mutex);
2242         USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh,
2243             "usbsacm_bulkin_cb: "
2244             "acm_bulkin_state = %d acm_port_state = %d data_len = %d",
2245             acm_port->acm_bulkin_state, acm_port->acm_port_state, data_len);
2246 
2247         if ((acm_port->acm_port_state == USBSACM_PORT_OPEN) && (data_len) &&
2248             (req->bulk_completion_reason == USB_CR_OK)) {
2249                 mutex_exit(&acm_port->acm_port_mutex);
2250                 /* prevent USBA from freeing data along with the request */
2251                 req->bulk_data = NULL;
2252 
2253                 /* save data on the receive list */
2254                 usbsacm_put_tail(&acm_port->acm_rx_mp, data);
2255 
2256                 /* invoke GSD receive callback */
2257                 if (acm_port->acm_cb.cb_rx) {
2258                         acm_port->acm_cb.cb_rx(acm_port->acm_cb.cb_arg);
2259                 }
2260                 mutex_enter(&acm_port->acm_port_mutex);
2261         }
2262         mutex_exit(&acm_port->acm_port_mutex);
2263 
2264         usb_free_bulk_req(req);
2265 
2266         /* receive more */
2267         mutex_enter(&acm_port->acm_port_mutex);
2268         if (((acm_port->acm_bulkin_state == USBSACM_PIPE_BUSY) ||
2269             (acm_port->acm_bulkin_state == USBSACM_PIPE_IDLE)) &&
2270             (acm_port->acm_port_state == USBSACM_PORT_OPEN) &&
2271             (acmp->acm_dev_state == USB_DEV_ONLINE)) {
2272                 if (usbsacm_rx_start(acm_port) != USB_SUCCESS) {
2273                         USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2274                             "usbsacm_bulkin_cb: restart rx fail "
2275                             "acm_port_state = %d", acm_port->acm_port_state);
2276                 }
2277         } else if (acm_port->acm_bulkin_state == USBSACM_PIPE_BUSY) {
2278                 acm_port->acm_bulkin_state = USBSACM_PIPE_IDLE;
2279         }
2280         mutex_exit(&acm_port->acm_port_mutex);
2281 }
2282 
2283 
2284 /*
2285  * usbsacm_bulkout_cb:
2286  *      Bulk Out regular and exeception callback;
2287  *      USBA framework will call this callback function
2288  *      after deal with bulkout request.
2289  */
2290 /*ARGSUSED*/
2291 static void
2292 usbsacm_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
2293 {
2294         usbsacm_port_t  *acm_port = (usbsacm_port_t *)req->bulk_client_private;
2295         usbsacm_state_t *acmp = acm_port->acm_device;
2296         int             data_len;
2297         mblk_t          *data = req->bulk_data;
2298 
2299         USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh,
2300             "usbsacm_bulkout_cb: acmp = 0x%p", (void *)acmp);
2301 
2302         data_len = (req->bulk_data) ? MBLKL(req->bulk_data) : 0;
2303 
2304         /* put untransferred residue back on the transfer list */
2305         if (req->bulk_completion_reason && (data_len > 0)) {
2306                 usbsacm_put_head(&acm_port->acm_tx_mp, data);
2307                 req->bulk_data = NULL;
2308         }
2309 
2310         usb_free_bulk_req(req);
2311 
2312         /* invoke GSD transmit callback */
2313         if (acm_port->acm_cb.cb_tx) {
2314                 acm_port->acm_cb.cb_tx(acm_port->acm_cb.cb_arg);
2315         }
2316 
2317         /* send more */
2318         mutex_enter(&acm_port->acm_port_mutex);
2319         acm_port->acm_bulkout_state = USBSACM_PIPE_IDLE;
2320         if (acm_port->acm_tx_mp == NULL) {
2321                 cv_broadcast(&acm_port->acm_tx_cv);
2322         } else {
2323                 usbsacm_tx_start(acm_port);
2324         }
2325         mutex_exit(&acm_port->acm_port_mutex);
2326 }
2327 
2328 
2329 /*
2330  * usbsacm_rx_start:
2331  *      start data receipt
2332  */
2333 static int
2334 usbsacm_rx_start(usbsacm_port_t *acm_port)
2335 {
2336         usbsacm_state_t *acmp = acm_port->acm_device;
2337         usb_bulk_req_t  *br;
2338         int             rval = USB_FAILURE;
2339         int             data_len;
2340 
2341         USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh,
2342             "usbsacm_rx_start: acm_xfer_sz = 0x%lx acm_bulkin_size = 0x%lx",
2343             acmp->acm_xfer_sz, acm_port->acm_bulkin_size);
2344 
2345         acm_port->acm_bulkin_state = USBSACM_PIPE_BUSY;
2346         /*
2347          * Qualcomm CDMA card won't response the first request,
2348          * if the following code don't multiply by 2.
2349          */
2350         data_len = min(acmp->acm_xfer_sz, acm_port->acm_bulkin_size * 2);
2351         mutex_exit(&acm_port->acm_port_mutex);
2352 
2353         br = usb_alloc_bulk_req(acmp->acm_dip, data_len, USB_FLAGS_SLEEP);
2354         if (br == NULL) {
2355                 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2356                     "usbsacm_rx_start: allocate bulk request failed");
2357 
2358                 mutex_enter(&acm_port->acm_port_mutex);
2359 
2360                 return (USB_FAILURE);
2361         }
2362         /* initialize bulk in request. */
2363         br->bulk_len = data_len;
2364         br->bulk_timeout = USBSACM_BULKIN_TIMEOUT;
2365         br->bulk_cb = usbsacm_bulkin_cb;
2366         br->bulk_exc_cb = usbsacm_bulkin_cb;
2367         br->bulk_client_private = (usb_opaque_t)acm_port;
2368         br->bulk_attributes = USB_ATTRS_AUTOCLEARING
2369             | USB_ATTRS_SHORT_XFER_OK;
2370 
2371         rval = usb_pipe_bulk_xfer(acm_port->acm_bulkin_ph, br, 0);
2372 
2373         mutex_enter(&acm_port->acm_port_mutex);
2374         if (rval != USB_SUCCESS) {
2375                 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2376                     "usbsacm_rx_start: bulk transfer failed %d", rval);
2377                 usb_free_bulk_req(br);
2378                 acm_port->acm_bulkin_state = USBSACM_PIPE_IDLE;
2379         }
2380 
2381         return (rval);
2382 }
2383 
2384 
2385 /*
2386  * usbsacm_tx_start:
2387  *      start data transmit
2388  */
2389 static void
2390 usbsacm_tx_start(usbsacm_port_t *acm_port)
2391 {
2392         int             len;            /* bytes we can transmit */
2393         mblk_t          *data;          /* data to be transmitted */
2394         int             data_len;       /* bytes in 'data' */
2395         mblk_t          *mp;            /* current msgblk */
2396         int             copylen;        /* bytes copy from 'mp' to 'data' */
2397         int             rval;
2398         usbsacm_state_t *acmp = acm_port->acm_device;
2399 
2400         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
2401             "usbsacm_tx_start: ");
2402 
2403         /* check the transmitted data. */
2404         if (acm_port->acm_tx_mp == NULL) {
2405                 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2406                     "usbsacm_tx_start: acm_tx_mp is NULL");
2407 
2408                 return;
2409         }
2410 
2411         /* check pipe status */
2412         if (acm_port->acm_bulkout_state != USBSACM_PIPE_IDLE) {
2413 
2414                 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2415                     "usbsacm_tx_start: error state in bulkout endpoint");
2416 
2417                 return;
2418         }
2419         ASSERT(MBLKL(acm_port->acm_tx_mp) > 0);
2420 
2421         /* send as much data as port can receive */
2422         len = min(msgdsize(acm_port->acm_tx_mp), acmp->acm_xfer_sz);
2423 
2424         if (len == 0) {
2425                 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2426                     "usbsacm_tx_start: data len is 0");
2427 
2428                 return;
2429         }
2430 
2431         /* allocate memory for sending data. */
2432         if ((data = allocb(len, BPRI_LO)) == NULL) {
2433                 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2434                     "usbsacm_tx_start: failure in allocate memory");
2435 
2436                 return;
2437         }
2438 
2439         /*
2440          * copy no more than 'len' bytes from mblk chain to transmit mblk 'data'
2441          */
2442         data_len = 0;
2443         while ((data_len < len) && acm_port->acm_tx_mp) {
2444                 /* Get the first mblk from chain. */
2445                 mp = acm_port->acm_tx_mp;
2446                 copylen = min(MBLKL(mp), len - data_len);
2447                 bcopy(mp->b_rptr, data->b_wptr, copylen);
2448                 mp->b_rptr += copylen;
2449                 data->b_wptr += copylen;
2450                 data_len += copylen;
2451 
2452                 if (MBLKL(mp) < 1) {
2453                         acm_port->acm_tx_mp = unlinkb(mp);
2454                         freeb(mp);
2455                 } else {
2456                         ASSERT(data_len == len);
2457                 }
2458         }
2459 
2460         if (data_len <= 0) {
2461                 freeb(data);
2462 
2463                 return;
2464         }
2465 
2466         acm_port->acm_bulkout_state = USBSACM_PIPE_BUSY;
2467 
2468         mutex_exit(&acm_port->acm_port_mutex);
2469         /* send request. */
2470         rval = usbsacm_send_data(acm_port, data);
2471         mutex_enter(&acm_port->acm_port_mutex);
2472 
2473         /*
2474          * If send failed, retransmit data when acm_tx_mp is null.
2475          */
2476         if (rval != USB_SUCCESS) {
2477                 acm_port->acm_bulkout_state = USBSACM_PIPE_IDLE;
2478                 if (acm_port->acm_tx_mp == NULL) {
2479                         usbsacm_put_head(&acm_port->acm_tx_mp, data);
2480                 }
2481         }
2482 }
2483 
2484 
2485 /*
2486  * usbsacm_send_data:
2487  *      data transfer
2488  */
2489 static int
2490 usbsacm_send_data(usbsacm_port_t *acm_port, mblk_t *data)
2491 {
2492         usbsacm_state_t *acmp = acm_port->acm_device;
2493         usb_bulk_req_t  *br;
2494         int             rval;
2495         int             data_len = MBLKL(data);
2496 
2497         USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh,
2498             "usbsacm_send_data: data address is 0x%p, length = %d",
2499             (void *)data, data_len);
2500 
2501         br = usb_alloc_bulk_req(acmp->acm_dip, 0, USB_FLAGS_SLEEP);
2502         if (br == NULL) {
2503                 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2504                     "usbsacm_send_data: alloc req failed.");
2505 
2506                 return (USB_FAILURE);
2507         }
2508 
2509         /* initialize the bulk out request */
2510         br->bulk_data = data;
2511         br->bulk_len = data_len;
2512         br->bulk_timeout = USBSACM_BULKOUT_TIMEOUT;
2513         br->bulk_cb = usbsacm_bulkout_cb;
2514         br->bulk_exc_cb = usbsacm_bulkout_cb;
2515         br->bulk_client_private = (usb_opaque_t)acm_port;
2516         br->bulk_attributes = USB_ATTRS_AUTOCLEARING;
2517 
2518         rval = usb_pipe_bulk_xfer(acm_port->acm_bulkout_ph, br, 0);
2519 
2520         if (rval != USB_SUCCESS) {
2521                 USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2522                     "usbsacm_send_data: Send Data failed.");
2523 
2524                 /*
2525                  * Don't free it in usb_free_bulk_req because it will
2526                  * be linked in usbsacm_put_head
2527                  */
2528                 br->bulk_data = NULL;
2529 
2530                 usb_free_bulk_req(br);
2531         }
2532 
2533         return (rval);
2534 }
2535 
2536 /*
2537  * usbsacm_wait_tx_drain:
2538  *      wait until local tx buffer drains.
2539  *      'timeout' is in seconds, zero means wait forever
2540  */
2541 static int
2542 usbsacm_wait_tx_drain(usbsacm_port_t *acm_port, int timeout)
2543 {
2544         clock_t         until;
2545         int             over = 0;
2546 
2547         until = ddi_get_lbolt() + drv_usectohz(1000 * 1000 * timeout);
2548 
2549         while (acm_port->acm_tx_mp && !over) {
2550                 if (timeout > 0) {
2551                         over = (cv_timedwait_sig(&acm_port->acm_tx_cv,
2552                             &acm_port->acm_port_mutex, until) <= 0);
2553                 } else {
2554                         over = (cv_wait_sig(&acm_port->acm_tx_cv,
2555                             &acm_port->acm_port_mutex) == 0);
2556                 }
2557         }
2558 
2559         return ((acm_port->acm_tx_mp == NULL) ? USB_SUCCESS : USB_FAILURE);
2560 }
2561 
2562 
2563 /*
2564  * usbsacm_req_write:
2565  *      send command over control pipe
2566  */
2567 static int
2568 usbsacm_req_write(usbsacm_port_t *acm_port, uchar_t request, uint16_t value,
2569     mblk_t **data)
2570 {
2571         usbsacm_state_t *acmp = acm_port->acm_device;
2572         usb_ctrl_setup_t setup;
2573         usb_cb_flags_t  cb_flags;
2574         usb_cr_t        cr;
2575 
2576         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
2577             "usbsacm_req_write: ");
2578 
2579         /* initialize the control request. */
2580         setup.bmRequestType = USBSACM_REQ_WRITE_IF;
2581         setup.bRequest = request;
2582         setup.wValue = value;
2583         setup.wIndex = acm_port->acm_ctrl_if_no;
2584         setup.wLength = ((data != NULL) && (*data != NULL)) ? MBLKL(*data) : 0;
2585         setup.attrs = 0;
2586 
2587         return (usb_pipe_ctrl_xfer_wait(acmp->acm_def_ph, &setup, data,
2588             &cr, &cb_flags, 0));
2589 }
2590 
2591 
2592 /*
2593  * usbsacm_set_line_coding:
2594  *      Send USB_CDC_REQ_SET_LINE_CODING request
2595  */
2596 static int
2597 usbsacm_set_line_coding(usbsacm_port_t *acm_port, usb_cdc_line_coding_t *lc)
2598 {
2599         mblk_t          *bp;
2600         int             ret;
2601 
2602         /* allocate mblk and copy supplied structure into it */
2603         if ((bp = allocb(USB_CDC_LINE_CODING_LEN, BPRI_HI)) == NULL) {
2604 
2605                 return (USB_NO_RESOURCES);
2606         }
2607 
2608 #ifndef __lock_lint /* warlock gets confused here */
2609         /* LINTED E_BAD_PTR_CAST_ALIGN */
2610         *((usb_cdc_line_coding_t *)bp->b_wptr) = *lc;
2611         bp->b_wptr += USB_CDC_LINE_CODING_LEN;
2612 #endif
2613 
2614         ret = usbsacm_req_write(acm_port, USB_CDC_REQ_SET_LINE_CODING, 0, &bp);
2615 
2616         if (bp != NULL) {
2617                 freeb(bp);
2618         }
2619 
2620         return (ret);
2621 }
2622 
2623 
2624 
2625 /*
2626  * usbsacm_mctl2reg:
2627  *      Set Modem control status
2628  */
2629 static void
2630 usbsacm_mctl2reg(int mask, int val, uint8_t *line_ctl)
2631 {
2632         if (mask & TIOCM_RTS) {
2633                 if (val & TIOCM_RTS) {
2634                         *line_ctl |= USB_CDC_ACM_CONTROL_RTS;
2635                 } else {
2636                         *line_ctl &= ~USB_CDC_ACM_CONTROL_RTS;
2637                 }
2638         }
2639         if (mask & TIOCM_DTR) {
2640                 if (val & TIOCM_DTR) {
2641                         *line_ctl |= USB_CDC_ACM_CONTROL_DTR;
2642                 } else {
2643                         *line_ctl &= ~USB_CDC_ACM_CONTROL_DTR;
2644                 }
2645         }
2646 }
2647 
2648 
2649 /*
2650  * usbsacm_reg2mctl:
2651  *      Get Modem control status
2652  */
2653 static int
2654 usbsacm_reg2mctl(uint8_t line_ctl)
2655 {
2656         int     val = 0;
2657 
2658         if (line_ctl & USB_CDC_ACM_CONTROL_RTS) {
2659                 val |= TIOCM_RTS;
2660         }
2661         if (line_ctl & USB_CDC_ACM_CONTROL_DTR) {
2662                 val |= TIOCM_DTR;
2663         }
2664         if (line_ctl & USB_CDC_ACM_CONTROL_DSR) {
2665                 val |= TIOCM_DSR;
2666         }
2667         if (line_ctl & USB_CDC_ACM_CONTROL_RNG) {
2668                 val |= TIOCM_RI;
2669         }
2670 
2671         return (val);
2672 }
2673 
2674 
2675 /*
2676  * misc routines
2677  * -------------
2678  *
2679  */
2680 
2681 /*
2682  * usbsacm_put_tail:
2683  *      link a message block to tail of message
2684  *      account for the case when message is null
2685  */
2686 static void
2687 usbsacm_put_tail(mblk_t **mpp, mblk_t *bp)
2688 {
2689         if (*mpp) {
2690                 linkb(*mpp, bp);
2691         } else {
2692                 *mpp = bp;
2693         }
2694 }
2695 
2696 
2697 /*
2698  * usbsacm_put_head:
2699  *      put a message block at the head of the message
2700  *      account for the case when message is null
2701  */
2702 static void
2703 usbsacm_put_head(mblk_t **mpp, mblk_t *bp)
2704 {
2705         if (*mpp) {
2706                 linkb(bp, *mpp);
2707         }
2708         *mpp = bp;
2709 }
2710 
2711 
2712 /*
2713  * power management
2714  * ----------------
2715  *
2716  * usbsacm_create_pm_components:
2717  *      create PM components
2718  */
2719 static int
2720 usbsacm_create_pm_components(usbsacm_state_t *acmp)
2721 {
2722         dev_info_t      *dip = acmp->acm_dip;
2723         usbsacm_pm_t    *pm;
2724         uint_t          pwr_states;
2725         usb_dev_descr_t *dev_descr;
2726 
2727         USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
2728             "usbsacm_create_pm_components: ");
2729 
2730         if (usb_create_pm_components(dip, &pwr_states) != USB_SUCCESS) {
2731                 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
2732                     "usbsacm_create_pm_components: failed");
2733 
2734                 return (USB_SUCCESS);
2735         }
2736 
2737         pm = acmp->acm_pm =
2738             (usbsacm_pm_t *)kmem_zalloc(sizeof (usbsacm_pm_t), KM_SLEEP);
2739 
2740         pm->pm_pwr_states = (uint8_t)pwr_states;
2741         pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
2742         /*
2743          * Qualcomm CDMA card won't response the following control commands
2744          * after receive USB_REMOTE_WAKEUP_ENABLE. So we just set
2745          * pm_wakeup_enable to 0 for this specific device.
2746          */
2747         dev_descr = acmp->acm_dev_data->dev_descr;
2748         if (dev_descr->idVendor == 0x5c6 && dev_descr->idProduct == 0x3100) {
2749                 pm->pm_wakeup_enabled = 0;
2750         } else {
2751                 pm->pm_wakeup_enabled = (usb_handle_remote_wakeup(dip,
2752                     USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS);
2753         }
2754 
2755         (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2756 
2757         return (USB_SUCCESS);
2758 }
2759 
2760 
2761 /*
2762  * usbsacm_destroy_pm_components:
2763  *      destroy PM components
2764  */
2765 static void
2766 usbsacm_destroy_pm_components(usbsacm_state_t *acmp)
2767 {
2768         usbsacm_pm_t    *pm = acmp->acm_pm;
2769         dev_info_t      *dip = acmp->acm_dip;
2770         int             rval;
2771 
2772         USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
2773             "usbsacm_destroy_pm_components: ");
2774 
2775         if (acmp->acm_dev_state != USB_DEV_DISCONNECTED) {
2776                 if (pm->pm_wakeup_enabled) {
2777                         rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2778                         if (rval != DDI_SUCCESS) {
2779                                 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
2780                                     "usbsacm_destroy_pm_components: "
2781                                     "raising power failed (%d)", rval);
2782                         }
2783 
2784                         rval = usb_handle_remote_wakeup(dip,
2785                             USB_REMOTE_WAKEUP_DISABLE);
2786                         if (rval != USB_SUCCESS) {
2787                                 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
2788                                     "usbsacm_destroy_pm_components: "
2789                                     "disable remote wakeup failed (%d)", rval);
2790                         }
2791                 }
2792 
2793                 (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
2794         }
2795         kmem_free((caddr_t)pm, sizeof (usbsacm_pm_t));
2796         acmp->acm_pm = NULL;
2797 }
2798 
2799 
2800 /*
2801  * usbsacm_pm_set_busy:
2802  *      mark device busy and raise power
2803  */
2804 static void
2805 usbsacm_pm_set_busy(usbsacm_state_t *acmp)
2806 {
2807         usbsacm_pm_t    *pm = acmp->acm_pm;
2808         dev_info_t      *dip = acmp->acm_dip;
2809         int             rval;
2810 
2811         USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
2812             "usbsacm_pm_set_busy: pm = 0x%p", (void *)pm);
2813 
2814         if (pm == NULL) {
2815 
2816                 return;
2817         }
2818 
2819         mutex_enter(&acmp->acm_mutex);
2820         /* if already marked busy, just increment the counter */
2821         if (pm->pm_busy_cnt++ > 0) {
2822                 mutex_exit(&acmp->acm_mutex);
2823 
2824                 return;
2825         }
2826 
2827         (void) pm_busy_component(dip, 0);
2828 
2829         if (pm->pm_cur_power == USB_DEV_OS_FULL_PWR) {
2830                 mutex_exit(&acmp->acm_mutex);
2831 
2832                 return;
2833         }
2834 
2835         /* need to raise power  */
2836         pm->pm_raise_power = B_TRUE;
2837         mutex_exit(&acmp->acm_mutex);
2838 
2839         rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2840         if (rval != DDI_SUCCESS) {
2841                 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
2842                     "usbsacm_pm_set_busy: raising power failed");
2843         }
2844 
2845         mutex_enter(&acmp->acm_mutex);
2846         pm->pm_raise_power = B_FALSE;
2847         mutex_exit(&acmp->acm_mutex);
2848 }
2849 
2850 
2851 /*
2852  * usbsacm_pm_set_idle:
2853  *      mark device idle
2854  */
2855 static void
2856 usbsacm_pm_set_idle(usbsacm_state_t *acmp)
2857 {
2858         usbsacm_pm_t    *pm = acmp->acm_pm;
2859         dev_info_t      *dip = acmp->acm_dip;
2860 
2861         USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
2862             "usbsacm_pm_set_idle: ");
2863 
2864         if (pm == NULL) {
2865 
2866                 return;
2867         }
2868 
2869         /*
2870          * if more ports use the device, do not mark as yet
2871          */
2872         mutex_enter(&acmp->acm_mutex);
2873         if (--pm->pm_busy_cnt > 0) {
2874                 mutex_exit(&acmp->acm_mutex);
2875 
2876                 return;
2877         }
2878 
2879         if (pm) {
2880                 (void) pm_idle_component(dip, 0);
2881         }
2882         mutex_exit(&acmp->acm_mutex);
2883 }
2884 
2885 
2886 /*
2887  * usbsacm_pwrlvl0:
2888  *      Functions to handle power transition for OS levels 0 -> 3
2889  *      The same level as OS state, different from USB state
2890  */
2891 static int
2892 usbsacm_pwrlvl0(usbsacm_state_t *acmp)
2893 {
2894         int             rval;
2895         int             i;
2896         usbsacm_port_t  *cur_port = acmp->acm_ports;
2897 
2898         USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
2899             "usbsacm_pwrlvl0: ");
2900 
2901         switch (acmp->acm_dev_state) {
2902         case USB_DEV_ONLINE:
2903                 /* issue USB D3 command to the device */
2904                 rval = usb_set_device_pwrlvl3(acmp->acm_dip);
2905                 ASSERT(rval == USB_SUCCESS);
2906 
2907                 if (cur_port != NULL) {
2908                         for (i = 0; i < acmp->acm_port_cnt; i++) {
2909                                 cur_port = &acmp->acm_ports[i];
2910                                 if (cur_port->acm_intr_ph != NULL &&
2911                                     cur_port->acm_port_state !=
2912                                     USBSACM_PORT_CLOSED) {
2913 
2914                                         mutex_exit(&acmp->acm_mutex);
2915                                         usb_pipe_stop_intr_polling(
2916                                             cur_port->acm_intr_ph,
2917                                             USB_FLAGS_SLEEP);
2918                                         mutex_enter(&acmp->acm_mutex);
2919 
2920                                         mutex_enter(&cur_port->acm_port_mutex);
2921                                         cur_port->acm_intr_state =
2922                                             USBSACM_PIPE_IDLE;
2923                                         mutex_exit(&cur_port->acm_port_mutex);
2924                                 }
2925                         }
2926                 }
2927 
2928                 acmp->acm_dev_state = USB_DEV_PWRED_DOWN;
2929                 acmp->acm_pm->pm_cur_power = USB_DEV_OS_PWR_OFF;
2930 
2931                 /* FALLTHRU */
2932         case USB_DEV_DISCONNECTED:
2933         case USB_DEV_SUSPENDED:
2934                 /* allow a disconnect/cpr'ed device to go to lower power */
2935 
2936                 return (USB_SUCCESS);
2937         case USB_DEV_PWRED_DOWN:
2938         default:
2939                 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
2940                     "usbsacm_pwrlvl0: illegal device state");
2941 
2942                 return (USB_FAILURE);
2943         }
2944 }
2945 
2946 
2947 /*
2948  * usbsacm_pwrlvl1:
2949  *      Functions to handle power transition for OS levels 1 -> 2
2950  */
2951 static int
2952 usbsacm_pwrlvl1(usbsacm_state_t *acmp)
2953 {
2954         /* issue USB D2 command to the device */
2955         (void) usb_set_device_pwrlvl2(acmp->acm_dip);
2956 
2957         return (USB_FAILURE);
2958 }
2959 
2960 
2961 /*
2962  * usbsacm_pwrlvl2:
2963  *      Functions to handle power transition for OS levels 2 -> 1
2964  */
2965 static int
2966 usbsacm_pwrlvl2(usbsacm_state_t *acmp)
2967 {
2968         /* issue USB D1 command to the device */
2969         (void) usb_set_device_pwrlvl1(acmp->acm_dip);
2970 
2971         return (USB_FAILURE);
2972 }
2973 
2974 
2975 /*
2976  * usbsacm_pwrlvl3:
2977  *      Functions to handle power transition for OS levels 3 -> 0
2978  *      The same level as OS state, different from USB state
2979  */
2980 static int
2981 usbsacm_pwrlvl3(usbsacm_state_t *acmp)
2982 {
2983         int             rval;
2984         int             i;
2985         usbsacm_port_t  *cur_port = acmp->acm_ports;
2986 
2987         USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
2988             "usbsacm_pwrlvl3: ");
2989 
2990         switch (acmp->acm_dev_state) {
2991         case USB_DEV_PWRED_DOWN:
2992                 /* Issue USB D0 command to the device here */
2993                 rval = usb_set_device_pwrlvl0(acmp->acm_dip);
2994                 ASSERT(rval == USB_SUCCESS);
2995 
2996                 if (cur_port != NULL) {
2997                         for (i = 0; i < acmp->acm_port_cnt; i++) {
2998                                 cur_port = &acmp->acm_ports[i];
2999                                 if (cur_port->acm_intr_ph != NULL &&
3000                                     cur_port->acm_port_state !=
3001                                     USBSACM_PORT_CLOSED) {
3002 
3003                                         mutex_exit(&acmp->acm_mutex);
3004                                         usbsacm_pipe_start_polling(cur_port);
3005                                         mutex_enter(&acmp->acm_mutex);
3006                                 }
3007                         }
3008                 }
3009 
3010                 acmp->acm_dev_state = USB_DEV_ONLINE;
3011                 acmp->acm_pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
3012 
3013                 /* FALLTHRU */
3014         case USB_DEV_ONLINE:
3015                 /* we are already in full power */
3016 
3017                 /* FALLTHRU */
3018         case USB_DEV_DISCONNECTED:
3019         case USB_DEV_SUSPENDED:
3020 
3021                 return (USB_SUCCESS);
3022         default:
3023                 USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
3024                     "usbsacm_pwrlvl3: illegal device state");
3025 
3026                 return (USB_FAILURE);
3027         }
3028 }
3029 
3030 
3031 /*
3032  * usbsacm_pipe_start_polling:
3033  *      start polling on the interrupt pipe
3034  */
3035 static void
3036 usbsacm_pipe_start_polling(usbsacm_port_t *acm_port)
3037 {
3038         usb_intr_req_t  *intr;
3039         int             rval;
3040         usbsacm_state_t *acmp = acm_port->acm_device;
3041 
3042         USB_DPRINTF_L4(PRINT_MASK_ATTA, acmp->acm_lh,
3043             "usbsacm_pipe_start_polling: ");
3044 
3045         if (acm_port->acm_intr_ph == NULL) {
3046 
3047                 return;
3048         }
3049 
3050         intr = usb_alloc_intr_req(acmp->acm_dip, 0, USB_FLAGS_SLEEP);
3051 
3052         /*
3053          * If it is in interrupt context, usb_alloc_intr_req will return NULL if
3054          * called with SLEEP flag.
3055          */
3056         if (!intr) {
3057                 USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
3058                     "usbsacm_pipe_start_polling: alloc req failed.");
3059 
3060                 return;
3061         }
3062 
3063         /* initialize the interrupt request. */
3064         intr->intr_attributes = USB_ATTRS_SHORT_XFER_OK |
3065             USB_ATTRS_AUTOCLEARING;
3066         mutex_enter(&acm_port->acm_port_mutex);
3067         intr->intr_len = acm_port->acm_intr_ep_descr.wMaxPacketSize;
3068         mutex_exit(&acm_port->acm_port_mutex);
3069         intr->intr_client_private = (usb_opaque_t)acm_port;
3070         intr->intr_cb = usbsacm_intr_cb;
3071         intr->intr_exc_cb = usbsacm_intr_ex_cb;
3072 
3073         rval = usb_pipe_intr_xfer(acm_port->acm_intr_ph, intr, USB_FLAGS_SLEEP);
3074 
3075         mutex_enter(&acm_port->acm_port_mutex);
3076         if (rval == USB_SUCCESS) {
3077                 acm_port->acm_intr_state = USBSACM_PIPE_BUSY;
3078         } else {
3079                 usb_free_intr_req(intr);
3080                 acm_port->acm_intr_state = USBSACM_PIPE_IDLE;
3081                 USB_DPRINTF_L3(PRINT_MASK_OPEN, acmp->acm_lh,
3082                     "usbsacm_pipe_start_polling: failed (%d)", rval);
3083         }
3084         mutex_exit(&acm_port->acm_port_mutex);
3085 }
3086 
3087 
3088 /*
3089  * usbsacm_intr_cb:
3090  *      interrupt pipe normal callback
3091  */
3092 /*ARGSUSED*/
3093 static void
3094 usbsacm_intr_cb(usb_pipe_handle_t ph, usb_intr_req_t *req)
3095 {
3096         usbsacm_port_t  *acm_port = (usbsacm_port_t *)req->intr_client_private;
3097         usbsacm_state_t *acmp = acm_port->acm_device;
3098         mblk_t          *data = req->intr_data;
3099         int             data_len;
3100 
3101         USB_DPRINTF_L4(PRINT_MASK_CB, acmp->acm_lh,
3102             "usbsacm_intr_cb: ");
3103 
3104         data_len = (data) ? MBLKL(data) : 0;
3105 
3106         /* check data length */
3107         if (data_len < 8) {
3108                 USB_DPRINTF_L2(PRINT_MASK_CB, acmp->acm_lh,
3109                     "usbsacm_intr_cb: %d packet too short", data_len);
3110                 usb_free_intr_req(req);
3111 
3112                 return;
3113         }
3114         req->intr_data = NULL;
3115         usb_free_intr_req(req);
3116 
3117         mutex_enter(&acm_port->acm_port_mutex);
3118         /* parse interrupt data. */
3119         usbsacm_parse_intr_data(acm_port, data);
3120         mutex_exit(&acm_port->acm_port_mutex);
3121 }
3122 
3123 
3124 /*
3125  * usbsacm_intr_ex_cb:
3126  *      interrupt pipe exception callback
3127  */
3128 /*ARGSUSED*/
3129 static void
3130 usbsacm_intr_ex_cb(usb_pipe_handle_t ph, usb_intr_req_t *req)
3131 {
3132         usbsacm_port_t  *acm_port = (usbsacm_port_t *)req->intr_client_private;
3133         usbsacm_state_t *acmp = acm_port->acm_device;
3134         usb_cr_t        cr = req->intr_completion_reason;
3135 
3136         USB_DPRINTF_L4(PRINT_MASK_CB, acmp->acm_lh,
3137             "usbsacm_intr_ex_cb: ");
3138 
3139         usb_free_intr_req(req);
3140 
3141         /*
3142          * If completion reason isn't USB_CR_PIPE_CLOSING and
3143          * USB_CR_STOPPED_POLLING, restart polling.
3144          */
3145         if ((cr != USB_CR_PIPE_CLOSING) && (cr != USB_CR_STOPPED_POLLING)) {
3146                 mutex_enter(&acmp->acm_mutex);
3147 
3148                 if (acmp->acm_dev_state != USB_DEV_ONLINE) {
3149 
3150                         USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3151                             "usbsacm_intr_ex_cb: state = %d",
3152                             acmp->acm_dev_state);
3153 
3154                         mutex_exit(&acmp->acm_mutex);
3155 
3156                         return;
3157                 }
3158                 mutex_exit(&acmp->acm_mutex);
3159 
3160                 usbsacm_pipe_start_polling(acm_port);
3161         }
3162 }
3163 
3164 
3165 /*
3166  * usbsacm_parse_intr_data:
3167  *      Parse data received from interrupt callback
3168  */
3169 static void
3170 usbsacm_parse_intr_data(usbsacm_port_t *acm_port, mblk_t *data)
3171 {
3172         usbsacm_state_t *acmp = acm_port->acm_device;
3173         uint8_t         bmRequestType;
3174         uint8_t         bNotification;
3175         uint16_t        wValue;
3176         uint16_t        wLength;
3177         uint16_t        wData;
3178 
3179         USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
3180             "usbsacm_parse_intr_data: ");
3181 
3182         bmRequestType = data->b_rptr[0];
3183         bNotification = data->b_rptr[1];
3184         /*
3185          * If Notification type is NETWORK_CONNECTION, wValue is 0 or 1,
3186          * mLength is 0. If Notification type is SERIAL_TYPE, mValue is 0,
3187          * mLength is 2. So we directly get the value from the byte.
3188          */
3189         wValue = data->b_rptr[2];
3190         wLength = data->b_rptr[6];
3191 
3192         if (bmRequestType != USB_CDC_NOTIFICATION_REQUEST_TYPE) {
3193                 USB_DPRINTF_L2(PRINT_MASK_CB, acmp->acm_lh,
3194                     "usbsacm_parse_intr_data: unknown request type - 0x%x",
3195                     bmRequestType);
3196 
3197                 freemsg(data);
3198 
3199                 return;
3200         }
3201 
3202         /*
3203          * Check the return value of device
3204          */
3205         switch (bNotification) {
3206         case USB_CDC_NOTIFICATION_NETWORK_CONNECTION:
3207                 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3208                     "usbsacm_parse_intr_data: %s network!",
3209                     wValue ? "connected to" :"disconnected from");
3210 
3211                 break;
3212         case USB_CDC_NOTIFICATION_RESPONSE_AVAILABLE:
3213                 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3214                     "usbsacm_parse_intr_data: A response is a available.");
3215 
3216                 break;
3217         case USB_CDC_NOTIFICATION_SERIAL_STATE:
3218                 /* check the parameter's length. */
3219                 if (wLength != 2) {
3220 
3221                         USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3222                             "usbsacm_parse_intr_data: error data length.");
3223                 } else {
3224                         /*
3225                          * The Data field is a bitmapped value that contains
3226                          * the current state of carrier detect, transmission
3227                          * carrier, break, ring signal and device overrun
3228                          * error.
3229                          */
3230                         wData = data->b_rptr[8];
3231                         /*
3232                          * Check the serial state of the current port.
3233                          */
3234                         if (wData & USB_CDC_ACM_CONTROL_DCD) {
3235 
3236                                 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3237                                     "usbsacm_parse_intr_data: "
3238                                     "receiver carrier is set.");
3239                         }
3240                         if (wData & USB_CDC_ACM_CONTROL_DSR) {
3241 
3242                                 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3243                                     "usbsacm_parse_intr_data: "
3244                                     "transmission carrier is set.");
3245 
3246                                 acm_port->acm_mctlin |= USB_CDC_ACM_CONTROL_DSR;
3247                         }
3248                         if (wData & USB_CDC_ACM_CONTROL_BREAK) {
3249 
3250                                 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3251                                     "usbsacm_parse_intr_data: "
3252                                     "break detection mechanism is set.");
3253                         }
3254                         if (wData & USB_CDC_ACM_CONTROL_RNG) {
3255 
3256                                 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3257                                     "usbsacm_parse_intr_data: "
3258                                     "ring signal detection is set.");
3259 
3260                                 acm_port->acm_mctlin |= USB_CDC_ACM_CONTROL_RNG;
3261                         }
3262                         if (wData & USB_CDC_ACM_CONTROL_FRAMING) {
3263 
3264                                 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3265                                     "usbsacm_parse_intr_data: "
3266                                     "A framing error has occurred.");
3267                         }
3268                         if (wData & USB_CDC_ACM_CONTROL_PARITY) {
3269 
3270                                 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3271                                     "usbsacm_parse_intr_data: "
3272                                     "A parity error has occurred.");
3273                         }
3274                         if (wData & USB_CDC_ACM_CONTROL_OVERRUN) {
3275 
3276                                 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3277                                     "usbsacm_parse_intr_data: "
3278                                     "Received data has been discarded "
3279                                     "due to overrun.");
3280                         }
3281                 }
3282 
3283                 break;
3284         default:
3285                 USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3286                     "usbsacm_parse_intr_data: unknown notification - 0x%x!",
3287                     bNotification);
3288 
3289                 break;
3290         }
3291 
3292         freemsg(data);
3293 }