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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 * USB Prolific PL2303 device-specific driver (DSD)
32 #include <sys/types.h>
33 #include <sys/param.h>
35 #include <sys/stream.h>
36 #include <sys/strsun.h>
37 #include <sys/termio.h>
38 #include <sys/termiox.h>
40 #include <sys/sunddi.h>
42 #define USBDRV_MAJOR_VER 2
43 #define USBDRV_MINOR_VER 0
45 #include <sys/usb/usba.h>
46 #include <sys/usb/usba/usba_types.h>
47 #include <sys/usb/usba/usba_impl.h>
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>
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
);
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
);
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);
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);
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
);
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
*);
99 static int pl2303_restore_device_state(pl2303_state_t
*);
100 static int pl2303_restore_port_state(pl2303_state_t
*);
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
*);
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
*);
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
*);
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);
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);
139 static void pl2303_put_tail(mblk_t
**, mblk_t
*);
140 static void pl2303_put_head(mblk_t
**, mblk_t
*);
146 ds_ops_t pl2303_ds_ops
= {
151 pl2303_unregister_cb
,
159 pl2303_set_port_params
,
160 pl2303_set_modem_ctl
,
161 pl2303_get_modem_ctl
,
163 NULL
, /* HW don't support loopback */
176 * baud code into baud rate
177 * value 0 means not supported in hardware
180 static int pl2303_speedtab
[] = {
199 115200, /* B115200 */
201 230400, /* B230400 */
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;
217 pl2303_attach(ds_attach_info_t
*aip
)
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
;
227 *aip
->ai_port_cnt
= 1;
229 if (usb_client_attach(plp
->pl_dip
, USBDRV_VERSION
, 0) != USB_SUCCESS
) {
230 pl2303_cleanup(plp
, 1);
232 return (USB_FAILURE
);
235 if (usb_get_dev_data(plp
->pl_dip
, &plp
->pl_dev_data
, USB_PARSE_LVL_IF
,
237 pl2303_cleanup(plp
, 2);
239 return (USB_FAILURE
);
242 mutex_init(&plp
->pl_mutex
, NULL
, MUTEX_DRIVER
,
243 plp
->pl_dev_data
->dev_iblock_cookie
);
245 cv_init(&plp
->pl_tx_cv
, NULL
, CV_DRIVER
, NULL
);
247 plp
->pl_lh
= usb_alloc_log_hdl(plp
->pl_dip
, "pl2303",
248 &pl2303_errlevel
, &pl2303_errmask
, &pl2303_instance_debug
, 0);
251 * Check the chip type: pl2303_H, pl2303_X (or pl2303_HX(Chip A)),
253 * pl2303_UNKNOWN means not supported chip type.
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
) {
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.
267 * So "pl2303_X" will stand for both pl2303_HX(Chip A)and
268 * pl2303_X devices in this driver.
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");
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");
297 plp
->pl_def_ph
= plp
->pl_dev_data
->dev_default_ph
;
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
);
304 if (pl2303_create_pm_components(plp
) != USB_SUCCESS
) {
305 pl2303_cleanup(plp
, 3);
307 return (USB_FAILURE
);
310 if (usb_register_event_cbs(plp
->pl_dip
, plp
->pl_usb_events
, 0)
312 pl2303_cleanup(plp
, 4);
314 return (USB_FAILURE
);
317 if (usb_pipe_get_max_bulk_transfer_size(plp
->pl_dip
,
318 &plp
->pl_xfer_sz
) != USB_SUCCESS
) {
319 pl2303_cleanup(plp
, 5);
321 return (USB_FAILURE
);
324 if (plp
->pl_xfer_sz
> PL2303_XFER_SZ_MAX
) {
325 plp
->pl_xfer_sz
= PL2303_XFER_SZ_MAX
;
328 if (pl2303_dev_attach(plp
) != USB_SUCCESS
) {
329 pl2303_cleanup(plp
, 5);
331 return (USB_FAILURE
);
334 return (USB_SUCCESS
);
342 pl2303_detach(ds_hdl_t hdl
)
344 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
346 pl2303_cleanup(plp
, PL2303_CLEANUP_LEVEL_MAX
);
355 pl2303_register_cb(ds_hdl_t hdl
, uint_t port_num
, ds_cb_t
*cb
)
357 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
361 return (USB_SUCCESS
);
370 pl2303_unregister_cb(ds_hdl_t hdl
, uint_t port_num
)
372 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
374 bzero(&plp
->pl_cb
, sizeof (plp
->pl_cb
));
383 pl2303_open_port(ds_hdl_t hdl
, uint_t port_num
)
385 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
386 int rval
= USB_FAILURE
;
388 USB_DPRINTF_L4(DPRINT_OPEN
, plp
->pl_lh
, "pl2303_open_port");
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
);
398 mutex_exit(&plp
->pl_mutex
);
400 if ((rval
= pl2303_pm_set_busy(plp
)) != USB_SUCCESS
) {
405 /* initialize hardware serial port */
406 rval
= pl2303_open_hw_port(plp
);
408 if (rval
== USB_SUCCESS
) {
409 mutex_enter(&plp
->pl_mutex
);
411 /* start to receive data */
412 if (pl2303_rx_start(plp
) != USB_SUCCESS
) {
413 mutex_exit(&plp
->pl_mutex
);
415 return (USB_FAILURE
);
417 plp
->pl_port_state
= PL2303_PORT_OPEN
;
418 mutex_exit(&plp
->pl_mutex
);
420 pl2303_pm_set_idle(plp
);
432 pl2303_close_port(ds_hdl_t hdl
, uint_t port_num
)
434 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
436 USB_DPRINTF_L4(DPRINT_CLOSE
, plp
->pl_lh
, "pl2303_close_port");
438 mutex_enter(&plp
->pl_mutex
);
440 /* free resources and finalize state */
442 freemsg(plp
->pl_rx_mp
);
443 plp
->pl_rx_mp
= NULL
;
446 freemsg(plp
->pl_tx_mp
);
447 plp
->pl_tx_mp
= NULL
;
450 plp
->pl_port_state
= PL2303_PORT_CLOSED
;
451 mutex_exit(&plp
->pl_mutex
);
453 pl2303_pm_set_idle(plp
);
455 return (USB_SUCCESS
);
467 pl2303_usb_power(ds_hdl_t hdl
, int comp
, int level
, int *new_state
)
469 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
470 pl2303_pm_t
*pm
= plp
->pl_pm
;
473 USB_DPRINTF_L4(DPRINT_PM
, plp
->pl_lh
, "pl2303_usb_power");
477 return (USB_FAILURE
);
480 mutex_enter(&plp
->pl_mutex
);
482 * check if we are transitioning to a legal power level
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
);
490 return (USB_FAILURE
);
494 * if we are about to raise power and asked to lower power, fail
496 if (pm
->pm_raise_power
&& (level
< (int)pm
->pm_cur_power
)) {
497 mutex_exit(&plp
->pl_mutex
);
499 return (USB_FAILURE
);
503 case USB_DEV_OS_PWR_OFF
:
504 rval
= pl2303_pwrlvl0(plp
);
507 case USB_DEV_OS_PWR_1
:
508 rval
= pl2303_pwrlvl1(plp
);
511 case USB_DEV_OS_PWR_2
:
512 rval
= pl2303_pwrlvl2(plp
);
515 case USB_DEV_OS_FULL_PWR
:
516 rval
= pl2303_pwrlvl3(plp
);
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.
525 if ((rval
== USB_SUCCESS
) &&
526 ((*new_state
== USB_DEV_DISCONNECTED
) ||
527 (*new_state
== USB_DEV_SUSPENDED
))) {
528 plp
->pl_dev_state
= *new_state
;
533 ASSERT(0); /* cannot happen */
536 *new_state
= plp
->pl_dev_state
;
537 mutex_exit(&plp
->pl_mutex
);
547 pl2303_suspend(ds_hdl_t hdl
)
549 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
550 int state
= USB_DEV_SUSPENDED
;
552 USB_DPRINTF_L4(DPRINT_PM
, plp
->pl_lh
, "pl2303_suspend");
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
560 mutex_enter(&plp
->pl_mutex
);
561 if (plp
->pl_dev_state
!= USB_DEV_PWRED_DOWN
) {
562 plp
->pl_dev_state
= USB_DEV_SUSPENDED
;
564 mutex_exit(&plp
->pl_mutex
);
566 pl2303_disconnect_pipes(plp
);
576 pl2303_resume(ds_hdl_t hdl
)
578 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
582 USB_DPRINTF_L4(DPRINT_PM
, plp
->pl_lh
, "pl2303_resume");
584 mutex_enter(&plp
->pl_mutex
);
585 current_state
= plp
->pl_dev_state
;
586 mutex_exit(&plp
->pl_mutex
);
588 if (current_state
!= USB_DEV_ONLINE
) {
589 rval
= pl2303_restore_device_state(plp
);
602 pl2303_disconnect(ds_hdl_t hdl
)
604 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
605 int state
= USB_DEV_DISCONNECTED
;
607 USB_DPRINTF_L4(DPRINT_HOTPLUG
, plp
->pl_lh
, "pl2303_disconnect");
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.
615 mutex_enter(&plp
->pl_mutex
);
616 if (plp
->pl_dev_state
!= USB_DEV_PWRED_DOWN
) {
617 plp
->pl_dev_state
= USB_DEV_DISCONNECTED
;
619 mutex_exit(&plp
->pl_mutex
);
621 pl2303_disconnect_pipes(plp
);
631 pl2303_reconnect(ds_hdl_t hdl
)
633 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
635 USB_DPRINTF_L4(DPRINT_HOTPLUG
, plp
->pl_lh
, "pl2303_reconnect");
637 return (pl2303_restore_device_state(plp
));
642 * standard UART operations
643 * ------------------------
650 pl2303_set_port_params(ds_hdl_t hdl
, uint_t port_num
, ds_port_params_t
*tp
)
652 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
653 int rval
= USB_FAILURE
;
659 ds_port_param_entry_t
*pe
;
660 uint16_t xonxoff_symbol
;
672 USB_DPRINTF_L4(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_set_port_params");
675 * get Line Coding Structure Request
676 * including: baud rate, stop bit, parity type and data bit
678 if ((rval
= pl2303_cmd_get_line(plp
, &bp
)) != USB_SUCCESS
) {
683 /* translate parameters into device-specific bits */
684 for (i
= 0; i
< cnt
; i
++, pe
++) {
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
);
697 return (USB_FAILURE
);
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;
707 case DS_PARAM_PARITY
:
708 if (pe
->val
.ui
& PARENB
) {
709 if (pe
->val
.ui
& PARODD
) {
720 if (pe
->val
.ui
& CSTOPB
) {
727 case DS_PARAM_CHARSZ
:
728 switch (pe
->val
.ui
) {
749 case DS_PARAM_XON_XOFF
:
751 * Software flow control: XON/XOFF
752 * not supported by PL-2303H, HX chips
754 if (pe
->val
.ui
& IXON
|| pe
->val
.ui
& IXOFF
) {
755 /* not supported by PL-2303H chip */
756 switch (plp
->pl_chiptype
) {
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)
767 rval
= pl2303_cmd_vendor_write0(
771 if (rval
!= USB_SUCCESS
) {
772 USB_DPRINTF_L3(DPRINT_CTLOP
,
774 "pl2303_set_port_params: "
775 "set XonXoff failed");
787 case DS_PARAM_FLOW_CTL
:
788 /* Hardware flow control */
789 if (pe
->val
.ui
& CTSXON
) {
790 if ((rval
= pl2303_cmd_set_rtscts(plp
))
793 USB_DPRINTF_L3(DPRINT_CTLOP
,
795 "pl2303_set_port_params: "
796 "pl2303_cmd_set_rtscts failed");
802 USB_DPRINTF_L2(DPRINT_CTLOP
, plp
->pl_lh
,
803 "pl2303_set_port_params: bad param %d", pe
->param
);
809 /* set new values for Line Coding Structure */
810 rval
= pl2303_cmd_set_line(plp
, bp
);
814 if (rval
!= USB_SUCCESS
) {
819 /* hardware need to get Line Coding Structure again */
820 if ((rval
= pl2303_cmd_get_line(plp
, &bp
)) != USB_SUCCESS
) {
827 return (USB_SUCCESS
);
836 pl2303_set_modem_ctl(ds_hdl_t hdl
, uint_t port_num
, int mask
, int val
)
838 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
839 int rval
= USB_FAILURE
;
842 USB_DPRINTF_L4(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_set_modem_ctl");
844 mutex_enter(&plp
->pl_mutex
);
845 new_mctl
= plp
->pl_mctl
;
846 mutex_exit(&plp
->pl_mutex
);
848 /* set RTS and DTR */
849 pl2303_mctl2reg(mask
, val
, &new_mctl
);
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
);
866 pl2303_get_modem_ctl(ds_hdl_t hdl
, uint_t port_num
, int mask
, int *valp
)
868 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
870 USB_DPRINTF_L4(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_get_modem_ctl");
872 mutex_enter(&plp
->pl_mutex
);
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
);
879 return (USB_SUCCESS
);
888 pl2303_break_ctl(ds_hdl_t hdl
, uint_t port_num
, int ctl
)
890 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
892 USB_DPRINTF_L4(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_break_ctl");
894 return (pl2303_cmd_break(plp
, ctl
));
903 pl2303_tx(ds_hdl_t hdl
, uint_t port_num
, mblk_t
*mp
)
905 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
908 USB_DPRINTF_L4(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_tx");
914 USB_DPRINTF_L3(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_tx: mp=NULL");
916 return (USB_SUCCESS
);
919 USB_DPRINTF_L3(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_tx: len<=0");
922 return (USB_SUCCESS
);
925 mutex_enter(&plp
->pl_mutex
);
927 pl2303_put_tail(&plp
->pl_tx_mp
, mp
); /* add to the chain */
929 pl2303_tx_start(plp
, &xferd
);
931 mutex_exit(&plp
->pl_mutex
);
933 return (USB_SUCCESS
);
939 * the real data receiving is in pl2303_open_port
943 pl2303_rx(ds_hdl_t hdl
, uint_t port_num
)
945 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
948 USB_DPRINTF_L4(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_rx");
950 mutex_enter(&plp
->pl_mutex
);
952 plp
->pl_rx_mp
= NULL
;
953 mutex_exit(&plp
->pl_mutex
);
964 pl2303_stop(ds_hdl_t hdl
, uint_t port_num
, int dir
)
966 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
968 USB_DPRINTF_L4(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_stop");
971 mutex_enter(&plp
->pl_mutex
);
972 plp
->pl_port_flags
|= PL2303_PORT_TX_STOPPED
;
973 mutex_exit(&plp
->pl_mutex
);
983 pl2303_start(ds_hdl_t hdl
, uint_t port_num
, int dir
)
985 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
987 USB_DPRINTF_L4(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_start");
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
);
995 mutex_exit(&plp
->pl_mutex
);
1005 pl2303_fifo_flush(ds_hdl_t hdl
, uint_t port_num
, int dir
)
1007 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
1009 USB_DPRINTF_L4(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_fifo_flush: dir=%x",
1012 mutex_enter(&plp
->pl_mutex
);
1013 ASSERT(plp
->pl_port_state
== PL2303_PORT_OPEN
);
1015 if ((dir
& DS_TX
) && plp
->pl_tx_mp
) {
1016 freemsg(plp
->pl_tx_mp
);
1017 plp
->pl_tx_mp
= NULL
;
1019 if ((dir
& DS_RX
) && plp
->pl_rx_mp
) {
1020 freemsg(plp
->pl_rx_mp
);
1021 plp
->pl_rx_mp
= NULL
;
1023 mutex_exit(&plp
->pl_mutex
);
1025 return (USB_SUCCESS
);
1034 pl2303_fifo_drain(ds_hdl_t hdl
, uint_t port_num
, int timeout
)
1036 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
1037 int rval
= USB_SUCCESS
;
1039 USB_DPRINTF_L4(DPRINT_CTLOP
, plp
->pl_lh
, "pl2303_fifo_drain");
1041 mutex_enter(&plp
->pl_mutex
);
1042 ASSERT(plp
->pl_port_state
== PL2303_PORT_OPEN
);
1045 * for the reason of hardware, set timeout 0
1047 if (pl2303_wait_tx_drain(plp
, 0) != USB_SUCCESS
) {
1049 mutex_exit(&plp
->pl_mutex
);
1051 return (USB_FAILURE
);
1054 mutex_exit(&plp
->pl_mutex
);
1056 /* wait 500 ms until hw fifo drains */
1064 * configuration routines
1065 * ----------------------
1070 pl2303_cleanup(pl2303_state_t
*plp
, int level
)
1072 ASSERT((level
> 0) && (level
<= PL2303_CLEANUP_LEVEL_MAX
));
1076 pl2303_close_pipes(plp
);
1079 usb_unregister_event_cbs(plp
->pl_dip
, plp
->pl_usb_events
);
1082 pl2303_destroy_pm_components(plp
);
1085 mutex_destroy(&plp
->pl_mutex
);
1086 cv_destroy(&plp
->pl_tx_cv
);
1088 usb_free_log_hdl(plp
->pl_lh
);
1091 usb_free_descr_tree(plp
->pl_dip
, plp
->pl_dev_data
);
1092 plp
->pl_def_ph
= NULL
;
1095 usb_client_detach(plp
->pl_dip
, plp
->pl_dev_data
);
1098 kmem_free(plp
, sizeof (pl2303_state_t
));
1104 * device specific attach
1107 pl2303_dev_attach(pl2303_state_t
*plp
)
1109 if (pl2303_open_pipes(plp
) != USB_SUCCESS
) {
1110 return (USB_FAILURE
);
1113 return (USB_SUCCESS
);
1122 * restore device state after CPR resume or reconnect
1125 pl2303_restore_device_state(pl2303_state_t
*plp
)
1129 mutex_enter(&plp
->pl_mutex
);
1130 state
= plp
->pl_dev_state
;
1131 mutex_exit(&plp
->pl_mutex
);
1133 if ((state
!= USB_DEV_DISCONNECTED
) && (state
!= USB_DEV_SUSPENDED
)) {
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
);
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");
1152 if (pl2303_reconnect_pipes(plp
) != USB_SUCCESS
) {
1160 mutex_enter(&plp
->pl_mutex
);
1161 state
= plp
->pl_dev_state
= USB_DEV_ONLINE
;
1162 mutex_exit(&plp
->pl_mutex
);
1164 if ((pl2303_restore_port_state(plp
) != USB_SUCCESS
)) {
1165 USB_DPRINTF_L2(DPRINT_HOTPLUG
, plp
->pl_lh
,
1166 "pl2303_restore_device_state: failed");
1174 * restore ports state after CPR resume or reconnect
1177 pl2303_restore_port_state(pl2303_state_t
*plp
)
1181 mutex_enter(&plp
->pl_mutex
);
1182 if (plp
->pl_port_state
!= PL2303_PORT_OPEN
) {
1183 mutex_exit(&plp
->pl_mutex
);
1185 return (USB_SUCCESS
);
1187 mutex_exit(&plp
->pl_mutex
);
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");
1204 * create PM components
1207 pl2303_create_pm_components(pl2303_state_t
*plp
)
1209 dev_info_t
*dip
= plp
->pl_dip
;
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");
1217 return (USB_SUCCESS
);
1220 pm
= plp
->pl_pm
= kmem_zalloc(sizeof (pl2303_pm_t
), KM_SLEEP
);
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
);
1227 (void) pm_raise_power(dip
, 0, USB_DEV_OS_FULL_PWR
);
1229 return (USB_SUCCESS
);
1234 * destroy PM components
1237 pl2303_destroy_pm_components(pl2303_state_t
*plp
)
1239 pl2303_pm_t
*pm
= plp
->pl_pm
;
1240 dev_info_t
*dip
= plp
->pl_dip
;
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
);
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
);
1265 (void) pm_lower_power(dip
, 0, USB_DEV_OS_PWR_OFF
);
1267 kmem_free(pm
, sizeof (pl2303_pm_t
));
1273 * mark device busy and raise power
1276 pl2303_pm_set_busy(pl2303_state_t
*plp
)
1278 pl2303_pm_t
*pm
= plp
->pl_pm
;
1279 dev_info_t
*dip
= plp
->pl_dip
;
1282 USB_DPRINTF_L4(DPRINT_PM
, plp
->pl_lh
, "pl2303_pm_set_busy");
1286 return (USB_SUCCESS
);
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
);
1294 return (USB_SUCCESS
);
1297 rval
= pm_busy_component(dip
, 0);
1298 ASSERT(rval
== DDI_SUCCESS
);
1300 if (pm
->pm_cur_power
== USB_DEV_OS_FULL_PWR
) {
1301 mutex_exit(&plp
->pl_mutex
);
1303 return (USB_SUCCESS
);
1306 /* need to raise power */
1307 pm
->pm_raise_power
= B_TRUE
;
1308 mutex_exit(&plp
->pl_mutex
);
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");
1315 mutex_enter(&plp
->pl_mutex
);
1316 pm
->pm_raise_power
= B_FALSE
;
1317 mutex_exit(&plp
->pl_mutex
);
1319 return (USB_SUCCESS
);
1327 pl2303_pm_set_idle(pl2303_state_t
*plp
)
1329 pl2303_pm_t
*pm
= plp
->pl_pm
;
1330 dev_info_t
*dip
= plp
->pl_dip
;
1332 USB_DPRINTF_L4(DPRINT_PM
, plp
->pl_lh
, "pl2303_pm_set_idle");
1340 * if more ports use the device, do not mark as yet
1342 mutex_enter(&plp
->pl_mutex
);
1343 if (--pm
->pm_busy_cnt
> 0) {
1344 mutex_exit(&plp
->pl_mutex
);
1350 (void) pm_idle_component(dip
, 0);
1352 mutex_exit(&plp
->pl_mutex
);
1357 * Functions to handle power transition for OS levels 0 -> 3
1358 * The same level as OS state, different from USB state
1361 pl2303_pwrlvl0(pl2303_state_t
*plp
)
1365 USB_DPRINTF_L4(DPRINT_PM
, plp
->pl_lh
, "pl2303_pwrlvl0");
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
);
1373 plp
->pl_dev_state
= USB_DEV_PWRED_DOWN
;
1374 plp
->pl_pm
->pm_cur_power
= USB_DEV_OS_PWR_OFF
;
1377 case USB_DEV_DISCONNECTED
:
1378 case USB_DEV_SUSPENDED
:
1379 /* allow a disconnect/cpr'ed device to go to lower power */
1381 return (USB_SUCCESS
);
1382 case USB_DEV_PWRED_DOWN
:
1384 USB_DPRINTF_L2(DPRINT_PM
, plp
->pl_lh
,
1385 "pl2303_pwrlvl0: illegal device state");
1387 return (USB_FAILURE
);
1393 pl2303_pwrlvl1(pl2303_state_t
*plp
)
1395 USB_DPRINTF_L4(DPRINT_PM
, plp
->pl_lh
, "pl2303_pwrlvl1");
1397 /* issue USB D2 command to the device */
1398 (void) usb_set_device_pwrlvl2(plp
->pl_dip
);
1400 return (USB_FAILURE
);
1405 pl2303_pwrlvl2(pl2303_state_t
*plp
)
1407 USB_DPRINTF_L4(DPRINT_PM
, plp
->pl_lh
, "pl2303_pwrlvl2");
1409 /* issue USB D1 command to the device */
1410 (void) usb_set_device_pwrlvl1(plp
->pl_dip
);
1412 return (USB_FAILURE
);
1417 pl2303_pwrlvl3(pl2303_state_t
*plp
)
1421 USB_DPRINTF_L4(DPRINT_PM
, plp
->pl_lh
, "pl2303_pwrlvl3");
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
);
1429 plp
->pl_dev_state
= USB_DEV_ONLINE
;
1430 plp
->pl_pm
->pm_cur_power
= USB_DEV_OS_FULL_PWR
;
1433 case USB_DEV_ONLINE
:
1434 /* we are already in full power */
1437 case USB_DEV_DISCONNECTED
:
1438 case USB_DEV_SUSPENDED
:
1440 return (USB_SUCCESS
);
1442 USB_DPRINTF_L2(DPRINT_PM
, plp
->pl_lh
,
1443 "pl2303_pwrlvl3: illegal device state");
1445 return (USB_FAILURE
);
1457 pl2303_open_pipes(pl2303_state_t
*plp
)
1460 usb_pipe_policy_t policy
;
1461 usb_ep_data_t
*in_data
, *out_data
;
1464 ifc
= plp
->pl_dev_data
->dev_curr_if
;
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
);
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
);
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");
1477 return (USB_FAILURE
);
1481 policy
.pp_max_async_reqs
= 2;
1483 if (usb_pipe_open(plp
->pl_dip
, &in_data
->ep_descr
, &policy
,
1484 USB_FLAGS_SLEEP
, &plp
->pl_bulkin_ph
) != USB_SUCCESS
) {
1486 return (USB_FAILURE
);
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
,
1494 return (USB_FAILURE
);
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
);
1502 return (USB_SUCCESS
);
1507 pl2303_close_pipes(pl2303_state_t
*plp
)
1509 if (plp
->pl_bulkin_ph
) {
1510 usb_pipe_close(plp
->pl_dip
, plp
->pl_bulkin_ph
,
1511 USB_FLAGS_SLEEP
, 0, 0);
1513 if (plp
->pl_bulkout_ph
) {
1514 usb_pipe_close(plp
->pl_dip
, plp
->pl_bulkout_ph
,
1515 USB_FLAGS_SLEEP
, 0, 0);
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
);
1526 pl2303_disconnect_pipes(pl2303_state_t
*plp
)
1528 pl2303_close_pipes(plp
);
1533 pl2303_reconnect_pipes(pl2303_state_t
*plp
)
1535 if ((pl2303_open_pipes(plp
) != USB_SUCCESS
)) {
1537 return (USB_FAILURE
);
1540 return (USB_SUCCESS
);
1549 * bulk in common and exeception callback
1554 pl2303_bulkin_cb(usb_pipe_handle_t pipe
, usb_bulk_req_t
*req
)
1556 pl2303_state_t
*plp
= (pl2303_state_t
*)req
->bulk_client_private
;
1560 data
= req
->bulk_data
;
1561 data_len
= (data
) ? MBLKL(data
) : 0;
1563 USB_DPRINTF_L4(DPRINT_IN_PIPE
, plp
->pl_lh
, "pl2303_bulkin_cb: "
1565 req
->bulk_completion_reason
,
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
);
1578 usb_free_bulk_req(req
);
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");
1590 mutex_exit(&plp
->pl_mutex
);
1595 * bulk out common and exeception callback
1599 pl2303_bulkout_cb(usb_pipe_handle_t pipe
, usb_bulk_req_t
*req
)
1601 pl2303_state_t
*plp
= (pl2303_state_t
*)req
->bulk_client_private
;
1603 mblk_t
*data
= req
->bulk_data
;
1605 data_len
= (req
->bulk_data
) ? MBLKL(req
->bulk_data
) : 0;
1607 USB_DPRINTF_L4(DPRINT_OUT_PIPE
, plp
->pl_lh
,
1608 "pl2303_bulkout_cb: cr=%d len=%d",
1609 req
->bulk_completion_reason
,
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
;
1619 usb_free_bulk_req(req
);
1622 if (plp
->pl_cb
.cb_tx
) {
1623 plp
->pl_cb
.cb_tx(plp
->pl_cb
.cb_arg
);
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
);
1632 pl2303_tx_start(plp
, NULL
);
1634 mutex_exit(&plp
->pl_mutex
);
1639 * data transfer routines
1640 * ----------------------
1643 * start data receipt
1646 pl2303_rx_start(pl2303_state_t
*plp
)
1649 int rval
= USB_FAILURE
;
1651 USB_DPRINTF_L4(DPRINT_OUT_PIPE
, plp
->pl_lh
, "pl2303_rx_start");
1653 ASSERT(mutex_owned(&plp
->pl_mutex
));
1655 plp
->pl_bulkin_state
= PL2303_PIPE_BUSY
;
1656 mutex_exit(&plp
->pl_mutex
);
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
;
1666 rval
= usb_pipe_bulk_xfer(plp
->pl_bulkin_ph
, br
, 0);
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
);
1674 mutex_enter(&plp
->pl_mutex
);
1675 if (rval
!= USB_SUCCESS
) {
1676 plp
->pl_bulkin_state
= PL2303_PIPE_IDLE
;
1684 * start data transmit
1687 pl2303_tx_start(pl2303_state_t
*plp
, int *xferd
)
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' */
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
);
1703 if ((plp
->pl_port_flags
& PL2303_PORT_TX_STOPPED
) ||
1704 (plp
->pl_tx_mp
== NULL
)) {
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");
1714 ASSERT(MBLKL(plp
->pl_tx_mp
) > 0);
1716 /* send as much data as port can receive */
1717 len
= min(msgdsize(plp
->pl_tx_mp
), plp
->pl_xfer_sz
);
1724 if ((data
= allocb(len
, BPRI_LO
)) == NULL
) {
1730 * copy no more than 'len' bytes from mblk chain to transmit mblk 'data'
1734 while ((data_len
< len
) && 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
;
1742 if (MBLKL(mp
) < 1) {
1743 plp
->pl_tx_mp
= unlinkb(mp
);
1746 ASSERT(data_len
== len
);
1750 if (data_len
<= 0) {
1751 USB_DPRINTF_L3(DPRINT_OUT_PIPE
, plp
->pl_lh
,
1752 "pl2303_tx_start: copied zero bytes");
1758 plp
->pl_bulkout_state
= PL2303_PIPE_BUSY
;
1759 mutex_exit(&plp
->pl_mutex
);
1761 rval
= pl2303_send_data(plp
, data
);
1762 mutex_enter(&plp
->pl_mutex
);
1764 if (rval
!= USB_SUCCESS
) {
1765 plp
->pl_bulkout_state
= PL2303_PIPE_IDLE
;
1766 pl2303_put_head(&plp
->pl_tx_mp
, data
);
1776 pl2303_send_data(pl2303_state_t
*plp
, mblk_t
*data
)
1779 int len
= MBLKL(data
);
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
));
1788 br
= usb_alloc_bulk_req(plp
->pl_dip
, 0, USB_FLAGS_SLEEP
);
1789 br
->bulk_data
= data
;
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
;
1797 rval
= usb_pipe_bulk_xfer(plp
->pl_bulkout_ph
, br
, 0);
1799 if (rval
!= USB_SUCCESS
) {
1800 USB_DPRINTF_L2(DPRINT_OUT_PIPE
, plp
->pl_lh
,
1801 "pl2303_send_data: xfer failed %d", rval
);
1803 br
->bulk_data
= NULL
;
1804 usb_free_bulk_req(br
);
1812 * wait until local tx buffer drains.
1813 * 'timeout' is in seconds, zero means wait forever
1816 pl2303_wait_tx_drain(pl2303_state_t
*plp
, int timeout
)
1821 until
= ddi_get_lbolt() + drv_usectohz(1000 * 1000 * timeout
);
1823 while (plp
->pl_tx_mp
&& !over
) {
1825 /* whether timedout or signal pending */
1826 over
= (cv_timedwait_sig(&plp
->pl_tx_cv
,
1827 &plp
->pl_mutex
, until
) <= 0);
1829 /* whether a signal is pending */
1830 over
= (cv_wait_sig(&plp
->pl_tx_cv
,
1831 &plp
->pl_mutex
) == 0);
1835 return ((plp
->pl_tx_mp
== NULL
) ? USB_SUCCESS
: USB_FAILURE
);
1844 * initialize hardware serial port
1847 pl2303_open_hw_port(pl2303_state_t
*plp
)
1849 int rval
= USB_SUCCESS
;
1852 * initialize three Device Configuration Registers (DCR):
1853 * DCR0, DCR1, and DCR2
1856 switch (plp
->pl_chiptype
) {
1859 if ((rval
= pl2303_cmd_vendor_write0(plp
, SET_DCR0
,
1860 DCR0_INIT_H
)) != USB_SUCCESS
) {
1866 if ((rval
= pl2303_cmd_vendor_write0(plp
, SET_DCR1
,
1867 DCR1_INIT_H
)) != USB_SUCCESS
) {
1873 if ((rval
= pl2303_cmd_vendor_write0(plp
, SET_DCR2
,
1874 DCR2_INIT_H
)) != USB_SUCCESS
) {
1881 case (pl2303_HX_CHIP_D
):
1884 if ((rval
= pl2303_cmd_vendor_write0(plp
, SET_DCR0
,
1885 DCR0_INIT
)) != USB_SUCCESS
) {
1891 if ((rval
= pl2303_cmd_vendor_write0(plp
, SET_DCR1
,
1892 DCR1_INIT_X
)) != USB_SUCCESS
) {
1898 if ((rval
= pl2303_cmd_vendor_write0(plp
, SET_DCR2
,
1899 DCR2_INIT_X
)) != USB_SUCCESS
) {
1904 /* reset Downstream data pipes */
1905 if ((rval
= pl2303_cmd_vendor_write0(plp
,
1906 RESET_DOWNSTREAM_DATA_PIPE
, 0)) != USB_SUCCESS
) {
1911 /* reset Upstream data pipes */
1912 if ((rval
= pl2303_cmd_vendor_write0(plp
,
1913 RESET_UPSTREAM_DATA_PIPE
, 0)) != USB_SUCCESS
) {
1919 case (pl2303_UNKNOWN
):
1921 USB_DPRINTF_L2(DPRINT_OPEN
, plp
->pl_lh
,
1922 "pl2303_open_hw_port: unknown chiptype");
1932 * vendor-specific commands
1933 * ------------------------
1936 * Get_Line_Coding Request
1939 pl2303_cmd_get_line(pl2303_state_t
*plp
, mblk_t
**data
)
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
;
1950 rval
= usb_pipe_ctrl_xfer_wait(plp
->pl_def_ph
, &setup
, data
,
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]);
1960 USB_DPRINTF_L2(DPRINT_DEF_PIPE
, plp
->pl_lh
,
1961 "pl2303_cmd_get_line: failed %d %d %x",
1962 rval
, cr
, cb_flags
);
1964 if (*data
!= NULL
) {
1974 * Set_Line_Coding Request
1977 pl2303_cmd_set_line(pl2303_state_t
*plp
, mblk_t
*data
)
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
;
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]);
1991 rval
= usb_pipe_ctrl_xfer_wait(plp
->pl_def_ph
, &setup
, &data
,
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
);
2005 * Set_Control_Line_State Request to RTS and DTR
2008 pl2303_cmd_set_ctl(pl2303_state_t
*plp
, uint8_t val
)
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
;
2019 rval
= usb_pipe_ctrl_xfer_wait(plp
->pl_def_ph
, &setup
, NULL
,
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
);
2033 * Vendor_Specific_Write Request
2037 pl2303_cmd_vendor_write0(pl2303_state_t
*plp
, uint16_t value
, int16_t index
)
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
;
2046 setup
.wValue
= value
;
2047 setup
.wIndex
= index
;
2049 rval
= usb_pipe_ctrl_xfer_wait(plp
->pl_def_ph
, &setup
, NULL
,
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
);
2063 * For Hardware flow control
2066 pl2303_cmd_set_rtscts(pl2303_state_t
*plp
)
2069 switch (plp
->pl_chiptype
) {
2072 return (pl2303_cmd_vendor_write0(plp
, SET_DCR0
, DCR0_INIT_H
));
2074 case pl2303_HX_CHIP_D
:
2076 return (pl2303_cmd_vendor_write0(plp
, SET_DCR0
, DCR0_INIT_X
));
2077 case pl2303_UNKNOWN
:
2080 return (USB_FAILURE
);
2086 * Set TxD BREAK_ON or BREAK_OFF
2089 pl2303_cmd_break(pl2303_state_t
*plp
, int ctl
)
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
;
2098 setup
.wValue
= (ctl
== DS_ON
) ? PL2303_BREAK_ON
: PL2303_BREAK_OFF
;
2100 rval
= usb_pipe_ctrl_xfer_wait(plp
->pl_def_ph
, &setup
, NULL
,
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
);
2117 pl2303_mctl2reg(int mask
, int val
, uint8_t *line_ctl
)
2119 if (mask
& TIOCM_RTS
) {
2120 if (val
& TIOCM_RTS
) {
2121 *line_ctl
|= PL2303_CONTROL_RTS
;
2123 *line_ctl
&= ~PL2303_CONTROL_RTS
;
2126 if (mask
& TIOCM_DTR
) {
2127 if (val
& TIOCM_DTR
) {
2128 *line_ctl
|= PL2303_CONTROL_DTR
;
2130 *line_ctl
&= ~PL2303_CONTROL_DTR
;
2140 pl2303_reg2mctl(uint8_t line_ctl
)
2144 if (line_ctl
& PL2303_CONTROL_RTS
) {
2147 if (line_ctl
& PL2303_CONTROL_DTR
) {
2162 * link a message block to tail of message
2163 * account for the case when message is null
2166 pl2303_put_tail(mblk_t
**mpp
, mblk_t
*bp
)
2177 * put a message block at the head of the message
2178 * account for the case when message is null
2181 pl2303_put_head(mblk_t
**mpp
, mblk_t
*bp
)
2190 static usb_pipe_handle_t
2191 pl2303_out_pipe(ds_hdl_t hdl
, uint_t port_num
)
2193 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
2195 return (plp
->pl_bulkout_ph
);
2199 static usb_pipe_handle_t
2200 pl2303_in_pipe(ds_hdl_t hdl
, uint_t port_num
)
2202 pl2303_state_t
*plp
= (pl2303_state_t
*)hdl
;
2204 return (plp
->pl_bulkin_ph
);