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