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