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  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
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_supported,	/* devo_quiesce */
395 };
396 
397 extern struct mod_ops mod_driverops;
398 /* modldrv structure */
399 static struct modldrv modldrv = {
400 	&mod_driverops,		/* type of module - driver */
401 	"USB Serial CDC ACM driver",
402 	&usbsacm_ops,
403 };
404 
405 /* modlinkage structure */
406 static struct modlinkage modlinkage = {
407 	MODREV_1,
408 	&modldrv,
409 	NULL
410 };
411 
412 static void	*usbsacm_statep;	/* soft state */
413 
414 /*
415  * DSD definitions
416  */
417 static ds_ops_t usbsacm_ds_ops = {
418 	DS_OPS_VERSION,
419 	usbsacm_ds_attach,
420 	usbsacm_ds_detach,
421 	usbsacm_ds_register_cb,
422 	usbsacm_ds_unregister_cb,
423 	usbsacm_ds_open_port,
424 	usbsacm_ds_close_port,
425 	usbsacm_ds_usb_power,
426 	usbsacm_ds_suspend,
427 	usbsacm_ds_resume,
428 	usbsacm_ds_disconnect,
429 	usbsacm_ds_reconnect,
430 	usbsacm_ds_set_port_params,
431 	usbsacm_ds_set_modem_ctl,
432 	usbsacm_ds_get_modem_ctl,
433 	usbsacm_ds_break_ctl,
434 	NULL,			/* NULL if h/w doesn't support loopback */
435 	usbsacm_ds_tx,
436 	usbsacm_ds_rx,
437 	usbsacm_ds_stop,
438 	usbsacm_ds_start,
439 	usbsacm_ds_fifo_flush,
440 	usbsacm_ds_fifo_drain
441 };
442 
443 /*
444  * baud code -> baud rate (0 means unsupported rate)
445  */
446 static int usbsacm_speedtab[] = {
447 	0,	/* B0 */
448 	50,	/* B50 */
449 	75,	/* B75 */
450 	110,	/* B110 */
451 	134,	/* B134 */
452 	150,	/* B150 */
453 	200,	/* B200 */
454 	300,	/* B300 */
455 	600,	/* B600 */
456 	1200,	/* B1200 */
457 	1800,	/* B1800 */
458 	2400,	/* B2400 */
459 	4800,	/* B4800 */
460 	9600,	/* B9600 */
461 	19200,	/* B19200 */
462 	38400,	/* B38400 */
463 	57600,	/* B57600 */
464 	76800,	/* B76800 */
465 	115200,	/* B115200 */
466 	153600,	/* B153600 */
467 	230400,	/* B230400 */
468 	307200,	/* B307200 */
469 	460800	/* B460800 */
470 };
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 	int		if_no;
1457 
1458 	USB_DPRINTF_L4(PRINT_MASK_ATTA, acmp->acm_lh,
1459 	    "usbsacm_get_bulk_pipe_number: ");
1460 
1461 	cur_if = acmp->acm_dev_data->dev_curr_cfg->cfg_if;
1462 	if_num = acmp->acm_dev_data->dev_curr_cfg->cfg_n_if;
1463 	if_no = acmp->acm_dev_data->dev_curr_if;
1464 
1465 	/* search each interface which have bulk endpoint */
1466 	for (i = 0; i < if_num; i++) {
1467 		ep_num = cur_if->if_alt->altif_n_ep;
1468 
1469 		/*
1470 		 * search endpoints in current interface,
1471 		 * which type is input parameter 'dir'
1472 		 */
1473 		for (skip = 0; skip < ep_num; skip++) {
1474 			if (usb_lookup_ep_data(acmp->acm_dip,
1475 			    acmp->acm_dev_data, if_no + i, 0, skip,
1476 			    USB_EP_ATTR_BULK, dir) == NULL) {
1477 
1478 				/*
1479 				 * If not found, skip the internal loop
1480 				 * and search the next interface.
1481 				 */
1482 				break;
1483 			}
1484 			count++;
1485 		}
1486 
1487 		cur_if++;
1488 	}
1489 
1490 	return (count);
1491 }
1492 
1493 
1494 /*
1495  * port management
1496  * ---------------
1497  *	initialize, release port.
1498  *
1499  *
1500  * usbsacm_init_ports_status:
1501  *	Initialize the port status for the current device.
1502  */
1503 static int
1504 usbsacm_init_ports_status(usbsacm_state_t *acmp)
1505 {
1506 	usbsacm_port_t	*cur_port;
1507 	int		i, skip;
1508 	int		if_num;
1509 	int		intr_if_no = 0;
1510 	int		ep_num;
1511 	usb_if_data_t	*cur_if;
1512 
1513 	USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh,
1514 	    "usbsacm_init_ports_status: acmp = 0x%p", (void *)acmp);
1515 
1516 	/* Initialize the port status to default value */
1517 	for (i = 0; i < acmp->acm_port_cnt; i++) {
1518 		cur_port = &acmp->acm_ports[i];
1519 
1520 		cv_init(&cur_port->acm_tx_cv, NULL, CV_DRIVER, NULL);
1521 
1522 		cur_port->acm_port_state = USBSACM_PORT_CLOSED;
1523 
1524 		cur_port->acm_line_coding.dwDTERate = LE_32((uint32_t)9600);
1525 		cur_port->acm_line_coding.bCharFormat = 0;
1526 		cur_port->acm_line_coding.bParityType = USB_CDC_PARITY_NO;
1527 		cur_port->acm_line_coding.bDataBits = 8;
1528 		cur_port->acm_device = acmp;
1529 		mutex_init(&cur_port->acm_port_mutex, NULL, MUTEX_DRIVER,
1530 		    acmp->acm_dev_data->dev_iblock_cookie);
1531 	}
1532 
1533 	/*
1534 	 * If device conform to cdc acm spec, parse function descriptors.
1535 	 */
1536 	if (acmp->acm_compatibility == B_TRUE) {
1537 
1538 		if (usbsacm_get_descriptors(acmp) != USB_SUCCESS) {
1539 
1540 			return (USB_FAILURE);
1541 		}
1542 
1543 		return (USB_SUCCESS);
1544 	}
1545 
1546 	/*
1547 	 * If device don't conform to spec, search pairs of bulk in/out
1548 	 * endpoints and fill port structure.
1549 	 */
1550 	cur_if = acmp->acm_dev_data->dev_curr_cfg->cfg_if;
1551 	if_num = acmp->acm_dev_data->dev_curr_cfg->cfg_n_if;
1552 	cur_port = acmp->acm_ports;
1553 
1554 	/* search each interface which have bulk in and out */
1555 	for (i = 0; i < if_num; i++) {
1556 		ep_num = cur_if->if_alt->altif_n_ep;
1557 
1558 		for (skip = 0; skip < ep_num; skip++) {
1559 
1560 		/* search interrupt pipe. */
1561 		if ((usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1562 		    i, 0, skip, USB_EP_ATTR_INTR, USB_EP_DIR_IN) != NULL)) {
1563 
1564 			intr_if_no = i;
1565 		}
1566 
1567 		/* search pair of bulk in/out endpoints. */
1568 		if ((usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1569 		    i, 0, skip, USB_EP_ATTR_BULK, USB_EP_DIR_IN) == NULL) ||
1570 		    (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1571 		    i, 0, skip, USB_EP_ATTR_BULK, USB_EP_DIR_OUT) == NULL)) {
1572 
1573 			continue;
1574 		}
1575 
1576 		cur_port->acm_data_if_no = i;
1577 		cur_port->acm_ctrl_if_no = intr_if_no;
1578 		cur_port->acm_data_port_no = skip;
1579 		cur_port++;
1580 		intr_if_no = 0;
1581 		}
1582 
1583 		cur_if++;
1584 	}
1585 
1586 	return (USB_SUCCESS);
1587 }
1588 
1589 
1590 /*
1591  * usbsacm_init_alloc_ports:
1592  *	Allocate memory and initialize the port state for the current device.
1593  */
1594 static int
1595 usbsacm_init_alloc_ports(usbsacm_state_t *acmp)
1596 {
1597 	int		rval = USB_SUCCESS;
1598 	int		count_in = 0, count_out = 0;
1599 
1600 	if (acmp->acm_compatibility) {
1601 		acmp->acm_port_cnt = 1;
1602 	} else {
1603 		/* Calculate the number of the bulk in/out endpoints */
1604 		count_in = usbsacm_get_bulk_pipe_number(acmp, USB_EP_DIR_IN);
1605 		count_out = usbsacm_get_bulk_pipe_number(acmp, USB_EP_DIR_OUT);
1606 
1607 		USB_DPRINTF_L3(PRINT_MASK_OPEN, acmp->acm_lh,
1608 		    "usbsacm_init_alloc_ports: count_in = %d, count_out = %d",
1609 		    count_in, count_out);
1610 
1611 		acmp->acm_port_cnt = min(count_in, count_out);
1612 	}
1613 
1614 	/* return if not found any pair of bulk in/out endpoint. */
1615 	if (acmp->acm_port_cnt == 0) {
1616 		USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
1617 		    "usbsacm_init_alloc_ports: port count is zero.");
1618 
1619 		return (USB_FAILURE);
1620 	}
1621 
1622 	/* allocate memory for ports */
1623 	acmp->acm_ports = (usbsacm_port_t *)kmem_zalloc(acmp->acm_port_cnt *
1624 	    sizeof (usbsacm_port_t), KM_SLEEP);
1625 	if (acmp->acm_ports == NULL) {
1626 		USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
1627 		    "usbsacm_init_alloc_ports: allocate memory failed.");
1628 
1629 		return (USB_FAILURE);
1630 	}
1631 
1632 	/* fill the status of port structure. */
1633 	rval = usbsacm_init_ports_status(acmp);
1634 	if (rval != USB_SUCCESS) {
1635 		usbsacm_free_ports(acmp);
1636 	}
1637 
1638 	return (rval);
1639 }
1640 
1641 
1642 /*
1643  * usbsacm_free_ports:
1644  *	Release ports and deallocate memory.
1645  */
1646 static void
1647 usbsacm_free_ports(usbsacm_state_t *acmp)
1648 {
1649 	int		i;
1650 
1651 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
1652 	    "usbsacm_free_ports: ");
1653 
1654 	/* Release memory and data structure for each port */
1655 	for (i = 0; i < acmp->acm_port_cnt; i++) {
1656 		cv_destroy(&acmp->acm_ports[i].acm_tx_cv);
1657 		mutex_destroy(&acmp->acm_ports[i].acm_port_mutex);
1658 	}
1659 	kmem_free((caddr_t)acmp->acm_ports, sizeof (usbsacm_port_t) *
1660 	    acmp->acm_port_cnt);
1661 	acmp->acm_ports = NULL;
1662 }
1663 
1664 
1665 /*
1666  * usbsacm_get_descriptors:
1667  *	analysis functional descriptors of acm device
1668  */
1669 static int
1670 usbsacm_get_descriptors(usbsacm_state_t *acmp)
1671 {
1672 	int			i;
1673 	usb_cfg_data_t		*cfg;
1674 	usb_alt_if_data_t	*altif;
1675 	usb_cvs_data_t		*cvs;
1676 	int			mgmt_cap = 0;
1677 	int			master_if = -1, slave_if = -1;
1678 	usbsacm_port_t		*acm_port = acmp->acm_ports;
1679 
1680 	USB_DPRINTF_L4(PRINT_MASK_ATTA, acmp->acm_lh,
1681 	    "usbsacm_get_descriptors: ");
1682 
1683 	cfg = acmp->acm_dev_data->dev_curr_cfg;
1684 	/* set default control and data interface */
1685 	acm_port->acm_ctrl_if_no = acm_port->acm_data_if_no = 0;
1686 
1687 	/* get current interfaces */
1688 	acm_port->acm_ctrl_if_no = acmp->acm_dev_data->dev_curr_if;
1689 	if (cfg->cfg_if[acm_port->acm_ctrl_if_no].if_n_alt == 0) {
1690 		USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1691 		    "usbsacm_get_descriptors: elements in if_alt is %d",
1692 		    cfg->cfg_if[acm_port->acm_ctrl_if_no].if_n_alt);
1693 
1694 		return (USB_FAILURE);
1695 	}
1696 
1697 	altif = &cfg->cfg_if[acm_port->acm_ctrl_if_no].if_alt[0];
1698 
1699 	/*
1700 	 * Based on CDC specification, ACM devices usually include the
1701 	 * following function descriptors: Header, ACM, Union and Call
1702 	 * Management function descriptors. This loop search tree data
1703 	 * structure for each acm class descriptor.
1704 	 */
1705 	for (i = 0; i < altif->altif_n_cvs; i++) {
1706 
1707 		cvs = &altif->altif_cvs[i];
1708 
1709 		if ((cvs->cvs_buf == NULL) ||
1710 		    (cvs->cvs_buf[1] != USB_CDC_CS_INTERFACE)) {
1711 			continue;
1712 		}
1713 
1714 		switch (cvs->cvs_buf[2]) {
1715 		case USB_CDC_DESCR_TYPE_CALL_MANAGEMENT:
1716 			/* parse call management functional descriptor. */
1717 			if (cvs->cvs_buf_len >= 5) {
1718 				mgmt_cap = cvs->cvs_buf[3];
1719 				acm_port->acm_data_if_no = cvs->cvs_buf[4];
1720 			}
1721 			break;
1722 		case USB_CDC_DESCR_TYPE_ACM:
1723 			/* parse ACM functional descriptor. */
1724 			if (cvs->cvs_buf_len >= 4) {
1725 				acm_port->acm_cap = cvs->cvs_buf[3];
1726 			}
1727 			break;
1728 		case USB_CDC_DESCR_TYPE_UNION:
1729 			/* parse Union functional descriptor. */
1730 			if (cvs->cvs_buf_len >= 5) {
1731 				master_if = cvs->cvs_buf[3];
1732 				slave_if = cvs->cvs_buf[4];
1733 			}
1734 			break;
1735 		default:
1736 			break;
1737 		}
1738 	}
1739 
1740 	/* For usb acm devices, it must satisfy the following options. */
1741 	if (cfg->cfg_n_if < 2) {
1742 		USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1743 		    "usbsacm_get_descriptors: # of interfaces %d < 2",
1744 		    cfg->cfg_n_if);
1745 
1746 		return (USB_FAILURE);
1747 	}
1748 
1749 	if (acm_port->acm_data_if_no == 0 &&
1750 	    slave_if != acm_port->acm_data_if_no) {
1751 		USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1752 		    "usbsacm_get_descriptors: Device hasn't call management "
1753 		    "descriptor and use Union Descriptor.");
1754 
1755 		acm_port->acm_data_if_no = slave_if;
1756 	}
1757 
1758 	if ((master_if != acm_port->acm_ctrl_if_no) ||
1759 	    (slave_if != acm_port->acm_data_if_no)) {
1760 		USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1761 		    "usbsacm_get_descriptors: control interface or "
1762 		    "data interface don't match.");
1763 
1764 		return (USB_FAILURE);
1765 	}
1766 
1767 	/*
1768 	 * We usually need both call and data capabilities, but
1769 	 * some devices, such as Nokia mobile phones, don't provide
1770 	 * call management descriptor, so we just give a warning
1771 	 * message.
1772 	 */
1773 	if (((mgmt_cap & USB_CDC_CALL_MGMT_CAP_CALL_MGMT) == 0) ||
1774 	    ((mgmt_cap & USB_CDC_CALL_MGMT_CAP_DATA_INTERFACE) == 0)) {
1775 		USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1776 		    "usbsacm_get_descriptors: "
1777 		    "insufficient mgmt capabilities %x",
1778 		    mgmt_cap);
1779 	}
1780 
1781 	if ((acm_port->acm_ctrl_if_no >= cfg->cfg_n_if) ||
1782 	    (acm_port->acm_data_if_no >= cfg->cfg_n_if)) {
1783 		USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1784 		    "usbsacm_get_descriptors: control interface %d or "
1785 		    "data interface %d out of range.",
1786 		    acm_port->acm_ctrl_if_no, acm_port->acm_data_if_no);
1787 
1788 		return (USB_FAILURE);
1789 	}
1790 
1791 	/* control interface must have interrupt endpoint */
1792 	if (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1793 	    acm_port->acm_ctrl_if_no, 0, 0, USB_EP_ATTR_INTR,
1794 	    USB_EP_DIR_IN) == NULL) {
1795 		USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1796 		    "usbsacm_get_descriptors: "
1797 		    "ctrl interface %d has no interrupt endpoint",
1798 		    acm_port->acm_data_if_no);
1799 
1800 		return (USB_FAILURE);
1801 	}
1802 
1803 	/* data interface must have bulk in and out */
1804 	if (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1805 	    acm_port->acm_data_if_no, 0, 0, USB_EP_ATTR_BULK,
1806 	    USB_EP_DIR_IN) == NULL) {
1807 		USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1808 		    "usbsacm_get_descriptors: "
1809 		    "data interface %d has no bulk in endpoint",
1810 		    acm_port->acm_data_if_no);
1811 
1812 		return (USB_FAILURE);
1813 	}
1814 	if (usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1815 	    acm_port->acm_data_if_no, 0, 0, USB_EP_ATTR_BULK,
1816 	    USB_EP_DIR_OUT) == NULL) {
1817 		USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1818 		    "usbsacm_get_descriptors: "
1819 		    "data interface %d has no bulk out endpoint",
1820 		    acm_port->acm_data_if_no);
1821 
1822 		return (USB_FAILURE);
1823 	}
1824 
1825 	return (USB_SUCCESS);
1826 }
1827 
1828 
1829 /*
1830  * usbsacm_cleanup:
1831  *	Release resources of current device during detach.
1832  */
1833 static void
1834 usbsacm_cleanup(usbsacm_state_t *acmp)
1835 {
1836 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
1837 	    "usbsacm_cleanup: ");
1838 
1839 	if (acmp != NULL) {
1840 		/* free ports */
1841 		if (acmp->acm_ports != NULL) {
1842 			usbsacm_free_ports(acmp);
1843 		}
1844 
1845 		/* unregister callback function */
1846 		if (acmp->acm_usb_events != NULL) {
1847 			usb_unregister_event_cbs(acmp->acm_dip,
1848 			    acmp->acm_usb_events);
1849 		}
1850 
1851 		/* destroy power management components */
1852 		if (acmp->acm_pm != NULL) {
1853 			usbsacm_destroy_pm_components(acmp);
1854 		}
1855 
1856 		/* free description of device tree. */
1857 		if (acmp->acm_def_ph != NULL) {
1858 			mutex_destroy(&acmp->acm_mutex);
1859 
1860 			usb_free_descr_tree(acmp->acm_dip, acmp->acm_dev_data);
1861 			acmp->acm_def_ph = NULL;
1862 		}
1863 
1864 		if (acmp->acm_lh != NULL) {
1865 			usb_free_log_hdl(acmp->acm_lh);
1866 			acmp->acm_lh = NULL;
1867 		}
1868 
1869 		/* detach client device */
1870 		if (acmp->acm_dev_data != NULL) {
1871 			usb_client_detach(acmp->acm_dip, acmp->acm_dev_data);
1872 		}
1873 
1874 		kmem_free((caddr_t)acmp, sizeof (usbsacm_state_t));
1875 	}
1876 }
1877 
1878 
1879 /*
1880  * usbsacm_restore_device_state:
1881  *	restore device state after CPR resume or reconnect
1882  */
1883 static int
1884 usbsacm_restore_device_state(usbsacm_state_t *acmp)
1885 {
1886 	int	state;
1887 
1888 	USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
1889 	    "usbsacm_restore_device_state: ");
1890 
1891 	mutex_enter(&acmp->acm_mutex);
1892 	state = acmp->acm_dev_state;
1893 	mutex_exit(&acmp->acm_mutex);
1894 
1895 	/* Check device status */
1896 	if ((state != USB_DEV_DISCONNECTED) && (state != USB_DEV_SUSPENDED)) {
1897 
1898 		return (state);
1899 	}
1900 
1901 	/* Check if we are talking to the same device */
1902 	if (usb_check_same_device(acmp->acm_dip, acmp->acm_lh, USB_LOG_L0,
1903 	    -1, USB_CHK_ALL, NULL) != USB_SUCCESS) {
1904 		mutex_enter(&acmp->acm_mutex);
1905 		state = acmp->acm_dev_state = USB_DEV_DISCONNECTED;
1906 		mutex_exit(&acmp->acm_mutex);
1907 
1908 		return (state);
1909 	}
1910 
1911 	if (state == USB_DEV_DISCONNECTED) {
1912 		USB_DPRINTF_L1(PRINT_MASK_ALL, acmp->acm_lh,
1913 		    "usbsacm_restore_device_state: Device has been reconnected "
1914 		    "but data may have been lost");
1915 	}
1916 
1917 	/* reconnect pipes */
1918 	if (usbsacm_reconnect_pipes(acmp) != USB_SUCCESS) {
1919 
1920 		return (state);
1921 	}
1922 
1923 	/*
1924 	 * init device state
1925 	 */
1926 	mutex_enter(&acmp->acm_mutex);
1927 	state = acmp->acm_dev_state = USB_DEV_ONLINE;
1928 	mutex_exit(&acmp->acm_mutex);
1929 
1930 	if ((usbsacm_restore_port_state(acmp) != USB_SUCCESS)) {
1931 		USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1932 		    "usbsacm_restore_device_state: failed");
1933 	}
1934 
1935 	return (state);
1936 }
1937 
1938 
1939 /*
1940  * usbsacm_restore_port_state:
1941  *	restore ports state after CPR resume or reconnect
1942  */
1943 static int
1944 usbsacm_restore_port_state(usbsacm_state_t *acmp)
1945 {
1946 	int		i, ret = USB_SUCCESS;
1947 	usbsacm_port_t	*cur_port;
1948 
1949 	USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
1950 	    "usbsacm_restore_port_state: ");
1951 
1952 	/* restore status of all ports */
1953 	for (i = 0; i < acmp->acm_port_cnt; i++) {
1954 		cur_port = &acmp->acm_ports[i];
1955 		mutex_enter(&cur_port->acm_port_mutex);
1956 		if (cur_port->acm_port_state != USBSACM_PORT_OPEN) {
1957 			mutex_exit(&cur_port->acm_port_mutex);
1958 
1959 			continue;
1960 		}
1961 		mutex_exit(&cur_port->acm_port_mutex);
1962 
1963 		if ((ret = usbsacm_set_line_coding(cur_port,
1964 		    &cur_port->acm_line_coding)) != USB_SUCCESS) {
1965 			USB_DPRINTF_L2(PRINT_MASK_ATTA, acmp->acm_lh,
1966 			    "usbsacm_restore_port_state: failed.");
1967 		}
1968 	}
1969 
1970 	return (ret);
1971 }
1972 
1973 
1974 /*
1975  * pipe management
1976  * ---------------
1977  *
1978  *
1979  * usbsacm_open_port_pipes:
1980  *	Open pipes of one port and set port structure;
1981  *	Each port includes three pipes: bulk in, bulk out and interrupt.
1982  */
1983 static int
1984 usbsacm_open_port_pipes(usbsacm_port_t *acm_port)
1985 {
1986 	int		rval = USB_SUCCESS;
1987 	usbsacm_state_t	*acmp = acm_port->acm_device;
1988 	usb_ep_data_t	*in_data, *out_data, *intr_pipe;
1989 	usb_pipe_policy_t policy;
1990 
1991 	USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh,
1992 	    "usbsacm_open_port_pipes: acmp = 0x%p", (void *)acmp);
1993 
1994 	/* Get bulk and interrupt endpoint data */
1995 	intr_pipe = usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1996 	    acm_port->acm_ctrl_if_no, 0, 0,
1997 	    USB_EP_ATTR_INTR, USB_EP_DIR_IN);
1998 	in_data = usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
1999 	    acm_port->acm_data_if_no, 0, acm_port->acm_data_port_no,
2000 	    USB_EP_ATTR_BULK, USB_EP_DIR_IN);
2001 	out_data = usb_lookup_ep_data(acmp->acm_dip, acmp->acm_dev_data,
2002 	    acm_port->acm_data_if_no, 0, acm_port->acm_data_port_no,
2003 	    USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
2004 
2005 	/* Bulk in and out must exist meanwhile. */
2006 	if ((in_data == NULL) || (out_data == NULL)) {
2007 		USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2008 		    "usbsacm_open_port_pipes: look up bulk pipe failed in "
2009 		    "interface %d port %d",
2010 		    acm_port->acm_data_if_no, acm_port->acm_data_port_no);
2011 
2012 		return (USB_FAILURE);
2013 	}
2014 
2015 	/*
2016 	 * If device conform to acm spec, it must have an interrupt pipe
2017 	 * for this port.
2018 	 */
2019 	if (acmp->acm_compatibility == B_TRUE && intr_pipe == NULL) {
2020 		USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2021 		    "usbsacm_open_port_pipes: look up interrupt pipe failed in "
2022 		    "interface %d", acm_port->acm_ctrl_if_no);
2023 
2024 		return (USB_FAILURE);
2025 	}
2026 
2027 	policy.pp_max_async_reqs = 2;
2028 
2029 	/* Open bulk in endpoint */
2030 	if (usb_pipe_open(acmp->acm_dip, &in_data->ep_descr, &policy,
2031 	    USB_FLAGS_SLEEP, &acm_port->acm_bulkin_ph) != USB_SUCCESS) {
2032 		USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2033 		    "usbsacm_open_port_pipes: open bulkin pipe failed!");
2034 
2035 		return (USB_FAILURE);
2036 	}
2037 
2038 	/* Open bulk out endpoint */
2039 	if (usb_pipe_open(acmp->acm_dip, &out_data->ep_descr, &policy,
2040 	    USB_FLAGS_SLEEP, &acm_port->acm_bulkout_ph) != USB_SUCCESS) {
2041 		USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2042 		    "usbsacm_open_port_pipes: open bulkout pipe failed!");
2043 
2044 		usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkin_ph,
2045 		    USB_FLAGS_SLEEP, NULL, NULL);
2046 
2047 		return (USB_FAILURE);
2048 	}
2049 
2050 	/* Open interrupt endpoint if found. */
2051 	if (intr_pipe != NULL) {
2052 
2053 		if (usb_pipe_open(acmp->acm_dip, &intr_pipe->ep_descr, &policy,
2054 		    USB_FLAGS_SLEEP, &acm_port->acm_intr_ph) != USB_SUCCESS) {
2055 			USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2056 			    "usbsacm_open_port_pipes: "
2057 			    "open control pipe failed");
2058 
2059 			usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkin_ph,
2060 			    USB_FLAGS_SLEEP, NULL, NULL);
2061 			usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkout_ph,
2062 			    USB_FLAGS_SLEEP, NULL, NULL);
2063 
2064 			return (USB_FAILURE);
2065 		}
2066 	}
2067 
2068 	/* initialize the port structure. */
2069 	mutex_enter(&acm_port->acm_port_mutex);
2070 	acm_port->acm_bulkin_size = in_data->ep_descr.wMaxPacketSize;
2071 	acm_port->acm_bulkin_state = USBSACM_PIPE_IDLE;
2072 	acm_port->acm_bulkout_state = USBSACM_PIPE_IDLE;
2073 	if (acm_port->acm_intr_ph != NULL) {
2074 		acm_port->acm_intr_state = USBSACM_PIPE_IDLE;
2075 		acm_port->acm_intr_ep_descr = intr_pipe->ep_descr;
2076 	}
2077 	mutex_exit(&acm_port->acm_port_mutex);
2078 
2079 	if (acm_port->acm_intr_ph != NULL) {
2080 
2081 		usbsacm_pipe_start_polling(acm_port);
2082 	}
2083 
2084 	return (rval);
2085 }
2086 
2087 
2088 /*
2089  * usbsacm_close_port_pipes:
2090  *	Close pipes of one port and reset port structure to closed;
2091  *	Each port includes three pipes: bulk in, bulk out and interrupt.
2092  */
2093 static void
2094 usbsacm_close_port_pipes(usbsacm_port_t	*acm_port)
2095 {
2096 	usbsacm_state_t	*acmp = acm_port->acm_device;
2097 
2098 	mutex_enter(&acm_port->acm_port_mutex);
2099 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
2100 	    "usbsacm_close_port_pipes: acm_bulkin_state = %d",
2101 	    acm_port->acm_bulkin_state);
2102 
2103 	/*
2104 	 * Check the status of the given port. If port is closing or closed,
2105 	 * return directly.
2106 	 */
2107 	if ((acm_port->acm_bulkin_state == USBSACM_PIPE_CLOSED) ||
2108 	    (acm_port->acm_bulkin_state == USBSACM_PIPE_CLOSING)) {
2109 		USB_DPRINTF_L2(PRINT_MASK_CLOSE, acmp->acm_lh,
2110 		    "usbsacm_close_port_pipes: port is closing or has closed");
2111 		mutex_exit(&acm_port->acm_port_mutex);
2112 
2113 		return;
2114 	}
2115 
2116 	acm_port->acm_bulkin_state = USBSACM_PIPE_CLOSING;
2117 	mutex_exit(&acm_port->acm_port_mutex);
2118 
2119 	/* Close pipes */
2120 	usb_pipe_reset(acmp->acm_dip, acm_port->acm_bulkin_ph,
2121 	    USB_FLAGS_SLEEP, 0, 0);
2122 	usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkin_ph,
2123 	    USB_FLAGS_SLEEP, 0, 0);
2124 	usb_pipe_close(acmp->acm_dip, acm_port->acm_bulkout_ph,
2125 	    USB_FLAGS_SLEEP, 0, 0);
2126 	if (acm_port->acm_intr_ph != NULL) {
2127 		usb_pipe_stop_intr_polling(acm_port->acm_intr_ph,
2128 		    USB_FLAGS_SLEEP);
2129 		usb_pipe_close(acmp->acm_dip, acm_port->acm_intr_ph,
2130 		    USB_FLAGS_SLEEP, 0, 0);
2131 	}
2132 
2133 	mutex_enter(&acm_port->acm_port_mutex);
2134 	/* Reset the status of pipes to closed */
2135 	acm_port->acm_bulkin_state = USBSACM_PIPE_CLOSED;
2136 	acm_port->acm_bulkin_ph = NULL;
2137 	acm_port->acm_bulkout_state = USBSACM_PIPE_CLOSED;
2138 	acm_port->acm_bulkout_ph = NULL;
2139 	if (acm_port->acm_intr_ph != NULL) {
2140 		acm_port->acm_intr_state = USBSACM_PIPE_CLOSED;
2141 		acm_port->acm_intr_ph = NULL;
2142 	}
2143 
2144 	mutex_exit(&acm_port->acm_port_mutex);
2145 
2146 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
2147 	    "usbsacm_close_port_pipes: port has been closed.");
2148 }
2149 
2150 
2151 /*
2152  * usbsacm_close_pipes:
2153  *	close all opened pipes of current devices.
2154  */
2155 static void
2156 usbsacm_close_pipes(usbsacm_state_t *acmp)
2157 {
2158 	int		i;
2159 
2160 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
2161 	    "usbsacm_close_pipes: ");
2162 
2163 	/* Close all ports */
2164 	for (i = 0; i < acmp->acm_port_cnt; i++) {
2165 		usbsacm_close_port_pipes(&acmp->acm_ports[i]);
2166 	}
2167 }
2168 
2169 
2170 /*
2171  * usbsacm_disconnect_pipes:
2172  *	this function just call usbsacm_close_pipes.
2173  */
2174 static void
2175 usbsacm_disconnect_pipes(usbsacm_state_t *acmp)
2176 {
2177 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
2178 	    "usbsacm_disconnect_pipes: ");
2179 
2180 	usbsacm_close_pipes(acmp);
2181 }
2182 
2183 
2184 /*
2185  * usbsacm_reconnect_pipes:
2186  *	reconnect pipes in CPR resume or reconnect
2187  */
2188 static int
2189 usbsacm_reconnect_pipes(usbsacm_state_t *acmp)
2190 {
2191 	usbsacm_port_t	*cur_port = acmp->acm_ports;
2192 	int		i;
2193 
2194 	USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh,
2195 	    "usbsacm_reconnect_pipes: ");
2196 
2197 	/* reopen all ports of current device. */
2198 	for (i = 0; i < acmp->acm_port_cnt; i++) {
2199 		cur_port = &acmp->acm_ports[i];
2200 
2201 		mutex_enter(&cur_port->acm_port_mutex);
2202 		/*
2203 		 * If port status is open, reopen it;
2204 		 * else retain the current status.
2205 		 */
2206 		if (cur_port->acm_port_state == USBSACM_PORT_OPEN) {
2207 
2208 			mutex_exit(&cur_port->acm_port_mutex);
2209 			if (usbsacm_open_port_pipes(cur_port) != USB_SUCCESS) {
2210 				USB_DPRINTF_L4(PRINT_MASK_OPEN, acmp->acm_lh,
2211 				    "usbsacm_reconnect_pipes: "
2212 				    "open port %d failed.", i);
2213 
2214 				return (USB_FAILURE);
2215 			}
2216 			mutex_enter(&cur_port->acm_port_mutex);
2217 		}
2218 		mutex_exit(&cur_port->acm_port_mutex);
2219 	}
2220 
2221 	return (USB_SUCCESS);
2222 }
2223 
2224 /*
2225  * usbsacm_bulkin_cb:
2226  *	Bulk In regular and exeception callback;
2227  *	USBA framework will call this callback
2228  *	after deal with bulkin request.
2229  */
2230 /*ARGSUSED*/
2231 static void
2232 usbsacm_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
2233 {
2234 	usbsacm_port_t	*acm_port = (usbsacm_port_t *)req->bulk_client_private;
2235 	usbsacm_state_t	*acmp = acm_port->acm_device;
2236 	mblk_t		*data;
2237 	int		data_len;
2238 
2239 	data = req->bulk_data;
2240 	data_len = (data) ? MBLKL(data) : 0;
2241 
2242 	mutex_enter(&acm_port->acm_port_mutex);
2243 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh,
2244 	    "usbsacm_bulkin_cb: "
2245 	    "acm_bulkin_state = %d acm_port_state = %d data_len = %d",
2246 	    acm_port->acm_bulkin_state, acm_port->acm_port_state, data_len);
2247 
2248 	if ((acm_port->acm_port_state == USBSACM_PORT_OPEN) && (data_len) &&
2249 	    (req->bulk_completion_reason == USB_CR_OK)) {
2250 		mutex_exit(&acm_port->acm_port_mutex);
2251 		/* prevent USBA from freeing data along with the request */
2252 		req->bulk_data = NULL;
2253 
2254 		/* save data on the receive list */
2255 		usbsacm_put_tail(&acm_port->acm_rx_mp, data);
2256 
2257 		/* invoke GSD receive callback */
2258 		if (acm_port->acm_cb.cb_rx) {
2259 			acm_port->acm_cb.cb_rx(acm_port->acm_cb.cb_arg);
2260 		}
2261 		mutex_enter(&acm_port->acm_port_mutex);
2262 	}
2263 	mutex_exit(&acm_port->acm_port_mutex);
2264 
2265 	usb_free_bulk_req(req);
2266 
2267 	/* receive more */
2268 	mutex_enter(&acm_port->acm_port_mutex);
2269 	if (((acm_port->acm_bulkin_state == USBSACM_PIPE_BUSY) ||
2270 	    (acm_port->acm_bulkin_state == USBSACM_PIPE_IDLE)) &&
2271 	    (acm_port->acm_port_state == USBSACM_PORT_OPEN) &&
2272 	    (acmp->acm_dev_state == USB_DEV_ONLINE)) {
2273 		if (usbsacm_rx_start(acm_port) != USB_SUCCESS) {
2274 			USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2275 			    "usbsacm_bulkin_cb: restart rx fail "
2276 			    "acm_port_state = %d", acm_port->acm_port_state);
2277 		}
2278 	} else if (acm_port->acm_bulkin_state == USBSACM_PIPE_BUSY) {
2279 		acm_port->acm_bulkin_state = USBSACM_PIPE_IDLE;
2280 	}
2281 	mutex_exit(&acm_port->acm_port_mutex);
2282 }
2283 
2284 
2285 /*
2286  * usbsacm_bulkout_cb:
2287  *	Bulk Out regular and exeception callback;
2288  *	USBA framework will call this callback function
2289  *	after deal with bulkout request.
2290  */
2291 /*ARGSUSED*/
2292 static void
2293 usbsacm_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
2294 {
2295 	usbsacm_port_t	*acm_port = (usbsacm_port_t *)req->bulk_client_private;
2296 	usbsacm_state_t	*acmp = acm_port->acm_device;
2297 	int		data_len;
2298 	mblk_t		*data = req->bulk_data;
2299 
2300 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh,
2301 	    "usbsacm_bulkout_cb: acmp = 0x%p", (void *)acmp);
2302 
2303 	data_len = (req->bulk_data) ? MBLKL(req->bulk_data) : 0;
2304 
2305 	/* put untransferred residue back on the transfer list */
2306 	if (req->bulk_completion_reason && (data_len > 0)) {
2307 		usbsacm_put_head(&acm_port->acm_tx_mp, data);
2308 		req->bulk_data = NULL;
2309 	}
2310 
2311 	usb_free_bulk_req(req);
2312 
2313 	/* invoke GSD transmit callback */
2314 	if (acm_port->acm_cb.cb_tx) {
2315 		acm_port->acm_cb.cb_tx(acm_port->acm_cb.cb_arg);
2316 	}
2317 
2318 	/* send more */
2319 	mutex_enter(&acm_port->acm_port_mutex);
2320 	acm_port->acm_bulkout_state = USBSACM_PIPE_IDLE;
2321 	if (acm_port->acm_tx_mp == NULL) {
2322 		cv_broadcast(&acm_port->acm_tx_cv);
2323 	} else {
2324 		usbsacm_tx_start(acm_port);
2325 	}
2326 	mutex_exit(&acm_port->acm_port_mutex);
2327 }
2328 
2329 
2330 /*
2331  * usbsacm_rx_start:
2332  *	start data receipt
2333  */
2334 static int
2335 usbsacm_rx_start(usbsacm_port_t *acm_port)
2336 {
2337 	usbsacm_state_t	*acmp = acm_port->acm_device;
2338 	usb_bulk_req_t	*br;
2339 	int		rval = USB_FAILURE;
2340 	int		data_len;
2341 
2342 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh,
2343 	    "usbsacm_rx_start: acm_xfer_sz = 0x%lx acm_bulkin_size = 0x%lx",
2344 	    acmp->acm_xfer_sz, acm_port->acm_bulkin_size);
2345 
2346 	acm_port->acm_bulkin_state = USBSACM_PIPE_BUSY;
2347 	/*
2348 	 * Qualcomm CDMA card won't response the first request,
2349 	 * if the following code don't multiply by 2.
2350 	 */
2351 	data_len = min(acmp->acm_xfer_sz, acm_port->acm_bulkin_size * 2);
2352 	mutex_exit(&acm_port->acm_port_mutex);
2353 
2354 	br = usb_alloc_bulk_req(acmp->acm_dip, data_len, USB_FLAGS_SLEEP);
2355 	if (br == NULL) {
2356 		USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2357 		    "usbsacm_rx_start: allocate bulk request failed");
2358 
2359 		mutex_enter(&acm_port->acm_port_mutex);
2360 
2361 		return (USB_FAILURE);
2362 	}
2363 	/* initialize bulk in request. */
2364 	br->bulk_len = data_len;
2365 	br->bulk_timeout = USBSACM_BULKIN_TIMEOUT;
2366 	br->bulk_cb = usbsacm_bulkin_cb;
2367 	br->bulk_exc_cb = usbsacm_bulkin_cb;
2368 	br->bulk_client_private = (usb_opaque_t)acm_port;
2369 	br->bulk_attributes = USB_ATTRS_AUTOCLEARING
2370 	    | USB_ATTRS_SHORT_XFER_OK;
2371 
2372 	rval = usb_pipe_bulk_xfer(acm_port->acm_bulkin_ph, br, 0);
2373 
2374 	mutex_enter(&acm_port->acm_port_mutex);
2375 	if (rval != USB_SUCCESS) {
2376 		USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2377 		    "usbsacm_rx_start: bulk transfer failed %d", rval);
2378 		usb_free_bulk_req(br);
2379 		acm_port->acm_bulkin_state = USBSACM_PIPE_IDLE;
2380 	}
2381 
2382 	return (rval);
2383 }
2384 
2385 
2386 /*
2387  * usbsacm_tx_start:
2388  *	start data transmit
2389  */
2390 static void
2391 usbsacm_tx_start(usbsacm_port_t *acm_port)
2392 {
2393 	int		len;		/* bytes we can transmit */
2394 	mblk_t		*data;		/* data to be transmitted */
2395 	int		data_len;	/* bytes in 'data' */
2396 	mblk_t		*mp;		/* current msgblk */
2397 	int		copylen;	/* bytes copy from 'mp' to 'data' */
2398 	int		rval;
2399 	usbsacm_state_t	*acmp = acm_port->acm_device;
2400 
2401 	USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
2402 	    "usbsacm_tx_start: ");
2403 
2404 	/* check the transmitted data. */
2405 	if (acm_port->acm_tx_mp == NULL) {
2406 		USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2407 		    "usbsacm_tx_start: acm_tx_mp is NULL");
2408 
2409 		return;
2410 	}
2411 
2412 	/* check pipe status */
2413 	if (acm_port->acm_bulkout_state != USBSACM_PIPE_IDLE) {
2414 
2415 		USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2416 		    "usbsacm_tx_start: error state in bulkout endpoint");
2417 
2418 		return;
2419 	}
2420 	ASSERT(MBLKL(acm_port->acm_tx_mp) > 0);
2421 
2422 	/* send as much data as port can receive */
2423 	len = min(msgdsize(acm_port->acm_tx_mp), acmp->acm_xfer_sz);
2424 
2425 	if (len == 0) {
2426 		USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2427 		    "usbsacm_tx_start: data len is 0");
2428 
2429 		return;
2430 	}
2431 
2432 	/* allocate memory for sending data. */
2433 	if ((data = allocb(len, BPRI_LO)) == NULL) {
2434 		USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2435 		    "usbsacm_tx_start: failure in allocate memory");
2436 
2437 		return;
2438 	}
2439 
2440 	/*
2441 	 * copy no more than 'len' bytes from mblk chain to transmit mblk 'data'
2442 	 */
2443 	data_len = 0;
2444 	while ((data_len < len) && acm_port->acm_tx_mp) {
2445 		/* Get the first mblk from chain. */
2446 		mp = acm_port->acm_tx_mp;
2447 		copylen = min(MBLKL(mp), len - data_len);
2448 		bcopy(mp->b_rptr, data->b_wptr, copylen);
2449 		mp->b_rptr += copylen;
2450 		data->b_wptr += copylen;
2451 		data_len += copylen;
2452 
2453 		if (MBLKL(mp) < 1) {
2454 			acm_port->acm_tx_mp = unlinkb(mp);
2455 			freeb(mp);
2456 		} else {
2457 			ASSERT(data_len == len);
2458 		}
2459 	}
2460 
2461 	if (data_len <= 0) {
2462 		freeb(data);
2463 
2464 		return;
2465 	}
2466 
2467 	acm_port->acm_bulkout_state = USBSACM_PIPE_BUSY;
2468 
2469 	mutex_exit(&acm_port->acm_port_mutex);
2470 	/* send request. */
2471 	rval = usbsacm_send_data(acm_port, data);
2472 	mutex_enter(&acm_port->acm_port_mutex);
2473 
2474 	/*
2475 	 * If send failed, retransmit data when acm_tx_mp is null.
2476 	 */
2477 	if (rval != USB_SUCCESS) {
2478 		acm_port->acm_bulkout_state = USBSACM_PIPE_IDLE;
2479 		if (acm_port->acm_tx_mp == NULL) {
2480 			usbsacm_put_head(&acm_port->acm_tx_mp, data);
2481 		}
2482 	}
2483 }
2484 
2485 
2486 /*
2487  * usbsacm_send_data:
2488  *	data transfer
2489  */
2490 static int
2491 usbsacm_send_data(usbsacm_port_t *acm_port, mblk_t *data)
2492 {
2493 	usbsacm_state_t	*acmp = acm_port->acm_device;
2494 	usb_bulk_req_t	*br;
2495 	int		rval;
2496 	int		data_len = MBLKL(data);
2497 
2498 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, acmp->acm_lh,
2499 	    "usbsacm_send_data: data address is 0x%p, length = %d",
2500 	    (void *)data, data_len);
2501 
2502 	br = usb_alloc_bulk_req(acmp->acm_dip, 0, USB_FLAGS_SLEEP);
2503 	if (br == NULL) {
2504 		USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
2505 		    "usbsacm_send_data: alloc req failed.");
2506 
2507 		return (USB_FAILURE);
2508 	}
2509 
2510 	/* initialize the bulk out request */
2511 	br->bulk_data = data;
2512 	br->bulk_len = data_len;
2513 	br->bulk_timeout = USBSACM_BULKOUT_TIMEOUT;
2514 	br->bulk_cb = usbsacm_bulkout_cb;
2515 	br->bulk_exc_cb = usbsacm_bulkout_cb;
2516 	br->bulk_client_private = (usb_opaque_t)acm_port;
2517 	br->bulk_attributes = USB_ATTRS_AUTOCLEARING;
2518 
2519 	rval = usb_pipe_bulk_xfer(acm_port->acm_bulkout_ph, br, 0);
2520 
2521 	if (rval != USB_SUCCESS) {
2522 		USB_DPRINTF_L2(PRINT_MASK_EVENTS, acmp->acm_lh,
2523 		    "usbsacm_send_data: Send Data failed.");
2524 
2525 		/*
2526 		 * Don't free it in usb_free_bulk_req because it will
2527 		 * be linked in usbsacm_put_head
2528 		 */
2529 		br->bulk_data = NULL;
2530 
2531 		usb_free_bulk_req(br);
2532 	}
2533 
2534 	return (rval);
2535 }
2536 
2537 /*
2538  * usbsacm_wait_tx_drain:
2539  *	wait until local tx buffer drains.
2540  *	'timeout' is in seconds, zero means wait forever
2541  */
2542 static int
2543 usbsacm_wait_tx_drain(usbsacm_port_t *acm_port, int timeout)
2544 {
2545 	clock_t		until;
2546 	int		over = 0;
2547 
2548 	until = ddi_get_lbolt() + drv_usectohz(1000 * 1000 * timeout);
2549 
2550 	while (acm_port->acm_tx_mp && !over) {
2551 		if (timeout > 0) {
2552 			over = (cv_timedwait_sig(&acm_port->acm_tx_cv,
2553 			    &acm_port->acm_port_mutex, until) <= 0);
2554 		} else {
2555 			over = (cv_wait_sig(&acm_port->acm_tx_cv,
2556 			    &acm_port->acm_port_mutex) == 0);
2557 		}
2558 	}
2559 
2560 	return ((acm_port->acm_tx_mp == NULL) ? USB_SUCCESS : USB_FAILURE);
2561 }
2562 
2563 
2564 /*
2565  * usbsacm_req_write:
2566  *	send command over control pipe
2567  */
2568 static int
2569 usbsacm_req_write(usbsacm_port_t *acm_port, uchar_t request, uint16_t value,
2570     mblk_t **data)
2571 {
2572 	usbsacm_state_t	*acmp = acm_port->acm_device;
2573 	usb_ctrl_setup_t setup;
2574 	usb_cb_flags_t	cb_flags;
2575 	usb_cr_t	cr;
2576 
2577 	USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
2578 	    "usbsacm_req_write: ");
2579 
2580 	/* initialize the control request. */
2581 	setup.bmRequestType = USBSACM_REQ_WRITE_IF;
2582 	setup.bRequest = request;
2583 	setup.wValue = value;
2584 	setup.wIndex = acm_port->acm_ctrl_if_no;
2585 	setup.wLength = ((data != NULL) && (*data != NULL)) ? MBLKL(*data) : 0;
2586 	setup.attrs = 0;
2587 
2588 	return (usb_pipe_ctrl_xfer_wait(acmp->acm_def_ph, &setup, data,
2589 	    &cr, &cb_flags, 0));
2590 }
2591 
2592 
2593 /*
2594  * usbsacm_set_line_coding:
2595  *	Send USB_CDC_REQ_SET_LINE_CODING request
2596  */
2597 static int
2598 usbsacm_set_line_coding(usbsacm_port_t *acm_port, usb_cdc_line_coding_t *lc)
2599 {
2600 	mblk_t		*bp;
2601 	int		ret;
2602 
2603 	/* allocate mblk and copy supplied structure into it */
2604 	if ((bp = allocb(USB_CDC_LINE_CODING_LEN, BPRI_HI)) == NULL) {
2605 
2606 		return (USB_NO_RESOURCES);
2607 	}
2608 
2609 #ifndef __lock_lint /* warlock gets confused here */
2610 	/* LINTED E_BAD_PTR_CAST_ALIGN */
2611 	*((usb_cdc_line_coding_t *)bp->b_wptr) = *lc;
2612 	bp->b_wptr += USB_CDC_LINE_CODING_LEN;
2613 #endif
2614 
2615 	ret = usbsacm_req_write(acm_port, USB_CDC_REQ_SET_LINE_CODING, 0, &bp);
2616 
2617 	if (bp != NULL) {
2618 		freeb(bp);
2619 	}
2620 
2621 	return (ret);
2622 }
2623 
2624 
2625 
2626 /*
2627  * usbsacm_mctl2reg:
2628  *	Set Modem control status
2629  */
2630 static void
2631 usbsacm_mctl2reg(int mask, int val, uint8_t *line_ctl)
2632 {
2633 	if (mask & TIOCM_RTS) {
2634 		if (val & TIOCM_RTS) {
2635 			*line_ctl |= USB_CDC_ACM_CONTROL_RTS;
2636 		} else {
2637 			*line_ctl &= ~USB_CDC_ACM_CONTROL_RTS;
2638 		}
2639 	}
2640 	if (mask & TIOCM_DTR) {
2641 		if (val & TIOCM_DTR) {
2642 			*line_ctl |= USB_CDC_ACM_CONTROL_DTR;
2643 		} else {
2644 			*line_ctl &= ~USB_CDC_ACM_CONTROL_DTR;
2645 		}
2646 	}
2647 }
2648 
2649 
2650 /*
2651  * usbsacm_reg2mctl:
2652  *	Get Modem control status
2653  */
2654 static int
2655 usbsacm_reg2mctl(uint8_t line_ctl)
2656 {
2657 	int	val = 0;
2658 
2659 	if (line_ctl & USB_CDC_ACM_CONTROL_RTS) {
2660 		val |= TIOCM_RTS;
2661 	}
2662 	if (line_ctl & USB_CDC_ACM_CONTROL_DTR) {
2663 		val |= TIOCM_DTR;
2664 	}
2665 	if (line_ctl & USB_CDC_ACM_CONTROL_DSR) {
2666 		val |= TIOCM_DSR;
2667 	}
2668 	if (line_ctl & USB_CDC_ACM_CONTROL_RNG) {
2669 		val |= TIOCM_RI;
2670 	}
2671 
2672 	return (val);
2673 }
2674 
2675 
2676 /*
2677  * misc routines
2678  * -------------
2679  *
2680  */
2681 
2682 /*
2683  * usbsacm_put_tail:
2684  *	link a message block to tail of message
2685  *	account for the case when message is null
2686  */
2687 static void
2688 usbsacm_put_tail(mblk_t **mpp, mblk_t *bp)
2689 {
2690 	if (*mpp) {
2691 		linkb(*mpp, bp);
2692 	} else {
2693 		*mpp = bp;
2694 	}
2695 }
2696 
2697 
2698 /*
2699  * usbsacm_put_head:
2700  *	put a message block at the head of the message
2701  *	account for the case when message is null
2702  */
2703 static void
2704 usbsacm_put_head(mblk_t **mpp, mblk_t *bp)
2705 {
2706 	if (*mpp) {
2707 		linkb(bp, *mpp);
2708 	}
2709 	*mpp = bp;
2710 }
2711 
2712 
2713 /*
2714  * power management
2715  * ----------------
2716  *
2717  * usbsacm_create_pm_components:
2718  *	create PM components
2719  */
2720 static int
2721 usbsacm_create_pm_components(usbsacm_state_t *acmp)
2722 {
2723 	dev_info_t	*dip = acmp->acm_dip;
2724 	usbsacm_pm_t	*pm;
2725 	uint_t		pwr_states;
2726 	usb_dev_descr_t *dev_descr;
2727 
2728 	USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
2729 	    "usbsacm_create_pm_components: ");
2730 
2731 	if (usb_create_pm_components(dip, &pwr_states) != USB_SUCCESS) {
2732 		USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
2733 		    "usbsacm_create_pm_components: failed");
2734 
2735 		return (USB_SUCCESS);
2736 	}
2737 
2738 	pm = acmp->acm_pm =
2739 	    (usbsacm_pm_t *)kmem_zalloc(sizeof (usbsacm_pm_t), KM_SLEEP);
2740 
2741 	pm->pm_pwr_states = (uint8_t)pwr_states;
2742 	pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
2743 	/*
2744 	 * Qualcomm CDMA card won't response the following control commands
2745 	 * after receive USB_REMOTE_WAKEUP_ENABLE. So we just set
2746 	 * pm_wakeup_enable to 0 for this specific device.
2747 	 */
2748 	dev_descr = acmp->acm_dev_data->dev_descr;
2749 	if (dev_descr->idVendor == 0x5c6 && dev_descr->idProduct == 0x3100) {
2750 		pm->pm_wakeup_enabled = 0;
2751 	} else {
2752 		pm->pm_wakeup_enabled = (usb_handle_remote_wakeup(dip,
2753 		    USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS);
2754 	}
2755 
2756 	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2757 
2758 	return (USB_SUCCESS);
2759 }
2760 
2761 
2762 /*
2763  * usbsacm_destroy_pm_components:
2764  *	destroy PM components
2765  */
2766 static void
2767 usbsacm_destroy_pm_components(usbsacm_state_t *acmp)
2768 {
2769 	usbsacm_pm_t	*pm = acmp->acm_pm;
2770 	dev_info_t	*dip = acmp->acm_dip;
2771 	int		rval;
2772 
2773 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, acmp->acm_lh,
2774 	    "usbsacm_destroy_pm_components: ");
2775 
2776 	if (acmp->acm_dev_state != USB_DEV_DISCONNECTED) {
2777 		if (pm->pm_wakeup_enabled) {
2778 			rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2779 			if (rval != DDI_SUCCESS) {
2780 				USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
2781 				    "usbsacm_destroy_pm_components: "
2782 				    "raising power failed (%d)", rval);
2783 			}
2784 
2785 			rval = usb_handle_remote_wakeup(dip,
2786 			    USB_REMOTE_WAKEUP_DISABLE);
2787 			if (rval != USB_SUCCESS) {
2788 				USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
2789 				    "usbsacm_destroy_pm_components: "
2790 				    "disable remote wakeup failed (%d)", rval);
2791 			}
2792 		}
2793 
2794 		(void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
2795 	}
2796 	kmem_free((caddr_t)pm, sizeof (usbsacm_pm_t));
2797 	acmp->acm_pm = NULL;
2798 }
2799 
2800 
2801 /*
2802  * usbsacm_pm_set_busy:
2803  *	mark device busy and raise power
2804  */
2805 static void
2806 usbsacm_pm_set_busy(usbsacm_state_t *acmp)
2807 {
2808 	usbsacm_pm_t	*pm = acmp->acm_pm;
2809 	dev_info_t	*dip = acmp->acm_dip;
2810 	int		rval;
2811 
2812 	USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
2813 	    "usbsacm_pm_set_busy: pm = 0x%p", (void *)pm);
2814 
2815 	if (pm == NULL) {
2816 
2817 		return;
2818 	}
2819 
2820 	mutex_enter(&acmp->acm_mutex);
2821 	/* if already marked busy, just increment the counter */
2822 	if (pm->pm_busy_cnt++ > 0) {
2823 		mutex_exit(&acmp->acm_mutex);
2824 
2825 		return;
2826 	}
2827 
2828 	(void) pm_busy_component(dip, 0);
2829 
2830 	if (pm->pm_cur_power == USB_DEV_OS_FULL_PWR) {
2831 		mutex_exit(&acmp->acm_mutex);
2832 
2833 		return;
2834 	}
2835 
2836 	/* need to raise power	*/
2837 	pm->pm_raise_power = B_TRUE;
2838 	mutex_exit(&acmp->acm_mutex);
2839 
2840 	rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2841 	if (rval != DDI_SUCCESS) {
2842 		USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
2843 		    "usbsacm_pm_set_busy: raising power failed");
2844 	}
2845 
2846 	mutex_enter(&acmp->acm_mutex);
2847 	pm->pm_raise_power = B_FALSE;
2848 	mutex_exit(&acmp->acm_mutex);
2849 }
2850 
2851 
2852 /*
2853  * usbsacm_pm_set_idle:
2854  *	mark device idle
2855  */
2856 static void
2857 usbsacm_pm_set_idle(usbsacm_state_t *acmp)
2858 {
2859 	usbsacm_pm_t	*pm = acmp->acm_pm;
2860 	dev_info_t	*dip = acmp->acm_dip;
2861 
2862 	USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
2863 	    "usbsacm_pm_set_idle: ");
2864 
2865 	if (pm == NULL) {
2866 
2867 		return;
2868 	}
2869 
2870 	/*
2871 	 * if more ports use the device, do not mark as yet
2872 	 */
2873 	mutex_enter(&acmp->acm_mutex);
2874 	if (--pm->pm_busy_cnt > 0) {
2875 		mutex_exit(&acmp->acm_mutex);
2876 
2877 		return;
2878 	}
2879 
2880 	if (pm) {
2881 		(void) pm_idle_component(dip, 0);
2882 	}
2883 	mutex_exit(&acmp->acm_mutex);
2884 }
2885 
2886 
2887 /*
2888  * usbsacm_pwrlvl0:
2889  *	Functions to handle power transition for OS levels 0 -> 3
2890  *	The same level as OS state, different from USB state
2891  */
2892 static int
2893 usbsacm_pwrlvl0(usbsacm_state_t *acmp)
2894 {
2895 	int		rval;
2896 	int		i;
2897 	usbsacm_port_t	*cur_port = acmp->acm_ports;
2898 
2899 	USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
2900 	    "usbsacm_pwrlvl0: ");
2901 
2902 	switch (acmp->acm_dev_state) {
2903 	case USB_DEV_ONLINE:
2904 		/* issue USB D3 command to the device */
2905 		rval = usb_set_device_pwrlvl3(acmp->acm_dip);
2906 		ASSERT(rval == USB_SUCCESS);
2907 
2908 		if (cur_port != NULL) {
2909 			for (i = 0; i < acmp->acm_port_cnt; i++) {
2910 				cur_port = &acmp->acm_ports[i];
2911 				if (cur_port->acm_intr_ph != NULL &&
2912 				    cur_port->acm_port_state !=
2913 				    USBSACM_PORT_CLOSED) {
2914 
2915 					mutex_exit(&acmp->acm_mutex);
2916 					usb_pipe_stop_intr_polling(
2917 					    cur_port->acm_intr_ph,
2918 					    USB_FLAGS_SLEEP);
2919 					mutex_enter(&acmp->acm_mutex);
2920 
2921 					mutex_enter(&cur_port->acm_port_mutex);
2922 					cur_port->acm_intr_state =
2923 					    USBSACM_PIPE_IDLE;
2924 					mutex_exit(&cur_port->acm_port_mutex);
2925 				}
2926 			}
2927 		}
2928 
2929 		acmp->acm_dev_state = USB_DEV_PWRED_DOWN;
2930 		acmp->acm_pm->pm_cur_power = USB_DEV_OS_PWR_OFF;
2931 
2932 		/* FALLTHRU */
2933 	case USB_DEV_DISCONNECTED:
2934 	case USB_DEV_SUSPENDED:
2935 		/* allow a disconnect/cpr'ed device to go to lower power */
2936 
2937 		return (USB_SUCCESS);
2938 	case USB_DEV_PWRED_DOWN:
2939 	default:
2940 		USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
2941 		    "usbsacm_pwrlvl0: illegal device state");
2942 
2943 		return (USB_FAILURE);
2944 	}
2945 }
2946 
2947 
2948 /*
2949  * usbsacm_pwrlvl1:
2950  *	Functions to handle power transition for OS levels 1 -> 2
2951  */
2952 static int
2953 usbsacm_pwrlvl1(usbsacm_state_t *acmp)
2954 {
2955 	/* issue USB D2 command to the device */
2956 	(void) usb_set_device_pwrlvl2(acmp->acm_dip);
2957 
2958 	return (USB_FAILURE);
2959 }
2960 
2961 
2962 /*
2963  * usbsacm_pwrlvl2:
2964  *	Functions to handle power transition for OS levels 2 -> 1
2965  */
2966 static int
2967 usbsacm_pwrlvl2(usbsacm_state_t *acmp)
2968 {
2969 	/* issue USB D1 command to the device */
2970 	(void) usb_set_device_pwrlvl1(acmp->acm_dip);
2971 
2972 	return (USB_FAILURE);
2973 }
2974 
2975 
2976 /*
2977  * usbsacm_pwrlvl3:
2978  *	Functions to handle power transition for OS levels 3 -> 0
2979  *	The same level as OS state, different from USB state
2980  */
2981 static int
2982 usbsacm_pwrlvl3(usbsacm_state_t *acmp)
2983 {
2984 	int		rval;
2985 	int		i;
2986 	usbsacm_port_t	*cur_port = acmp->acm_ports;
2987 
2988 	USB_DPRINTF_L4(PRINT_MASK_PM, acmp->acm_lh,
2989 	    "usbsacm_pwrlvl3: ");
2990 
2991 	switch (acmp->acm_dev_state) {
2992 	case USB_DEV_PWRED_DOWN:
2993 		/* Issue USB D0 command to the device here */
2994 		rval = usb_set_device_pwrlvl0(acmp->acm_dip);
2995 		ASSERT(rval == USB_SUCCESS);
2996 
2997 		if (cur_port != NULL) {
2998 			for (i = 0; i < acmp->acm_port_cnt; i++) {
2999 				cur_port = &acmp->acm_ports[i];
3000 				if (cur_port->acm_intr_ph != NULL &&
3001 				    cur_port->acm_port_state !=
3002 				    USBSACM_PORT_CLOSED) {
3003 
3004 					mutex_exit(&acmp->acm_mutex);
3005 					usbsacm_pipe_start_polling(cur_port);
3006 					mutex_enter(&acmp->acm_mutex);
3007 				}
3008 			}
3009 		}
3010 
3011 		acmp->acm_dev_state = USB_DEV_ONLINE;
3012 		acmp->acm_pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
3013 
3014 		/* FALLTHRU */
3015 	case USB_DEV_ONLINE:
3016 		/* we are already in full power */
3017 
3018 		/* FALLTHRU */
3019 	case USB_DEV_DISCONNECTED:
3020 	case USB_DEV_SUSPENDED:
3021 
3022 		return (USB_SUCCESS);
3023 	default:
3024 		USB_DPRINTF_L2(PRINT_MASK_PM, acmp->acm_lh,
3025 		    "usbsacm_pwrlvl3: illegal device state");
3026 
3027 		return (USB_FAILURE);
3028 	}
3029 }
3030 
3031 
3032 /*
3033  * usbsacm_pipe_start_polling:
3034  *	start polling on the interrupt pipe
3035  */
3036 static void
3037 usbsacm_pipe_start_polling(usbsacm_port_t *acm_port)
3038 {
3039 	usb_intr_req_t	*intr;
3040 	int		rval;
3041 	usbsacm_state_t	*acmp = acm_port->acm_device;
3042 
3043 	USB_DPRINTF_L4(PRINT_MASK_ATTA, acmp->acm_lh,
3044 	    "usbsacm_pipe_start_polling: ");
3045 
3046 	if (acm_port->acm_intr_ph == NULL) {
3047 
3048 		return;
3049 	}
3050 
3051 	intr = usb_alloc_intr_req(acmp->acm_dip, 0, USB_FLAGS_SLEEP);
3052 
3053 	/*
3054 	 * If it is in interrupt context, usb_alloc_intr_req will return NULL if
3055 	 * called with SLEEP flag.
3056 	 */
3057 	if (!intr) {
3058 		USB_DPRINTF_L2(PRINT_MASK_OPEN, acmp->acm_lh,
3059 		    "usbsacm_pipe_start_polling: alloc req failed.");
3060 
3061 		return;
3062 	}
3063 
3064 	/* initialize the interrupt request. */
3065 	intr->intr_attributes = USB_ATTRS_SHORT_XFER_OK |
3066 	    USB_ATTRS_AUTOCLEARING;
3067 	mutex_enter(&acm_port->acm_port_mutex);
3068 	intr->intr_len = acm_port->acm_intr_ep_descr.wMaxPacketSize;
3069 	mutex_exit(&acm_port->acm_port_mutex);
3070 	intr->intr_client_private = (usb_opaque_t)acm_port;
3071 	intr->intr_cb = usbsacm_intr_cb;
3072 	intr->intr_exc_cb = usbsacm_intr_ex_cb;
3073 
3074 	rval = usb_pipe_intr_xfer(acm_port->acm_intr_ph, intr, USB_FLAGS_SLEEP);
3075 
3076 	mutex_enter(&acm_port->acm_port_mutex);
3077 	if (rval == USB_SUCCESS) {
3078 		acm_port->acm_intr_state = USBSACM_PIPE_BUSY;
3079 	} else {
3080 		usb_free_intr_req(intr);
3081 		acm_port->acm_intr_state = USBSACM_PIPE_IDLE;
3082 		USB_DPRINTF_L3(PRINT_MASK_OPEN, acmp->acm_lh,
3083 		    "usbsacm_pipe_start_polling: failed (%d)", rval);
3084 	}
3085 	mutex_exit(&acm_port->acm_port_mutex);
3086 }
3087 
3088 
3089 /*
3090  * usbsacm_intr_cb:
3091  *	interrupt pipe normal callback
3092  */
3093 /*ARGSUSED*/
3094 static void
3095 usbsacm_intr_cb(usb_pipe_handle_t ph, usb_intr_req_t *req)
3096 {
3097 	usbsacm_port_t	*acm_port = (usbsacm_port_t *)req->intr_client_private;
3098 	usbsacm_state_t	*acmp = acm_port->acm_device;
3099 	mblk_t		*data = req->intr_data;
3100 	int		data_len;
3101 
3102 	USB_DPRINTF_L4(PRINT_MASK_CB, acmp->acm_lh,
3103 	    "usbsacm_intr_cb: ");
3104 
3105 	data_len = (data) ? MBLKL(data) : 0;
3106 
3107 	/* check data length */
3108 	if (data_len < 8) {
3109 		USB_DPRINTF_L2(PRINT_MASK_CB, acmp->acm_lh,
3110 		    "usbsacm_intr_cb: %d packet too short", data_len);
3111 		usb_free_intr_req(req);
3112 
3113 		return;
3114 	}
3115 	req->intr_data = NULL;
3116 	usb_free_intr_req(req);
3117 
3118 	mutex_enter(&acm_port->acm_port_mutex);
3119 	/* parse interrupt data. */
3120 	usbsacm_parse_intr_data(acm_port, data);
3121 	mutex_exit(&acm_port->acm_port_mutex);
3122 }
3123 
3124 
3125 /*
3126  * usbsacm_intr_ex_cb:
3127  *	interrupt pipe exception callback
3128  */
3129 /*ARGSUSED*/
3130 static void
3131 usbsacm_intr_ex_cb(usb_pipe_handle_t ph, usb_intr_req_t *req)
3132 {
3133 	usbsacm_port_t	*acm_port = (usbsacm_port_t *)req->intr_client_private;
3134 	usbsacm_state_t	*acmp = acm_port->acm_device;
3135 	usb_cr_t	cr = req->intr_completion_reason;
3136 
3137 	USB_DPRINTF_L4(PRINT_MASK_CB, acmp->acm_lh,
3138 	    "usbsacm_intr_ex_cb: ");
3139 
3140 	usb_free_intr_req(req);
3141 
3142 	/*
3143 	 * If completion reason isn't USB_CR_PIPE_CLOSING and
3144 	 * USB_CR_STOPPED_POLLING, restart polling.
3145 	 */
3146 	if ((cr != USB_CR_PIPE_CLOSING) && (cr != USB_CR_STOPPED_POLLING)) {
3147 		mutex_enter(&acmp->acm_mutex);
3148 
3149 		if (acmp->acm_dev_state != USB_DEV_ONLINE) {
3150 
3151 			USB_DPRINTF_L3(PRINT_MASK_CB, acmp->acm_lh,
3152 			    "usbsacm_intr_ex_cb: state = %d",
3153 			    acmp->acm_dev_state);
3154 
3155 			mutex_exit(&acmp->acm_mutex);
3156 
3157 			return;
3158 		}
3159 		mutex_exit(&acmp->acm_mutex);
3160 
3161 		usbsacm_pipe_start_polling(acm_port);
3162 	}
3163 }
3164 
3165 
3166 /*
3167  * usbsacm_parse_intr_data:
3168  *	Parse data received from interrupt callback
3169  */
3170 static void
3171 usbsacm_parse_intr_data(usbsacm_port_t *acm_port, mblk_t *data)
3172 {
3173 	usbsacm_state_t	*acmp = acm_port->acm_device;
3174 	uint8_t		bmRequestType;
3175 	uint8_t		bNotification;
3176 	uint16_t	wValue;
3177 	uint16_t	wLength;
3178 	uint16_t	wData;
3179 
3180 	USB_DPRINTF_L4(PRINT_MASK_ALL, acmp->acm_lh,
3181 	    "usbsacm_parse_intr_data: ");
3182 
3183 	bmRequestType = data->b_rptr[0];
3184 	bNotification = data->b_rptr[1];
3185 	/*
3186 	 * If Notification type is NETWORK_CONNECTION, wValue is 0 or 1,
3187 	 * mLength is 0. If Notification type is SERIAL_TYPE, mValue is 0,
3188 	 * mLength is 2. So we directly get the value from the byte.
3189 	 */
3190 	wValue = data->b_rptr[2];
3191 	wLength = data->b_rptr[6];
3192 
3193 	if (bmRequestType != USB_CDC_NOTIFICATION_REQUEST_TYPE) {
3194 		USB_DPRINTF_L2(PRINT_MASK_CB, acmp->acm_lh,
3195 		    "usbsacm_parse_intr_data: unknown request type - 0x%x",
3196 		    bmRequestType);
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 }
3293