xref: /illumos-gate/usr/src/uts/common/io/usb/clients/usbser/usbsprl/pl2303_dsd.c (revision 004388ebfdfe2ed7dfd2d153a876dfcc22d2c006)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  *
31  * USB Prolific PL2303 device-specific driver (DSD)
32  *
33  */
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/conf.h>
37 #include <sys/stream.h>
38 #include <sys/strsun.h>
39 #include <sys/termio.h>
40 #include <sys/termiox.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 
44 #define	USBDRV_MAJOR_VER	2
45 #define	USBDRV_MINOR_VER	0
46 
47 #include <sys/usb/usba.h>
48 #include <sys/usb/usba/usba_types.h>
49 #include <sys/usb/usba/usba_impl.h>
50 
51 #include <sys/usb/clients/usbser/usbser_dsdi.h>
52 #include <sys/usb/clients/usbser/usbsprl/pl2303_var.h>
53 #include <sys/usb/clients/usbser/usbsprl/pl2303_vendor.h>
54 
55 
56 /*
57  * DSD operations
58  */
59 static int	pl2303_attach(ds_attach_info_t *);
60 static void	pl2303_detach(ds_hdl_t);
61 static int	pl2303_register_cb(ds_hdl_t, uint_t, ds_cb_t *);
62 static void	pl2303_unregister_cb(ds_hdl_t, uint_t);
63 static int	pl2303_open_port(ds_hdl_t, uint_t);
64 static int	pl2303_close_port(ds_hdl_t, uint_t);
65 
66 /* power management */
67 static int	pl2303_usb_power(ds_hdl_t, int, int, int *);
68 static int	pl2303_suspend(ds_hdl_t);
69 static int	pl2303_resume(ds_hdl_t);
70 static int	pl2303_disconnect(ds_hdl_t);
71 static int	pl2303_reconnect(ds_hdl_t);
72 
73 /* standard UART operations */
74 static int	pl2303_set_port_params(ds_hdl_t, uint_t, ds_port_params_t *);
75 static int	pl2303_set_modem_ctl(ds_hdl_t, uint_t, int, int);
76 static int	pl2303_get_modem_ctl(ds_hdl_t, uint_t, int, int *);
77 static int	pl2303_break_ctl(ds_hdl_t, uint_t, int);
78 
79 /* data xfer */
80 static int	pl2303_tx(ds_hdl_t, uint_t, mblk_t *);
81 static mblk_t	*pl2303_rx(ds_hdl_t, uint_t);
82 static void	pl2303_stop(ds_hdl_t, uint_t, int);
83 static void	pl2303_start(ds_hdl_t, uint_t, int);
84 static int	pl2303_fifo_flush(ds_hdl_t, uint_t, int);
85 static int	pl2303_fifo_drain(ds_hdl_t, uint_t, int);
86 
87 
88 /*
89  * Sub-routines
90  */
91 
92 /* configuration routines */
93 static void	pl2303_cleanup(pl2303_state_t *, int);
94 static int	pl2303_dev_attach(pl2303_state_t *);
95 static int	pl2303_open_hw_port(pl2303_state_t *);
96 
97 /* hotplug */
98 static int	pl2303_restore_device_state(pl2303_state_t *);
99 static int	pl2303_restore_port_state(pl2303_state_t *);
100 
101 /* power management */
102 static int	pl2303_create_pm_components(pl2303_state_t *);
103 static void	pl2303_destroy_pm_components(pl2303_state_t *);
104 static int	pl2303_pm_set_busy(pl2303_state_t *);
105 static void	pl2303_pm_set_idle(pl2303_state_t *);
106 static int	pl2303_pwrlvl0(pl2303_state_t *);
107 static int	pl2303_pwrlvl1(pl2303_state_t *);
108 static int	pl2303_pwrlvl2(pl2303_state_t *);
109 static int	pl2303_pwrlvl3(pl2303_state_t *);
110 
111 /* pipe operations */
112 static int	pl2303_open_pipes(pl2303_state_t *);
113 static void	pl2303_close_pipes(pl2303_state_t *);
114 static void	pl2303_disconnect_pipes(pl2303_state_t *);
115 static int	pl2303_reconnect_pipes(pl2303_state_t *);
116 
117 /* pipe callbacks */
118 void		pl2303_bulkin_cb(usb_pipe_handle_t, usb_bulk_req_t *);
119 void		pl2303_bulkout_cb(usb_pipe_handle_t, usb_bulk_req_t *);
120 
121 /* data transfer routines */
122 static int	pl2303_rx_start(pl2303_state_t *);
123 static void	pl2303_tx_start(pl2303_state_t *, int *);
124 static int	pl2303_send_data(pl2303_state_t *, mblk_t *);
125 static int	pl2303_wait_tx_drain(pl2303_state_t *, int);
126 
127 /* vendor-specific commands */
128 static int	pl2303_cmd_get_line(pl2303_state_t *, mblk_t **);
129 static int	pl2303_cmd_set_line(pl2303_state_t *, mblk_t *);
130 static int	pl2303_cmd_set_ctl(pl2303_state_t *, uint8_t);
131 static int	pl2303_cmd_vendor_write0(pl2303_state_t *, uint16_t, int16_t);
132 static int	pl2303_cmd_set_rtscts(pl2303_state_t *);
133 static int	pl2303_cmd_break(pl2303_state_t *, int);
134 static void	pl2303_mctl2reg(int mask, int val, uint8_t *);
135 static int	pl2303_reg2mctl(uint8_t);
136 
137 /* misc */
138 static void	pl2303_put_tail(mblk_t **, mblk_t *);
139 static void	pl2303_put_head(mblk_t **, mblk_t *);
140 
141 
142 /*
143  * DSD ops structure
144  */
145 ds_ops_t ds_ops = {
146 	DS_OPS_VERSION,
147 	pl2303_attach,
148 	pl2303_detach,
149 	pl2303_register_cb,
150 	pl2303_unregister_cb,
151 	pl2303_open_port,
152 	pl2303_close_port,
153 	pl2303_usb_power,
154 	pl2303_suspend,
155 	pl2303_resume,
156 	pl2303_disconnect,
157 	pl2303_reconnect,
158 	pl2303_set_port_params,
159 	pl2303_set_modem_ctl,
160 	pl2303_get_modem_ctl,
161 	pl2303_break_ctl,
162 	NULL,			/* HW don't support loopback */
163 	pl2303_tx,
164 	pl2303_rx,
165 	pl2303_stop,
166 	pl2303_start,
167 	pl2303_fifo_flush,
168 	pl2303_fifo_drain
169 };
170 
171 
172 /*
173  * baud code into baud rate
174  * value 0 means not supported in hardware
175  *
176  */
177 static int pl2303_speedtab[] = {
178 	0,	/* B0 */
179 	0,	/* B50 */
180 	75,	/* B75 */
181 	0,	/* B110 */
182 	0,	/* B134 */
183 	150,	/* B150 */
184 	0,	/* B200 */
185 	300,	/* B300 */
186 	600,	/* B600 */
187 	1200,	/* B1200 */
188 	1800,	/* B1800 */
189 	2400,	/* B2400 */
190 	4800,	/* B4800 */
191 	9600,	/* B9600 */
192 	19200,	/* B19200 */
193 	38400,	/* B38400 */
194 	57600,	/* B57600 */
195 	0,	/* B76800 */
196 	115200,	/* B115200 */
197 	0,	/* B153600 */
198 	230400,	/* B230400 */
199 	0,	/* B307200 */
200 	460800	/* B460800 */
201 };
202 
203 
204 /* debug support */
205 static uint_t	pl2303_errlevel = USB_LOG_L4;
206 static uint_t	pl2303_errmask = DPRINT_MASK_ALL;
207 static uint_t	pl2303_instance_debug = (uint_t)-1;
208 
209 
210 /*
211  * ds_attach
212  */
213 static int
214 pl2303_attach(ds_attach_info_t *aip)
215 {
216 	pl2303_state_t	*plp;
217 
218 	plp = (pl2303_state_t *)kmem_zalloc(sizeof (pl2303_state_t), KM_SLEEP);
219 	plp->pl_dip = aip->ai_dip;
220 	plp->pl_usb_events = aip->ai_usb_events;
221 	*aip->ai_hdl = (ds_hdl_t)plp;
222 
223 	/* only one port */
224 	*aip->ai_port_cnt = 1;
225 
226 	if (usb_client_attach(plp->pl_dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
227 		pl2303_cleanup(plp, 1);
228 
229 		return (USB_FAILURE);
230 	}
231 
232 	if (usb_get_dev_data(plp->pl_dip, &plp->pl_dev_data,  USB_PARSE_LVL_IF,
233 	    0) != USB_SUCCESS) {
234 		pl2303_cleanup(plp, 2);
235 
236 		return (USB_FAILURE);
237 	}
238 
239 	mutex_init(&plp->pl_mutex, NULL, MUTEX_DRIVER,
240 			plp->pl_dev_data->dev_iblock_cookie);
241 
242 	cv_init(&plp->pl_tx_cv, NULL, CV_DRIVER, NULL);
243 
244 	plp->pl_lh = usb_alloc_log_hdl(plp->pl_dip, "pl2303",
245 	    &pl2303_errlevel, &pl2303_errmask, &pl2303_instance_debug, 0);
246 
247 	/*
248 	 * check the chip type: pl2303_H, pl2303_X (or pl2303_HX)
249 	 * pl2303_UNKNOWN means not supported chip type
250 	 */
251 	if (plp->pl_dev_data->dev_descr->bcdDevice == PROLIFIC_REV_H) {
252 		mutex_enter(&plp->pl_mutex);
253 		plp->pl_chiptype = pl2303_H;
254 		mutex_exit(&plp->pl_mutex);
255 		USB_DPRINTF_L4(DPRINT_ATTACH, plp->pl_lh,
256 			"Chip Type: pl2303_H");
257 	} else if (plp->pl_dev_data->dev_descr->bcdDevice == PROLIFIC_REV_X) {
258 		/*
259 		 * pl2303_HX and pl2303_X devices have different hardware,
260 		 * but from the view of device driver, they have the same
261 		 * software interface.
262 		 *
263 		 * so "pl2303_X" will stand for both pl2303_HX and pl2303_X
264 		 * devices in this driver
265 		 */
266 		mutex_enter(&plp->pl_mutex);
267 		plp->pl_chiptype = pl2303_X;
268 		mutex_exit(&plp->pl_mutex);
269 		USB_DPRINTF_L4(DPRINT_ATTACH, plp->pl_lh,
270 			"Chip Type: pl2303_HX or pl2303_X");
271 	} else {
272 		mutex_enter(&plp->pl_mutex);
273 		plp->pl_chiptype = pl2303_UNKNOWN;
274 		mutex_exit(&plp->pl_mutex);
275 		USB_DPRINTF_L4(DPRINT_ATTACH, plp->pl_lh,
276 			"Chip Type: Unknown");
277 	}
278 
279 	plp->pl_def_ph = plp->pl_dev_data->dev_default_ph;
280 
281 	mutex_enter(&plp->pl_mutex);
282 	plp->pl_dev_state = USB_DEV_ONLINE;
283 	plp->pl_port_state = PL2303_PORT_CLOSED;
284 	mutex_exit(&plp->pl_mutex);
285 
286 	if (pl2303_create_pm_components(plp) != USB_SUCCESS) {
287 		pl2303_cleanup(plp, 3);
288 
289 		return (USB_FAILURE);
290 	}
291 
292 	if (usb_register_event_cbs(plp->pl_dip, plp->pl_usb_events, 0)
293 	    != USB_SUCCESS) {
294 		pl2303_cleanup(plp, 4);
295 
296 		return (USB_FAILURE);
297 	}
298 
299 	if (usb_pipe_get_max_bulk_transfer_size(plp->pl_dip,
300 	    &plp->pl_xfer_sz) != USB_SUCCESS) {
301 		pl2303_cleanup(plp, 5);
302 
303 		return (USB_FAILURE);
304 	}
305 
306 	if (plp->pl_xfer_sz > PL2303_XFER_SZ_MAX) {
307 		plp->pl_xfer_sz = PL2303_XFER_SZ_MAX;
308 	}
309 
310 	if (pl2303_dev_attach(plp) != USB_SUCCESS) {
311 		pl2303_cleanup(plp, 5);
312 
313 		return (USB_FAILURE);
314 	}
315 
316 	return (USB_SUCCESS);
317 }
318 
319 
320 /*
321  * ds_detach
322  */
323 static void
324 pl2303_detach(ds_hdl_t hdl)
325 {
326 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
327 
328 	pl2303_cleanup(plp, PL2303_CLEANUP_LEVEL_MAX);
329 }
330 
331 
332 /*
333  * ds_register_cb
334  */
335 /*ARGSUSED*/
336 static int
337 pl2303_register_cb(ds_hdl_t hdl, uint_t port_num, ds_cb_t *cb)
338 {
339 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
340 
341 	plp->pl_cb = *cb;
342 
343 	return (USB_SUCCESS);
344 }
345 
346 
347 /*
348  * ds_unregister_cb
349  */
350 /*ARGSUSED*/
351 static void
352 pl2303_unregister_cb(ds_hdl_t hdl, uint_t port_num)
353 {
354 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
355 
356 	bzero(&plp->pl_cb, sizeof (plp->pl_cb));
357 }
358 
359 
360 /*
361  * ds_open_port
362  */
363 /*ARGSUSED*/
364 static int
365 pl2303_open_port(ds_hdl_t hdl, uint_t port_num)
366 {
367 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
368 	int		rval = USB_FAILURE;
369 
370 	USB_DPRINTF_L4(DPRINT_OPEN, plp->pl_lh, "pl2303_open_port");
371 
372 	mutex_enter(&plp->pl_mutex);
373 	if ((plp->pl_dev_state == USB_DEV_DISCONNECTED) ||
374 	    (plp->pl_port_state != PL2303_PORT_CLOSED)) {
375 		mutex_exit(&plp->pl_mutex);
376 
377 		return (rval);
378 	}
379 
380 	mutex_exit(&plp->pl_mutex);
381 
382 	if ((rval = pl2303_pm_set_busy(plp)) != USB_SUCCESS) {
383 
384 		return (rval);
385 	}
386 
387 	/* initialize hardware serial port */
388 	rval = pl2303_open_hw_port(plp);
389 
390 	if (rval == USB_SUCCESS) {
391 		mutex_enter(&plp->pl_mutex);
392 
393 		/* start to receive data */
394 		if (pl2303_rx_start(plp) != USB_SUCCESS) {
395 			mutex_exit(&plp->pl_mutex);
396 
397 			return (USB_FAILURE);
398 		}
399 		plp->pl_port_state = PL2303_PORT_OPEN;
400 		mutex_exit(&plp->pl_mutex);
401 	} else {
402 		pl2303_pm_set_idle(plp);
403 	}
404 
405 	return (rval);
406 }
407 
408 
409 /*
410  * ds_close_port
411  */
412 /*ARGSUSED*/
413 static int
414 pl2303_close_port(ds_hdl_t hdl, uint_t port_num)
415 {
416 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
417 
418 	USB_DPRINTF_L4(DPRINT_CLOSE, plp->pl_lh, "pl2303_close_port");
419 
420 	mutex_enter(&plp->pl_mutex);
421 
422 	/* free resources and finalize state */
423 	if (plp->pl_rx_mp) {
424 		freemsg(plp->pl_rx_mp);
425 		plp->pl_rx_mp = NULL;
426 	}
427 	if (plp->pl_tx_mp) {
428 		freemsg(plp->pl_tx_mp);
429 		plp->pl_tx_mp = NULL;
430 	}
431 
432 	plp->pl_port_state = PL2303_PORT_CLOSED;
433 	mutex_exit(&plp->pl_mutex);
434 
435 	pl2303_pm_set_idle(plp);
436 
437 	return (USB_SUCCESS);
438 }
439 
440 
441 /*
442  * power management
443  * ----------------
444  *
445  * ds_usb_power
446  */
447 /*ARGSUSED*/
448 static int
449 pl2303_usb_power(ds_hdl_t hdl, int comp, int level, int *new_state)
450 {
451 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
452 	pl2303_pm_t	*pm = plp->pl_pm;
453 	int		rval;
454 
455 	USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_usb_power");
456 
457 	if (!pm) {
458 
459 		return (USB_FAILURE);
460 	}
461 
462 	mutex_enter(&plp->pl_mutex);
463 	/*
464 	 * check if we are transitioning to a legal power level
465 	 */
466 	if (USB_DEV_PWRSTATE_OK(pm->pm_pwr_states, level)) {
467 		USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh, "pl2303_usb_power: "
468 		    "illegal power level %d, pwr_states=%x",
469 		    level, pm->pm_pwr_states);
470 		mutex_exit(&plp->pl_mutex);
471 
472 		return (USB_FAILURE);
473 	}
474 
475 	/*
476 	 * if we are about to raise power and asked to lower power, fail
477 	 */
478 	if (pm->pm_raise_power && (level < (int)pm->pm_cur_power)) {
479 		mutex_exit(&plp->pl_mutex);
480 
481 		return (USB_FAILURE);
482 	}
483 
484 	switch (level) {
485 	case USB_DEV_OS_PWR_OFF:
486 		rval = pl2303_pwrlvl0(plp);
487 
488 		break;
489 	case USB_DEV_OS_PWR_1:
490 		rval = pl2303_pwrlvl1(plp);
491 
492 		break;
493 	case USB_DEV_OS_PWR_2:
494 		rval = pl2303_pwrlvl2(plp);
495 
496 		break;
497 	case USB_DEV_OS_FULL_PWR:
498 		rval = pl2303_pwrlvl3(plp);
499 
500 		break;
501 	default:
502 		ASSERT(0);	/* cannot happen */
503 	}
504 
505 	*new_state = plp->pl_dev_state;
506 	mutex_exit(&plp->pl_mutex);
507 
508 	return (rval);
509 }
510 
511 
512 /*
513  * ds_suspend
514  */
515 static int
516 pl2303_suspend(ds_hdl_t hdl)
517 {
518 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
519 	int		state;
520 
521 	USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_suspend");
522 
523 	mutex_enter(&plp->pl_mutex);
524 	state = plp->pl_dev_state = USB_DEV_SUSPENDED;
525 	mutex_exit(&plp->pl_mutex);
526 
527 	pl2303_disconnect_pipes(plp);
528 
529 	return (state);
530 }
531 
532 
533 /*
534  * ds_resume
535  */
536 static int
537 pl2303_resume(ds_hdl_t hdl)
538 {
539 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
540 	int		current_state;
541 	int		rval;
542 
543 	USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_resume");
544 
545 	(void) pm_busy_component(plp->pl_dip, 0);
546 	(void) pm_raise_power(plp->pl_dip, 0, USB_DEV_OS_FULL_PWR);
547 
548 	mutex_enter(&plp->pl_mutex);
549 	current_state = plp->pl_dev_state;
550 	mutex_exit(&plp->pl_mutex);
551 
552 	if (current_state != USB_DEV_ONLINE) {
553 		rval = pl2303_restore_device_state(plp);
554 	} else {
555 		rval = USB_SUCCESS;
556 	}
557 
558 	(void) pm_idle_component(plp->pl_dip, 0);
559 
560 	return (rval);
561 }
562 
563 
564 /*
565  * ds_disconnect
566  */
567 static int
568 pl2303_disconnect(ds_hdl_t hdl)
569 {
570 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
571 	int		state;
572 
573 	USB_DPRINTF_L4(DPRINT_HOTPLUG, plp->pl_lh, "pl2303_disconnect");
574 
575 	mutex_enter(&plp->pl_mutex);
576 	state = plp->pl_dev_state = USB_DEV_DISCONNECTED;
577 	mutex_exit(&plp->pl_mutex);
578 
579 	pl2303_disconnect_pipes(plp);
580 
581 	return (state);
582 }
583 
584 
585 /*
586  * ds_reconnect
587  */
588 static int
589 pl2303_reconnect(ds_hdl_t hdl)
590 {
591 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
592 
593 	USB_DPRINTF_L4(DPRINT_HOTPLUG, plp->pl_lh, "pl2303_reconnect");
594 
595 	return (pl2303_restore_device_state(plp));
596 }
597 
598 
599 /*
600  * standard UART operations
601  * ------------------------
602  *
603  *
604  * ds_set_port_params
605  */
606 /*ARGSUSED*/
607 static int
608 pl2303_set_port_params(ds_hdl_t hdl, uint_t port_num, ds_port_params_t *tp)
609 {
610 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
611 	int		rval = USB_FAILURE;
612 	mblk_t		*bp;
613 	int		i;
614 	uint_t		ui;
615 	int		baud;
616 	int		cnt;
617 	ds_port_param_entry_t *pe;
618 	uint16_t xonxoff_symbol;
619 	uint8_t xon_char;
620 	uint8_t xoff_char;
621 
622 	if (tp == NULL) {
623 
624 		return (rval);
625 	}
626 
627 	cnt = tp->tp_cnt;
628 	pe = tp->tp_entries;
629 
630 	USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_set_port_params");
631 
632 	/*
633 	 * get Line Coding Structure Request
634 	 * including: baud rate, stop bit, parity type and data bit
635 	 */
636 	if ((rval = pl2303_cmd_get_line(plp, &bp)) != USB_SUCCESS) {
637 
638 		return (rval);
639 	}
640 
641 	/* translate parameters into device-specific bits */
642 	for (i = 0; i < cnt; i++, pe++) {
643 		switch (pe->param) {
644 		case DS_PARAM_BAUD:
645 			ui = pe->val.ui;
646 
647 			/* if we don't support this speed, return USB_FAILURE */
648 			if ((ui >= NELEM(pl2303_speedtab)) ||
649 			    ((ui > 0) && (pl2303_speedtab[ui] == 0))) {
650 				USB_DPRINTF_L3(DPRINT_CTLOP, plp->pl_lh,
651 				    "pl2303_set_port_params: bad baud %d", ui);
652 
653 				return (USB_FAILURE);
654 			}
655 
656 			baud = pl2303_speedtab[ui];
657 			bp->b_rptr[0] = baud & 0xff;
658 			bp->b_rptr[1] = (baud >> 8) & 0xff;
659 			bp->b_rptr[2] = (baud >> 16) & 0xff;
660 			bp->b_rptr[3] = (baud >> 24) & 0xff;
661 
662 			break;
663 		case DS_PARAM_PARITY:
664 			if (pe->val.ui & PARENB) {
665 				if (pe->val.ui & PARODD) {
666 					bp->b_rptr[5] = 1;
667 				} else {
668 					bp->b_rptr[5] = 2;
669 				}
670 			} else {
671 				bp->b_rptr[5] = 0;
672 			}
673 
674 			break;
675 		case DS_PARAM_STOPB:
676 			if (pe->val.ui & CSTOPB) {
677 				bp->b_rptr[4] = 2;
678 			} else {
679 				bp->b_rptr[4] = 0;
680 			}
681 
682 			break;
683 		case DS_PARAM_CHARSZ:
684 			switch (pe->val.ui) {
685 			case CS5:
686 				bp->b_rptr[6] = 5;
687 
688 				break;
689 			case CS6:
690 				bp->b_rptr[6] = 6;
691 
692 				break;
693 			case CS7:
694 				bp->b_rptr[6] = 7;
695 
696 				break;
697 			case CS8:
698 			default:
699 				bp->b_rptr[6] = 8;
700 
701 				break;
702 			}
703 
704 			break;
705 		case DS_PARAM_XON_XOFF:
706 			/*
707 			 * Software flow control: XON/XOFF
708 			 * not supported by PL-2303H, HX chips
709 			 */
710 			if (pe->val.ui & IXON || pe->val.ui & IXOFF) {
711 				/* not supported by PL-2303H chip */
712 				switch (plp->pl_chiptype) {
713 				case pl2303_H:
714 
715 					break;
716 				case pl2303_X:
717 					xon_char = pe->val.uc[0];
718 					xoff_char = pe->val.uc[1];
719 					xonxoff_symbol = (xoff_char << 8)
720 							| xon_char;
721 
722 					rval =	pl2303_cmd_vendor_write0(
723 						plp, SET_XONXOFF,
724 						xonxoff_symbol);
725 
726 					if (rval != USB_SUCCESS) {
727 						USB_DPRINTF_L3(DPRINT_CTLOP,
728 						plp->pl_lh,
729 						"pl2303_set_port_params: "
730 						"set XonXoff failed");
731 					}
732 
733 					break;
734 				case pl2303_UNKNOWN:
735 				default:
736 
737 					break;
738 				}
739 			}
740 
741 			break;
742 		case DS_PARAM_FLOW_CTL:
743 			/* Hardware flow control */
744 			if (pe->val.ui & CTSXON) {
745 				if ((rval = pl2303_cmd_set_rtscts(plp))
746 						!= USB_SUCCESS) {
747 
748 					USB_DPRINTF_L3(DPRINT_CTLOP,
749 						plp->pl_lh,
750 						"pl2303_set_port_params: "
751 						"pl2303_cmd_set_rtscts failed");
752 				}
753 			}
754 
755 			break;
756 		default:
757 			USB_DPRINTF_L2(DPRINT_CTLOP, plp->pl_lh,
758 			    "pl2303_set_port_params: bad param %d", pe->param);
759 
760 			break;
761 		}
762 	}
763 
764 	/* set new values for Line Coding Structure */
765 	if ((rval = pl2303_cmd_set_line(plp, bp)) != USB_SUCCESS) {
766 
767 		return (rval);
768 	}
769 
770 	freeb(bp);
771 	bp = NULL;
772 
773 	/* hardware need to get Line Coding Structure again */
774 	if ((rval = pl2303_cmd_get_line(plp, &bp)) != USB_SUCCESS) {
775 
776 		if (bp != NULL) {
777 			freeb(bp);
778 		}
779 
780 		return (rval);
781 	}
782 
783 	if (bp != NULL) {
784 		freeb(bp);
785 	}
786 
787 	return (USB_SUCCESS);
788 }
789 
790 
791 /*
792  * ds_set_modem_ctl
793  */
794 /*ARGSUSED*/
795 static int
796 pl2303_set_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int val)
797 {
798 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
799 	int		rval = USB_FAILURE;
800 	uint8_t		new_mctl;
801 
802 	USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_set_modem_ctl");
803 
804 	mutex_enter(&plp->pl_mutex);
805 	new_mctl = plp->pl_mctl;
806 	mutex_exit(&plp->pl_mutex);
807 
808 	/* set RTS and DTR */
809 	pl2303_mctl2reg(mask, val, &new_mctl);
810 
811 	if ((rval = pl2303_cmd_set_ctl(plp, new_mctl)) == USB_SUCCESS) {
812 		mutex_enter(&plp->pl_mutex);
813 		plp->pl_mctl = new_mctl;
814 		mutex_exit(&plp->pl_mutex);
815 	}
816 
817 	return (rval);
818 }
819 
820 
821 /*
822  * ds_get_modem_ctl
823  */
824 /*ARGSUSED*/
825 static int
826 pl2303_get_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int *valp)
827 {
828 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
829 
830 	USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_get_modem_ctl");
831 
832 	mutex_enter(&plp->pl_mutex);
833 
834 	/* get RTS and DTR */
835 	*valp = pl2303_reg2mctl(plp->pl_mctl) & mask;
836 	*valp |= (mask & (TIOCM_CD | TIOCM_CTS | TIOCM_DSR | TIOCM_RI));
837 	mutex_exit(&plp->pl_mutex);
838 
839 	return (USB_SUCCESS);
840 }
841 
842 
843 /*
844  * ds_break_ctl
845  */
846 /*ARGSUSED*/
847 static int
848 pl2303_break_ctl(ds_hdl_t hdl, uint_t port_num, int ctl)
849 {
850 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
851 
852 	USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_break_ctl");
853 
854 	return (pl2303_cmd_break(plp, ctl));
855 }
856 
857 
858 /*
859  * ds_tx
860  */
861 /*ARGSUSED*/
862 static int
863 pl2303_tx(ds_hdl_t hdl, uint_t port_num, mblk_t *mp)
864 {
865 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
866 	int		xferd;
867 
868 	USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_tx");
869 
870 	/*
871 	 * sanity checks
872 	 */
873 	if (mp == NULL) {
874 		USB_DPRINTF_L3(DPRINT_CTLOP, plp->pl_lh, "pl2303_tx: mp=NULL");
875 
876 		return (USB_SUCCESS);
877 	}
878 	if (MBLKL(mp) <= 0) {
879 		USB_DPRINTF_L3(DPRINT_CTLOP, plp->pl_lh, "pl2303_tx: len<=0");
880 		freemsg(mp);
881 
882 		return (USB_SUCCESS);
883 	}
884 
885 	mutex_enter(&plp->pl_mutex);
886 
887 	pl2303_put_tail(&plp->pl_tx_mp, mp);	/* add to the chain */
888 
889 	pl2303_tx_start(plp, &xferd);
890 
891 	mutex_exit(&plp->pl_mutex);
892 
893 	return (USB_SUCCESS);
894 }
895 
896 
897 /*
898  * ds_rx
899  * the real data receiving is in pl2303_open_port
900  */
901 /*ARGSUSED*/
902 static mblk_t *
903 pl2303_rx(ds_hdl_t hdl, uint_t port_num)
904 {
905 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
906 	mblk_t		*mp;
907 
908 	USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_rx");
909 
910 	mutex_enter(&plp->pl_mutex);
911 	mp = plp->pl_rx_mp;
912 	plp->pl_rx_mp = NULL;
913 	mutex_exit(&plp->pl_mutex);
914 
915 	return (mp);
916 }
917 
918 
919 /*
920  * ds_stop
921  */
922 /*ARGSUSED*/
923 static void
924 pl2303_stop(ds_hdl_t hdl, uint_t port_num, int dir)
925 {
926 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
927 
928 	USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_stop");
929 
930 	if (dir & DS_TX) {
931 		mutex_enter(&plp->pl_mutex);
932 		plp->pl_port_flags |= PL2303_PORT_TX_STOPPED;
933 		mutex_exit(&plp->pl_mutex);
934 	}
935 }
936 
937 
938 /*
939  * ds_start
940  */
941 /*ARGSUSED*/
942 static void
943 pl2303_start(ds_hdl_t hdl, uint_t port_num, int dir)
944 {
945 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
946 
947 	USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_start");
948 
949 	if (dir & DS_TX) {
950 		mutex_enter(&plp->pl_mutex);
951 		if (plp->pl_port_flags & PL2303_PORT_TX_STOPPED) {
952 			plp->pl_port_flags &= ~PL2303_PORT_TX_STOPPED;
953 			pl2303_tx_start(plp, NULL);
954 		}
955 		mutex_exit(&plp->pl_mutex);
956 	}
957 }
958 
959 
960 /*
961  * ds_fifo_flush
962  */
963 /*ARGSUSED*/
964 static int
965 pl2303_fifo_flush(ds_hdl_t hdl, uint_t port_num, int dir)
966 {
967 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
968 
969 	USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_fifo_flush: dir=%x",
970 	    dir);
971 
972 	mutex_enter(&plp->pl_mutex);
973 	ASSERT(plp->pl_port_state == PL2303_PORT_OPEN);
974 
975 	if ((dir & DS_TX) && plp->pl_tx_mp) {
976 		freemsg(plp->pl_tx_mp);
977 		plp->pl_tx_mp = NULL;
978 	}
979 	if ((dir & DS_RX) && plp->pl_rx_mp) {
980 		freemsg(plp->pl_rx_mp);
981 		plp->pl_rx_mp = NULL;
982 	}
983 	mutex_exit(&plp->pl_mutex);
984 
985 	return (USB_SUCCESS);
986 }
987 
988 
989 /*
990  * ds_fifo_drain
991  */
992 /*ARGSUSED*/
993 static int
994 pl2303_fifo_drain(ds_hdl_t hdl, uint_t port_num, int timeout)
995 {
996 	pl2303_state_t	*plp = (pl2303_state_t *)hdl;
997 	int		rval = USB_SUCCESS;
998 
999 	USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_fifo_drain");
1000 
1001 	mutex_enter(&plp->pl_mutex);
1002 	ASSERT(plp->pl_port_state == PL2303_PORT_OPEN);
1003 
1004 	/*
1005 	 * for the reason of hardware, set timeout 0
1006 	 */
1007 	if (pl2303_wait_tx_drain(plp, 0) != USB_SUCCESS) {
1008 
1009 		mutex_exit(&plp->pl_mutex);
1010 
1011 		return (USB_FAILURE);
1012 	}
1013 
1014 	mutex_exit(&plp->pl_mutex);
1015 
1016 	/* wait 500 ms until hw fifo drains */
1017 	delay(drv_usectohz(500*1000));
1018 
1019 	return (rval);
1020 }
1021 
1022 
1023 /*
1024  * configuration routines
1025  * ----------------------
1026  *
1027  * clean up routine
1028  */
1029 static void
1030 pl2303_cleanup(pl2303_state_t *plp, int level)
1031 {
1032 	ASSERT((level > 0) && (level <= PL2303_CLEANUP_LEVEL_MAX));
1033 
1034 	switch (level) {
1035 	default:
1036 		pl2303_close_pipes(plp);
1037 		/* FALLTHRU */
1038 	case 5:
1039 		usb_unregister_event_cbs(plp->pl_dip, plp->pl_usb_events);
1040 		/* FALLTHRU */
1041 	case 4:
1042 		pl2303_destroy_pm_components(plp);
1043 		/* FALLTHRU */
1044 	case 3:
1045 		mutex_destroy(&plp->pl_mutex);
1046 		cv_destroy(&plp->pl_tx_cv);
1047 
1048 		usb_free_log_hdl(plp->pl_lh);
1049 		plp->pl_lh = NULL;
1050 
1051 		usb_free_descr_tree(plp->pl_dip, plp->pl_dev_data);
1052 		plp->pl_def_ph = NULL;
1053 		/* FALLTHRU */
1054 	case 2:
1055 		usb_client_detach(plp->pl_dip, plp->pl_dev_data);
1056 		/* FALLTHRU */
1057 	case 1:
1058 		kmem_free(plp, sizeof (pl2303_state_t));
1059 	}
1060 }
1061 
1062 
1063 /*
1064  * device specific attach
1065  */
1066 static int
1067 pl2303_dev_attach(pl2303_state_t *plp)
1068 {
1069 	if (pl2303_open_pipes(plp) != USB_SUCCESS) {
1070 		return (USB_FAILURE);
1071 	}
1072 
1073 	return (USB_SUCCESS);
1074 }
1075 
1076 
1077 /*
1078  * hotplug
1079  * -------
1080  *
1081  *
1082  * restore device state after CPR resume or reconnect
1083  */
1084 static int
1085 pl2303_restore_device_state(pl2303_state_t *plp)
1086 {
1087 	int	state;
1088 
1089 	mutex_enter(&plp->pl_mutex);
1090 	state = plp->pl_dev_state;
1091 	mutex_exit(&plp->pl_mutex);
1092 
1093 	if ((state != USB_DEV_DISCONNECTED) && (state != USB_DEV_SUSPENDED)) {
1094 
1095 		return (state);
1096 	}
1097 
1098 	if (usb_check_same_device(plp->pl_dip, plp->pl_lh, USB_LOG_L0,
1099 	    DPRINT_MASK_ALL, USB_CHK_ALL, NULL) != USB_SUCCESS) {
1100 		mutex_enter(&plp->pl_mutex);
1101 		state = plp->pl_dev_state = USB_DEV_DISCONNECTED;
1102 		mutex_exit(&plp->pl_mutex);
1103 
1104 		return (state);
1105 	}
1106 
1107 	if (state == USB_DEV_DISCONNECTED) {
1108 		USB_DPRINTF_L0(DPRINT_HOTPLUG, plp->pl_lh,
1109 		    "Device has been reconnected but data may have been lost");
1110 	}
1111 
1112 	if (pl2303_reconnect_pipes(plp) != USB_SUCCESS) {
1113 
1114 		return (state);
1115 	}
1116 
1117 	/*
1118 	 * init device state
1119 	 */
1120 	mutex_enter(&plp->pl_mutex);
1121 	state = plp->pl_dev_state = USB_DEV_ONLINE;
1122 	mutex_exit(&plp->pl_mutex);
1123 
1124 	if ((pl2303_restore_port_state(plp) != USB_SUCCESS)) {
1125 		USB_DPRINTF_L2(DPRINT_HOTPLUG, plp->pl_lh,
1126 		    "pl2303_restore_device_state: failed");
1127 	}
1128 
1129 	return (state);
1130 }
1131 
1132 
1133 /*
1134  * restore ports state after CPR resume or reconnect
1135  */
1136 static int
1137 pl2303_restore_port_state(pl2303_state_t *plp)
1138 {
1139 	int		rval;
1140 
1141 	mutex_enter(&plp->pl_mutex);
1142 	if (plp->pl_port_state != PL2303_PORT_OPEN) {
1143 		mutex_exit(&plp->pl_mutex);
1144 
1145 		return (USB_SUCCESS);
1146 	}
1147 	mutex_exit(&plp->pl_mutex);
1148 
1149 	/* open hardware serial port */
1150 	if ((rval = pl2303_open_hw_port(plp)) != USB_SUCCESS) {
1151 		USB_DPRINTF_L2(DPRINT_HOTPLUG, plp->pl_lh,
1152 		    "pl2303_restore_ports_state: failed");
1153 	}
1154 
1155 	return (rval);
1156 }
1157 
1158 
1159 /*
1160  * power management
1161  * ----------------
1162  *
1163  *
1164  * create PM components
1165  */
1166 static int
1167 pl2303_create_pm_components(pl2303_state_t *plp)
1168 {
1169 	dev_info_t	*dip = plp->pl_dip;
1170 	pl2303_pm_t	*pm;
1171 	uint_t		pwr_states;
1172 
1173 	if (usb_create_pm_components(dip, &pwr_states) != USB_SUCCESS) {
1174 		USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh,
1175 		    "pl2303_create_pm_components: failed");
1176 
1177 		return (USB_SUCCESS);
1178 	}
1179 
1180 	pm = plp->pl_pm = kmem_zalloc(sizeof (pl2303_pm_t), KM_SLEEP);
1181 
1182 	pm->pm_pwr_states = (uint8_t)pwr_states;
1183 	pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
1184 	pm->pm_wakeup_enabled = (usb_handle_remote_wakeup(dip,
1185 				USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS);
1186 
1187 	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1188 
1189 	return (USB_SUCCESS);
1190 }
1191 
1192 
1193 /*
1194  * destroy PM components
1195  */
1196 static void
1197 pl2303_destroy_pm_components(pl2303_state_t *plp)
1198 {
1199 	pl2303_pm_t	*pm = plp->pl_pm;
1200 	dev_info_t	*dip = plp->pl_dip;
1201 	int		rval;
1202 
1203 	if (!pm)
1204 
1205 		return;
1206 
1207 	if (plp->pl_dev_state != USB_DEV_DISCONNECTED) {
1208 		if (pm->pm_wakeup_enabled) {
1209 			rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1210 			if (rval != DDI_SUCCESS) {
1211 				USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh,
1212 				    "pl2303_destroy_pm_components:"
1213 				    "raising power failed, rval=%d", rval);
1214 			}
1215 
1216 			rval = usb_handle_remote_wakeup(dip,
1217 						USB_REMOTE_WAKEUP_DISABLE);
1218 			if (rval != USB_SUCCESS) {
1219 				USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh,
1220 				    "pl2303_destroy_pm_components: disable "
1221 				    "remote wakeup failed, rval=%d", rval);
1222 			}
1223 		}
1224 
1225 		(void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
1226 	}
1227 	kmem_free(pm, sizeof (pl2303_pm_t));
1228 	plp->pl_pm = NULL;
1229 }
1230 
1231 
1232 /*
1233  * mark device busy and raise power
1234  */
1235 static int
1236 pl2303_pm_set_busy(pl2303_state_t *plp)
1237 {
1238 	pl2303_pm_t	*pm = plp->pl_pm;
1239 	dev_info_t	*dip = plp->pl_dip;
1240 	int		rval;
1241 
1242 	USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pm_set_busy");
1243 
1244 	if (!pm) {
1245 
1246 		return (USB_SUCCESS);
1247 	}
1248 
1249 	mutex_enter(&plp->pl_mutex);
1250 	/* if already marked busy, just increment the counter */
1251 	if (pm->pm_busy_cnt++ > 0) {
1252 		mutex_exit(&plp->pl_mutex);
1253 
1254 		return (USB_SUCCESS);
1255 	}
1256 
1257 	rval = pm_busy_component(dip, 0);
1258 	ASSERT(rval == DDI_SUCCESS);
1259 
1260 	if (pm->pm_cur_power == USB_DEV_OS_FULL_PWR) {
1261 		mutex_exit(&plp->pl_mutex);
1262 
1263 		return (USB_SUCCESS);
1264 	}
1265 
1266 	/* need to raise power	*/
1267 	pm->pm_raise_power = B_TRUE;
1268 	mutex_exit(&plp->pl_mutex);
1269 
1270 	rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1271 	if (rval != DDI_SUCCESS) {
1272 		USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh, "raising power failed");
1273 	}
1274 
1275 	mutex_enter(&plp->pl_mutex);
1276 	pm->pm_raise_power = B_FALSE;
1277 	mutex_exit(&plp->pl_mutex);
1278 
1279 	return (USB_SUCCESS);
1280 }
1281 
1282 
1283 /*
1284  * mark device idle
1285  */
1286 static void
1287 pl2303_pm_set_idle(pl2303_state_t *plp)
1288 {
1289 	pl2303_pm_t	*pm = plp->pl_pm;
1290 	dev_info_t	*dip = plp->pl_dip;
1291 
1292 	USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pm_set_idle");
1293 
1294 	if (!pm) {
1295 
1296 		return;
1297 	}
1298 
1299 	/*
1300 	 * if more ports use the device, do not mark as yet
1301 	 */
1302 	mutex_enter(&plp->pl_mutex);
1303 	if (--pm->pm_busy_cnt > 0) {
1304 		mutex_exit(&plp->pl_mutex);
1305 
1306 		return;
1307 	}
1308 
1309 	if (pm) {
1310 		(void) pm_idle_component(dip, 0);
1311 	}
1312 	mutex_exit(&plp->pl_mutex);
1313 }
1314 
1315 
1316 /*
1317  * Functions to handle power transition for OS levels 0 -> 3
1318  * The same level as OS state, different from USB state
1319  */
1320 static int
1321 pl2303_pwrlvl0(pl2303_state_t *plp)
1322 {
1323 	int	rval;
1324 
1325 	USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pwrlvl0");
1326 
1327 	switch (plp->pl_dev_state) {
1328 	case USB_DEV_ONLINE:
1329 		/* issue USB D3 command to the device */
1330 		rval = usb_set_device_pwrlvl3(plp->pl_dip);
1331 		ASSERT(rval == USB_SUCCESS);
1332 
1333 		plp->pl_dev_state = USB_DEV_PWRED_DOWN;
1334 		plp->pl_pm->pm_cur_power = USB_DEV_OS_PWR_OFF;
1335 
1336 		/* FALLTHRU */
1337 	case USB_DEV_DISCONNECTED:
1338 	case USB_DEV_SUSPENDED:
1339 		/* allow a disconnect/cpr'ed device to go to lower power */
1340 
1341 		return (USB_SUCCESS);
1342 	case USB_DEV_PWRED_DOWN:
1343 	default:
1344 		USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh,
1345 		    "pl2303_pwrlvl0: illegal device state");
1346 
1347 		return (USB_FAILURE);
1348 	}
1349 }
1350 
1351 
1352 static int
1353 pl2303_pwrlvl1(pl2303_state_t *plp)
1354 {
1355 	USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pwrlvl1");
1356 
1357 	/* issue USB D2 command to the device */
1358 	(void) usb_set_device_pwrlvl2(plp->pl_dip);
1359 
1360 	return (USB_FAILURE);
1361 }
1362 
1363 
1364 static int
1365 pl2303_pwrlvl2(pl2303_state_t *plp)
1366 {
1367 	USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pwrlvl2");
1368 
1369 	/* issue USB D1 command to the device */
1370 	(void) usb_set_device_pwrlvl1(plp->pl_dip);
1371 
1372 	return (USB_FAILURE);
1373 }
1374 
1375 
1376 static int
1377 pl2303_pwrlvl3(pl2303_state_t *plp)
1378 {
1379 	int	rval;
1380 
1381 	USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pwrlvl3");
1382 
1383 	switch (plp->pl_dev_state) {
1384 	case USB_DEV_PWRED_DOWN:
1385 		/* Issue USB D0 command to the device here */
1386 		rval = usb_set_device_pwrlvl0(plp->pl_dip);
1387 		ASSERT(rval == USB_SUCCESS);
1388 
1389 		plp->pl_dev_state = USB_DEV_ONLINE;
1390 		plp->pl_pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
1391 
1392 		/* FALLTHRU */
1393 	case USB_DEV_ONLINE:
1394 		/* we are already in full power */
1395 
1396 		/* FALLTHRU */
1397 	case USB_DEV_DISCONNECTED:
1398 	case USB_DEV_SUSPENDED:
1399 
1400 		return (USB_SUCCESS);
1401 	default:
1402 		USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh,
1403 		    "pl2303_pwrlvl3: illegal device state");
1404 
1405 		return (USB_FAILURE);
1406 	}
1407 }
1408 
1409 
1410 /*
1411  * pipe operations
1412  * ---------------
1413  *
1414  *
1415  */
1416 static int
1417 pl2303_open_pipes(pl2303_state_t *plp)
1418 {
1419 	int		ifc, alt;
1420 	usb_pipe_policy_t policy;
1421 	usb_ep_data_t	*in_data, *out_data;
1422 
1423 	/* get ep data */
1424 	ifc = plp->pl_dev_data->dev_curr_if;
1425 	alt = 0;
1426 
1427 	in_data = usb_lookup_ep_data(plp->pl_dip, plp->pl_dev_data, ifc, alt,
1428 	    0, USB_EP_ATTR_BULK, USB_EP_DIR_IN);
1429 
1430 	out_data = usb_lookup_ep_data(plp->pl_dip, plp->pl_dev_data, ifc, alt,
1431 	    0, USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
1432 
1433 	if ((in_data == NULL) || (out_data == NULL)) {
1434 		USB_DPRINTF_L2(DPRINT_ATTACH, plp->pl_lh,
1435 		    "pl2303_open_pipes: can't get ep data");
1436 
1437 		return (USB_FAILURE);
1438 	}
1439 
1440 	/* open pipes */
1441 	policy.pp_max_async_reqs = 2;
1442 
1443 	if (usb_pipe_open(plp->pl_dip, &in_data->ep_descr, &policy,
1444 	    USB_FLAGS_SLEEP, &plp->pl_bulkin_ph) != USB_SUCCESS) {
1445 
1446 		return (USB_FAILURE);
1447 	}
1448 
1449 	if (usb_pipe_open(plp->pl_dip, &out_data->ep_descr, &policy,
1450 	    USB_FLAGS_SLEEP, &plp->pl_bulkout_ph) != USB_SUCCESS) {
1451 		usb_pipe_close(plp->pl_dip, plp->pl_bulkin_ph, USB_FLAGS_SLEEP,
1452 		    NULL, NULL);
1453 
1454 		return (USB_FAILURE);
1455 	}
1456 
1457 	mutex_enter(&plp->pl_mutex);
1458 	plp->pl_bulkin_state = PL2303_PIPE_IDLE;
1459 	plp->pl_bulkout_state = PL2303_PIPE_IDLE;
1460 	mutex_exit(&plp->pl_mutex);
1461 
1462 	return (USB_SUCCESS);
1463 }
1464 
1465 
1466 static void
1467 pl2303_close_pipes(pl2303_state_t *plp)
1468 {
1469 	if (plp->pl_bulkin_ph) {
1470 		usb_pipe_close(plp->pl_dip, plp->pl_bulkin_ph,
1471 		    USB_FLAGS_SLEEP, 0, 0);
1472 	}
1473 	if (plp->pl_bulkout_ph) {
1474 		usb_pipe_close(plp->pl_dip, plp->pl_bulkout_ph,
1475 		    USB_FLAGS_SLEEP, 0, 0);
1476 	}
1477 
1478 	mutex_enter(&plp->pl_mutex);
1479 	plp->pl_bulkin_state = PL2303_PIPE_CLOSED;
1480 	plp->pl_bulkout_state = PL2303_PIPE_CLOSED;
1481 	mutex_exit(&plp->pl_mutex);
1482 }
1483 
1484 
1485 static void
1486 pl2303_disconnect_pipes(pl2303_state_t *plp)
1487 {
1488 	pl2303_close_pipes(plp);
1489 }
1490 
1491 
1492 static int
1493 pl2303_reconnect_pipes(pl2303_state_t *plp)
1494 {
1495 	if ((pl2303_open_pipes(plp) != USB_SUCCESS)) {
1496 
1497 		return (USB_FAILURE);
1498 	}
1499 
1500 	return (USB_SUCCESS);
1501 }
1502 
1503 
1504 /*
1505  * pipe callbacks
1506  * --------------
1507  *
1508  *
1509  * bulk in common and exeception callback
1510  *
1511  */
1512 /*ARGSUSED*/
1513 void
1514 pl2303_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
1515 {
1516 	pl2303_state_t	*plp = (pl2303_state_t *)req->bulk_client_private;
1517 	mblk_t		*data;
1518 	int		data_len;
1519 
1520 	data = req->bulk_data;
1521 	data_len = (data) ? MBLKL(data) : 0;
1522 
1523 	USB_DPRINTF_L4(DPRINT_IN_PIPE, plp->pl_lh, "pl2303_bulkin_cb: "
1524 	    "cr=%d len=%d",
1525 	    req->bulk_completion_reason,
1526 	    data_len);
1527 
1528 	/* save data and notify GSD */
1529 	if ((plp->pl_port_state == PL2303_PORT_OPEN) && (data_len) &&
1530 			(req->bulk_completion_reason == USB_CR_OK)) {
1531 		req->bulk_data = NULL;
1532 		pl2303_put_tail(&plp->pl_rx_mp, data);
1533 		if (plp->pl_cb.cb_rx) {
1534 			plp->pl_cb.cb_rx(plp->pl_cb.cb_arg);
1535 		}
1536 	}
1537 
1538 	usb_free_bulk_req(req);
1539 
1540 	/* receive more */
1541 	mutex_enter(&plp->pl_mutex);
1542 	plp->pl_bulkin_state = PL2303_PIPE_IDLE;
1543 	if ((plp->pl_port_state == PL2303_PORT_OPEN) &&
1544 	    (plp->pl_dev_state == USB_DEV_ONLINE)) {
1545 		if (pl2303_rx_start(plp) != USB_SUCCESS) {
1546 			USB_DPRINTF_L2(DPRINT_IN_PIPE, plp->pl_lh,
1547 			    "pl2303_bulkin_cb: restart rx fail");
1548 		}
1549 	}
1550 	mutex_exit(&plp->pl_mutex);
1551 }
1552 
1553 
1554 /*
1555  * bulk out common and exeception callback
1556  */
1557 /*ARGSUSED*/
1558 void
1559 pl2303_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
1560 {
1561 	pl2303_state_t	*plp = (pl2303_state_t *)req->bulk_client_private;
1562 	int		data_len;
1563 	mblk_t		*data = req->bulk_data;
1564 
1565 	data_len = (req->bulk_data) ? MBLKL(req->bulk_data) : 0;
1566 
1567 	USB_DPRINTF_L4(DPRINT_OUT_PIPE, plp->pl_lh,
1568 	    "pl2303_bulkout_cb: cr=%d len=%d",
1569 	    req->bulk_completion_reason,
1570 	    data_len);
1571 
1572 	if (req->bulk_completion_reason && (data_len > 0)) {
1573 		pl2303_put_head(&plp->pl_tx_mp, data);
1574 		req->bulk_data = NULL;
1575 	}
1576 
1577 	usb_free_bulk_req(req);
1578 
1579 	/* notify GSD */
1580 	if (plp->pl_cb.cb_tx) {
1581 		plp->pl_cb.cb_tx(plp->pl_cb.cb_arg);
1582 	}
1583 
1584 	/* send more */
1585 	mutex_enter(&plp->pl_mutex);
1586 	plp->pl_bulkout_state = PL2303_PIPE_IDLE;
1587 	if (plp->pl_tx_mp == NULL) {
1588 		cv_broadcast(&plp->pl_tx_cv);
1589 	} else {
1590 		pl2303_tx_start(plp, NULL);
1591 	}
1592 	mutex_exit(&plp->pl_mutex);
1593 }
1594 
1595 
1596 /*
1597  * data transfer routines
1598  * ----------------------
1599  *
1600  *
1601  * start data receipt
1602  */
1603 static int
1604 pl2303_rx_start(pl2303_state_t *plp)
1605 {
1606 	usb_bulk_req_t	*br;
1607 	int		rval = USB_FAILURE;
1608 
1609 	USB_DPRINTF_L4(DPRINT_OUT_PIPE, plp->pl_lh, "pl2303_rx_start");
1610 
1611 	ASSERT(mutex_owned(&plp->pl_mutex));
1612 
1613 	plp->pl_bulkin_state = PL2303_PIPE_BUSY;
1614 	mutex_exit(&plp->pl_mutex);
1615 
1616 	br = usb_alloc_bulk_req(plp->pl_dip, plp->pl_xfer_sz, USB_FLAGS_SLEEP);
1617 	br->bulk_len = plp->pl_xfer_sz;
1618 	br->bulk_timeout = PL2303_BULKIN_TIMEOUT;
1619 	br->bulk_cb = pl2303_bulkin_cb;
1620 	br->bulk_exc_cb = pl2303_bulkin_cb;
1621 	br->bulk_client_private = (usb_opaque_t)plp;
1622 	br->bulk_attributes = USB_ATTRS_AUTOCLEARING | USB_ATTRS_SHORT_XFER_OK;
1623 
1624 	rval = usb_pipe_bulk_xfer(plp->pl_bulkin_ph, br, 0);
1625 
1626 	if (rval != USB_SUCCESS) {
1627 		USB_DPRINTF_L2(DPRINT_IN_PIPE, plp->pl_lh,
1628 		    "pl2303_rx_start: xfer failed %d", rval);
1629 		usb_free_bulk_req(br);
1630 	}
1631 
1632 	mutex_enter(&plp->pl_mutex);
1633 	if (rval != USB_SUCCESS) {
1634 		plp->pl_bulkin_state = PL2303_PIPE_IDLE;
1635 	}
1636 
1637 	return (rval);
1638 }
1639 
1640 
1641 /*
1642  * start data transmit
1643  */
1644 static void
1645 pl2303_tx_start(pl2303_state_t *plp, int *xferd)
1646 {
1647 	int		len;		/* bytes we can transmit */
1648 	mblk_t		*data;		/* data to be transmitted */
1649 	int		data_len;	/* bytes in 'data' */
1650 	mblk_t		*mp;		/* current msgblk */
1651 	int		copylen;	/* bytes copy from 'mp' to 'data' */
1652 	int		rval;
1653 
1654 	USB_DPRINTF_L4(DPRINT_OUT_PIPE, plp->pl_lh, "pl2303_tx_start");
1655 	ASSERT(mutex_owned(&plp->pl_mutex));
1656 	ASSERT(plp->pl_port_state != PL2303_PORT_CLOSED);
1657 
1658 	if (xferd) {
1659 		*xferd = 0;
1660 	}
1661 	if ((plp->pl_port_flags & PL2303_PORT_TX_STOPPED) ||
1662 	    (plp->pl_tx_mp == NULL)) {
1663 
1664 		return;
1665 	}
1666 	if (plp->pl_bulkout_state != PL2303_PIPE_IDLE) {
1667 		USB_DPRINTF_L4(DPRINT_OUT_PIPE, plp->pl_lh,
1668 		    "pl2303_tx_start: pipe busy");
1669 
1670 		return;
1671 	}
1672 	ASSERT(MBLKL(plp->pl_tx_mp) > 0);
1673 
1674 	/* send as much data as port can receive */
1675 	len = min(msgdsize(plp->pl_tx_mp), plp->pl_xfer_sz);
1676 
1677 	if (len == 0) {
1678 
1679 		return;
1680 	}
1681 
1682 	if ((data = allocb(len, BPRI_LO)) == NULL) {
1683 
1684 		return;
1685 	}
1686 
1687 	/*
1688 	 * copy no more than 'len' bytes from mblk chain to transmit mblk 'data'
1689 	 */
1690 	data_len = 0;
1691 
1692 	while ((data_len < len) && plp->pl_tx_mp) {
1693 		mp = plp->pl_tx_mp;
1694 		copylen = min(MBLKL(mp), len - data_len);
1695 		bcopy(mp->b_rptr, data->b_wptr, copylen);
1696 		mp->b_rptr += copylen;
1697 		data->b_wptr += copylen;
1698 		data_len += copylen;
1699 
1700 		if (MBLKL(mp) <= 0) {
1701 			plp->pl_tx_mp = unlinkb(mp);
1702 			freeb(mp);
1703 		} else {
1704 			ASSERT(data_len == len);
1705 		}
1706 	}
1707 
1708 	if (data_len <= 0) {
1709 		USB_DPRINTF_L3(DPRINT_OUT_PIPE, plp->pl_lh,
1710 		    "pl2303_tx_start: copied zero bytes");
1711 		freeb(data);
1712 
1713 		return;
1714 	}
1715 
1716 	plp->pl_bulkout_state = PL2303_PIPE_BUSY;
1717 	mutex_exit(&plp->pl_mutex);
1718 
1719 	rval = pl2303_send_data(plp, data);
1720 	mutex_enter(&plp->pl_mutex);
1721 
1722 	if (rval != USB_SUCCESS) {
1723 		plp->pl_bulkout_state = PL2303_PIPE_IDLE;
1724 		if (plp->pl_tx_mp == NULL) {
1725 			plp->pl_tx_mp = data;
1726 		}
1727 
1728 	} else {
1729 		if (xferd) {
1730 			*xferd = data_len;
1731 		}
1732 	}
1733 }
1734 
1735 
1736 static int
1737 pl2303_send_data(pl2303_state_t *plp, mblk_t *data)
1738 {
1739 	usb_bulk_req_t	*br;
1740 	int		len = MBLKL(data);
1741 	int		rval;
1742 
1743 	USB_DPRINTF_L4(DPRINT_OUT_PIPE, plp->pl_lh, "pl2303_send_data: %d "
1744 	    "%x %x %x", len, data->b_rptr[0],
1745 	    (len > 1) ? data->b_rptr[1] : 0,
1746 	    (len > 2) ? data->b_rptr[2] : 0);
1747 	ASSERT(!mutex_owned(&plp->pl_mutex));
1748 
1749 	br = usb_alloc_bulk_req(plp->pl_dip, 0, USB_FLAGS_SLEEP);
1750 	br->bulk_data = data;
1751 	br->bulk_len = len;
1752 	br->bulk_timeout = PL2303_BULKOUT_TIMEOUT;
1753 	br->bulk_cb = pl2303_bulkout_cb;
1754 	br->bulk_exc_cb = pl2303_bulkout_cb;
1755 	br->bulk_client_private = (usb_opaque_t)plp;
1756 	br->bulk_attributes = USB_ATTRS_AUTOCLEARING;
1757 
1758 	rval = usb_pipe_bulk_xfer(plp->pl_bulkout_ph, br, 0);
1759 
1760 	if (rval != USB_SUCCESS) {
1761 		USB_DPRINTF_L2(DPRINT_OUT_PIPE, plp->pl_lh,
1762 		    "pl2303_send_data: xfer failed %d", rval);
1763 		usb_free_bulk_req(br);
1764 	}
1765 
1766 	return (rval);
1767 }
1768 
1769 
1770 /*
1771  * wait until local tx buffer drains.
1772  * 'timeout' is in seconds, zero means wait forever
1773  */
1774 static int
1775 pl2303_wait_tx_drain(pl2303_state_t *plp, int timeout)
1776 {
1777 	clock_t	until;
1778 	int	over = 0;
1779 
1780 	until = ddi_get_lbolt() + drv_usectohz(1000 * 1000 * timeout);
1781 
1782 	while (plp->pl_tx_mp && !over) {
1783 		if (timeout > 0) {
1784 			/* whether timedout or signal pending */
1785 			over = (cv_timedwait_sig(&plp->pl_tx_cv,
1786 					&plp->pl_mutex, until) <= 0);
1787 		} else {
1788 			/* whether a signal is pending */
1789 			over = (cv_wait_sig(&plp->pl_tx_cv,
1790 					&plp->pl_mutex) == 0);
1791 		}
1792 	}
1793 
1794 	return ((plp->pl_tx_mp == NULL) ? USB_SUCCESS : USB_FAILURE);
1795 }
1796 
1797 
1798 /*
1799  * device operations
1800  * -----------------
1801  *
1802  *
1803  * initialize hardware serial port
1804  */
1805 static int
1806 pl2303_open_hw_port(pl2303_state_t *plp)
1807 {
1808 	int		rval = USB_SUCCESS;
1809 
1810 	/*
1811 	 * initialize three Device Configuration Registers (DCR):
1812 	 * DCR0, DCR1, and DCR2
1813 	 */
1814 
1815 	switch (plp->pl_chiptype) {
1816 	case (pl2303_H):
1817 		/* Set DCR0 */
1818 		if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR0,
1819 					DCR0_INIT_H)) != USB_SUCCESS) {
1820 
1821 			return (rval);
1822 		}
1823 
1824 		/* Set DCR1 */
1825 		if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR1,
1826 					DCR1_INIT_H)) != USB_SUCCESS) {
1827 
1828 			return (rval);
1829 		}
1830 
1831 		/* Set DCR2 */
1832 		if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR2,
1833 					DCR2_INIT_H)) != USB_SUCCESS) {
1834 
1835 			return (rval);
1836 		}
1837 
1838 		break;
1839 	case (pl2303_X):
1840 
1841 		/* Set DCR0 */
1842 		if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR0,
1843 					DCR0_INIT)) != USB_SUCCESS) {
1844 
1845 			return (rval);
1846 		}
1847 
1848 		/* Set DCR1 */
1849 		if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR1,
1850 					DCR1_INIT_X)) != USB_SUCCESS) {
1851 
1852 			return (rval);
1853 		}
1854 
1855 		/* Set DCR2 */
1856 		if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR2,
1857 					DCR2_INIT_X)) != USB_SUCCESS) {
1858 
1859 			return (rval);
1860 		}
1861 
1862 		/* reset Downstream data pipes */
1863 		if ((rval = pl2303_cmd_vendor_write0(plp,
1864 			RESET_DOWNSTREAM_DATA_PIPE, 0)) != USB_SUCCESS) {
1865 
1866 			return (rval);
1867 		}
1868 
1869 		/* reset Upstream data pipes */
1870 		if ((rval = pl2303_cmd_vendor_write0(plp,
1871 				RESET_UPSTREAM_DATA_PIPE, 0)) != USB_SUCCESS) {
1872 
1873 			return (rval);
1874 		}
1875 
1876 		break;
1877 	case (pl2303_UNKNOWN):
1878 	default:
1879 		USB_DPRINTF_L2(DPRINT_OPEN, plp->pl_lh,
1880 			"pl2303_open_hw_port: unknown chiptype");
1881 
1882 		rval = USB_FAILURE;
1883 	}
1884 
1885 	return (rval);
1886 }
1887 
1888 
1889 /*
1890  * vendor-specific commands
1891  * ------------------------
1892  *
1893  *
1894  * Get_Line_Coding Request
1895  */
1896 static int
1897 pl2303_cmd_get_line(pl2303_state_t *plp, mblk_t **data)
1898 {
1899 	usb_ctrl_setup_t setup = { PL2303_GET_LINE_CODING_REQUEST_TYPE,
1900 			PL2303_GET_LINE_CODING_REQUEST, 0, 0,
1901 			PL2303_GET_LINE_CODING_LENGTH, 0 };
1902 	usb_cb_flags_t	cb_flags;
1903 	usb_cr_t	cr;
1904 	int		rval;
1905 
1906 	*data = NULL;
1907 
1908 	rval = usb_pipe_ctrl_xfer_wait(plp->pl_def_ph, &setup, data,
1909 		&cr, &cb_flags, 0);
1910 
1911 	if ((rval == USB_SUCCESS) && (*data != NULL)) {
1912 		USB_DPRINTF_L4(DPRINT_DEF_PIPE, plp->pl_lh,
1913 		    "pl2303_cmd_get_line: %x %x %x %x %x %x %x",
1914 		    (*data)->b_rptr[0], (*data)->b_rptr[1], (*data)->b_rptr[2],
1915 		    (*data)->b_rptr[3], (*data)->b_rptr[4], (*data)->b_rptr[5],
1916 		    (*data)->b_rptr[6]);
1917 	} else {
1918 		USB_DPRINTF_L2(DPRINT_DEF_PIPE, plp->pl_lh,
1919 		    "pl2303_cmd_get_line: failed %d %d %x",
1920 		    rval, cr, cb_flags);
1921 	}
1922 
1923 	return (rval);
1924 }
1925 
1926 
1927 /*
1928  * Set_Line_Coding Request
1929  */
1930 static int
1931 pl2303_cmd_set_line(pl2303_state_t *plp, mblk_t *data)
1932 {
1933 	usb_ctrl_setup_t setup = { PL2303_SET_LINE_CODING_REQUEST_TYPE,
1934 			PL2303_SET_LINE_CODING_REQUEST, 0, 0,
1935 			PL2303_SET_LINE_CODING_LENGTH, 0 };
1936 	usb_cb_flags_t	cb_flags;
1937 	usb_cr_t	cr;
1938 	int		rval;
1939 
1940 	USB_DPRINTF_L4(DPRINT_DEF_PIPE, plp->pl_lh,
1941 	    "pl2303_cmd_set_line: %x %x %x %x %x %x %x",
1942 	    data->b_rptr[0], data->b_rptr[1], data->b_rptr[2],
1943 	    data->b_rptr[3], data->b_rptr[4], data->b_rptr[5], data->b_rptr[6]);
1944 
1945 	rval = usb_pipe_ctrl_xfer_wait(plp->pl_def_ph, &setup, &data,
1946 		&cr, &cb_flags, 0);
1947 
1948 	if (rval != USB_SUCCESS) {
1949 		USB_DPRINTF_L2(DPRINT_DEF_PIPE, plp->pl_lh,
1950 		    "pl2303_cmd_set_line: failed %d %d %x",
1951 		    rval, cr, cb_flags);
1952 	}
1953 
1954 	return (rval);
1955 }
1956 
1957 
1958 /*
1959  * Set_Control_Line_State Request to RTS and DTR
1960  */
1961 static int
1962 pl2303_cmd_set_ctl(pl2303_state_t *plp, uint8_t val)
1963 {
1964 	usb_ctrl_setup_t setup = { PL2303_SET_CONTROL_REQUEST_TYPE,
1965 			PL2303_SET_CONTROL_REQUEST, 0, 0,
1966 			PL2303_SET_CONTROL_LENGTH, 0 };
1967 	usb_cb_flags_t	cb_flags;
1968 	usb_cr_t	cr;
1969 	int		rval;
1970 
1971 	setup.wValue = val;
1972 
1973 	rval = usb_pipe_ctrl_xfer_wait(plp->pl_def_ph, &setup, NULL,
1974 		&cr, &cb_flags, 0);
1975 
1976 	if (rval != USB_SUCCESS) {
1977 		USB_DPRINTF_L2(DPRINT_DEF_PIPE, plp->pl_lh,
1978 		    "pl2303_cmd_set_ctl: failed %d %d %x",
1979 		    rval, cr, cb_flags);
1980 	}
1981 
1982 	return (rval);
1983 }
1984 
1985 
1986 /*
1987  * Vendor_Specific_Write Request
1988  * wLength: 0
1989  */
1990 static int
1991 pl2303_cmd_vendor_write0(pl2303_state_t *plp, uint16_t value, int16_t index)
1992 {
1993 	usb_ctrl_setup_t setup = { PL2303_VENDOR_WRITE_REQUEST_TYPE,
1994 			PL2303_VENDOR_WRITE_REQUEST, 0, 0,
1995 			PL2303_VENDOR_WRITE_LENGTH, 0 };
1996 	usb_cb_flags_t	cb_flags;
1997 	usb_cr_t	cr;
1998 	int		rval;
1999 
2000 	setup.wValue = value;
2001 	setup.wIndex = index;
2002 
2003 	rval = usb_pipe_ctrl_xfer_wait(plp->pl_def_ph, &setup, NULL,
2004 		&cr, &cb_flags, 0);
2005 
2006 	if (rval != USB_SUCCESS) {
2007 		USB_DPRINTF_L2(DPRINT_DEF_PIPE, plp->pl_lh,
2008 		    "pl2303_cmd_vendor_write0: %x %x failed %d %d %x",
2009 		    value, index, rval, cr, cb_flags);
2010 	}
2011 
2012 	return (rval);
2013 }
2014 
2015 
2016 /*
2017  * For Hardware flow control
2018  */
2019 static int
2020 pl2303_cmd_set_rtscts(pl2303_state_t *plp)
2021 {
2022 	/* Set DCR0 */
2023 	switch (plp->pl_chiptype) {
2024 	case pl2303_H:
2025 
2026 		return (pl2303_cmd_vendor_write0(plp, SET_DCR0, DCR0_INIT_H));
2027 	case pl2303_X:
2028 
2029 		return (pl2303_cmd_vendor_write0(plp, SET_DCR0, DCR0_INIT_X));
2030 	case pl2303_UNKNOWN:
2031 	default:
2032 
2033 		return (USB_FAILURE);
2034 	}
2035 }
2036 
2037 
2038 /*
2039  * Set TxD BREAK_ON or BREAK_OFF
2040  */
2041 static int
2042 pl2303_cmd_break(pl2303_state_t *plp, int ctl)
2043 {
2044 	usb_ctrl_setup_t setup = { PL2303_BREAK_REQUEST_TYPE,
2045 			PL2303_BREAK_REQUEST, 0, 0,
2046 			PL2303_BREAK_LENGTH, 0 };
2047 	usb_cb_flags_t	cb_flags;
2048 	usb_cr_t	cr;
2049 	int		rval;
2050 
2051 	setup.wValue = (ctl == DS_ON) ? PL2303_BREAK_ON : PL2303_BREAK_OFF;
2052 
2053 	rval = usb_pipe_ctrl_xfer_wait(plp->pl_def_ph, &setup, NULL,
2054 		&cr, &cb_flags, 0);
2055 
2056 	if (rval != USB_SUCCESS) {
2057 		USB_DPRINTF_L2(DPRINT_DEF_PIPE, plp->pl_lh,
2058 			"pl2303_cmd_break: failed rval=%d,cr=%d,cb_flags=0x%x",
2059 			rval, cr, cb_flags);
2060 	}
2061 
2062 	return (rval);
2063 }
2064 
2065 
2066 /*
2067  * for set_mod_ctl
2068  */
2069 static void
2070 pl2303_mctl2reg(int mask, int val, uint8_t *line_ctl)
2071 {
2072 	if (mask & TIOCM_RTS) {
2073 		if (val & TIOCM_RTS) {
2074 			*line_ctl |= PL2303_CONTROL_RTS;
2075 		} else {
2076 			*line_ctl &= ~PL2303_CONTROL_RTS;
2077 		}
2078 	}
2079 	if (mask & TIOCM_DTR) {
2080 		if (val & TIOCM_DTR) {
2081 			*line_ctl |= PL2303_CONTROL_DTR;
2082 		} else {
2083 			*line_ctl &= ~PL2303_CONTROL_DTR;
2084 		}
2085 	}
2086 }
2087 
2088 
2089 /*
2090  * for get_mod_ctl
2091  */
2092 static int
2093 pl2303_reg2mctl(uint8_t line_ctl)
2094 {
2095 	int	val = 0;
2096 
2097 	if (line_ctl & PL2303_CONTROL_RTS) {
2098 		val |= TIOCM_RTS;
2099 	}
2100 	if (line_ctl & PL2303_CONTROL_DTR) {
2101 		val |= TIOCM_DTR;
2102 	}
2103 
2104 	return (val);
2105 }
2106 
2107 
2108 /*
2109  * misc routines
2110  * -------------
2111  *
2112  */
2113 
2114 /*
2115  * link a message block to tail of message
2116  * account for the case when message is null
2117  */
2118 static void
2119 pl2303_put_tail(mblk_t **mpp, mblk_t *bp)
2120 {
2121 	if (*mpp) {
2122 		linkb(*mpp, bp);
2123 	} else {
2124 		*mpp = bp;
2125 	}
2126 }
2127 
2128 
2129 /*
2130  * put a message block at the head of the message
2131  * account for the case when message is null
2132  */
2133 static void
2134 pl2303_put_head(mblk_t **mpp, mblk_t *bp)
2135 {
2136 	if (*mpp) {
2137 		linkb(bp, *mpp);
2138 	}
2139 	*mpp = bp;
2140 }
2141