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