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