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