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