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/*
23 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * Copyright 2013 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
29 */
30
31/*
32 * FTDI FT232R USB UART device-specific driver
33 *
34 * May work on the (many) devices based on earlier versions of the chip.
35 */
36
37#include <sys/types.h>
38#include <sys/param.h>
39#include <sys/conf.h>
40#include <sys/stream.h>
41#include <sys/strsun.h>
42#include <sys/termio.h>
43#include <sys/termiox.h>
44#include <sys/ddi.h>
45#include <sys/sunddi.h>
46
47#define	USBDRV_MAJOR_VER	2
48#define	USBDRV_MINOR_VER	0
49
50#include <sys/usb/usba.h>
51#include <sys/usb/usba/usba_types.h>
52#include <sys/usb/usba/usba_impl.h>
53
54#include <sys/usb/clients/usbser/usbser_dsdi.h>
55#include <sys/usb/clients/usbser/usbftdi/uftdi_var.h>
56#include <sys/usb/clients/usbser/usbftdi/uftdi_reg.h>
57
58#include <sys/usb/usbdevs.h>
59
60/*
61 * DSD operations
62 */
63static int	uftdi_attach(ds_attach_info_t *);
64static void	uftdi_detach(ds_hdl_t);
65static int	uftdi_register_cb(ds_hdl_t, uint_t, ds_cb_t *);
66static void	uftdi_unregister_cb(ds_hdl_t, uint_t);
67static int	uftdi_open_port(ds_hdl_t, uint_t);
68static int	uftdi_close_port(ds_hdl_t, uint_t);
69
70/* power management */
71static int	uftdi_usb_power(ds_hdl_t, int, int, int *);
72static int	uftdi_suspend(ds_hdl_t);
73static int	uftdi_resume(ds_hdl_t);
74static int	uftdi_disconnect(ds_hdl_t);
75static int	uftdi_reconnect(ds_hdl_t);
76
77/* standard UART operations */
78static int	uftdi_set_port_params(ds_hdl_t, uint_t, ds_port_params_t *);
79static int	uftdi_set_modem_ctl(ds_hdl_t, uint_t, int, int);
80static int	uftdi_get_modem_ctl(ds_hdl_t, uint_t, int, int *);
81static int	uftdi_break_ctl(ds_hdl_t, uint_t, int);
82
83/* data xfer */
84static int	uftdi_tx(ds_hdl_t, uint_t, mblk_t *);
85static mblk_t	*uftdi_rx(ds_hdl_t, uint_t);
86static void	uftdi_stop(ds_hdl_t, uint_t, int);
87static void	uftdi_start(ds_hdl_t, uint_t, int);
88static int	uftdi_fifo_flush(ds_hdl_t, uint_t, int);
89static int	uftdi_fifo_drain(ds_hdl_t, uint_t, int);
90
91/* polled I/O support */
92static usb_pipe_handle_t uftdi_out_pipe(ds_hdl_t, uint_t);
93static usb_pipe_handle_t uftdi_in_pipe(ds_hdl_t, uint_t);
94
95/*
96 * Sub-routines
97 */
98
99/* configuration routines */
100static void	uftdi_cleanup(uftdi_state_t *, int);
101static int	uftdi_dev_attach(uftdi_state_t *);
102static int	uftdi_open_hw_port(uftdi_state_t *, int);
103
104/* hotplug */
105static int	uftdi_restore_device_state(uftdi_state_t *);
106static int	uftdi_restore_port_state(uftdi_state_t *);
107
108/* power management */
109static int	uftdi_create_pm_components(uftdi_state_t *);
110static void	uftdi_destroy_pm_components(uftdi_state_t *);
111static int	uftdi_pm_set_busy(uftdi_state_t *);
112static void	uftdi_pm_set_idle(uftdi_state_t *);
113static int	uftdi_pwrlvl0(uftdi_state_t *);
114static int	uftdi_pwrlvl1(uftdi_state_t *);
115static int	uftdi_pwrlvl2(uftdi_state_t *);
116static int	uftdi_pwrlvl3(uftdi_state_t *);
117
118/* pipe operations */
119static int	uftdi_open_pipes(uftdi_state_t *);
120static void	uftdi_close_pipes(uftdi_state_t *);
121static void	uftdi_disconnect_pipes(uftdi_state_t *);
122static int	uftdi_reconnect_pipes(uftdi_state_t *);
123
124/* pipe callbacks */
125static void	uftdi_bulkin_cb(usb_pipe_handle_t, usb_bulk_req_t *);
126static void	uftdi_bulkout_cb(usb_pipe_handle_t, usb_bulk_req_t *);
127
128/* data transfer routines */
129static int	uftdi_rx_start(uftdi_state_t *);
130static void	uftdi_tx_start(uftdi_state_t *, int *);
131static int	uftdi_send_data(uftdi_state_t *, mblk_t *);
132static int	uftdi_wait_tx_drain(uftdi_state_t *, int);
133
134/* vendor-specific commands */
135static int	uftdi_cmd_vendor_write0(uftdi_state_t *,
136		    uint16_t, uint16_t, uint16_t);
137
138/* misc */
139static void	uftdi_put_tail(mblk_t **, mblk_t *);
140static void	uftdi_put_head(mblk_t **, mblk_t *);
141
142
143/*
144 * DSD ops structure
145 */
146ds_ops_t uftdi_ds_ops = {
147	DS_OPS_VERSION,
148	uftdi_attach,
149	uftdi_detach,
150	uftdi_register_cb,
151	uftdi_unregister_cb,
152	uftdi_open_port,
153	uftdi_close_port,
154	uftdi_usb_power,
155	uftdi_suspend,
156	uftdi_resume,
157	uftdi_disconnect,
158	uftdi_reconnect,
159	uftdi_set_port_params,
160	uftdi_set_modem_ctl,
161	uftdi_get_modem_ctl,
162	uftdi_break_ctl,
163	NULL,			/* no loopback support */
164	uftdi_tx,
165	uftdi_rx,
166	uftdi_stop,
167	uftdi_start,
168	uftdi_fifo_flush,
169	uftdi_fifo_drain,
170	uftdi_out_pipe,
171	uftdi_in_pipe
172};
173
174/* debug support */
175static uint_t	uftdi_errlevel = USB_LOG_L4;
176static uint_t	uftdi_errmask = DPRINT_MASK_ALL;
177static uint_t	uftdi_instance_debug = (uint_t)-1;
178static uint_t	uftdi_attach_unrecognized = B_FALSE;
179
180/*
181 * ds_attach
182 */
183static int
184uftdi_attach(ds_attach_info_t *aip)
185{
186	uftdi_state_t *uf;
187	usb_dev_descr_t *dd;
188	int recognized;
189
190	uf = kmem_zalloc(sizeof (*uf), KM_SLEEP);
191	uf->uf_dip = aip->ai_dip;
192	uf->uf_usb_events = aip->ai_usb_events;
193	*aip->ai_hdl = (ds_hdl_t)uf;
194
195	/* only one port */
196	*aip->ai_port_cnt = 1;
197
198	if (usb_client_attach(uf->uf_dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
199		uftdi_cleanup(uf, 1);
200		return (USB_FAILURE);
201	}
202
203	if (usb_get_dev_data(uf->uf_dip,
204	    &uf->uf_dev_data, USB_PARSE_LVL_IF, 0) != USB_SUCCESS) {
205		uftdi_cleanup(uf, 2);
206		return (USB_FAILURE);
207	}
208
209	uf->uf_hwport = FTDI_PIT_SIOA + uf->uf_dev_data->dev_curr_if;
210
211	mutex_init(&uf->uf_lock, NULL, MUTEX_DRIVER,
212	    uf->uf_dev_data->dev_iblock_cookie);
213
214	cv_init(&uf->uf_tx_cv, NULL, CV_DRIVER, NULL);
215
216	uf->uf_lh = usb_alloc_log_hdl(uf->uf_dip, "uftdi",
217	    &uftdi_errlevel, &uftdi_errmask, &uftdi_instance_debug, 0);
218
219	/*
220	 * This device and its clones has numerous physical instantiations.
221	 */
222	recognized = B_TRUE;
223	dd = uf->uf_dev_data->dev_descr;
224	switch (dd->idVendor) {
225	case USB_VENDOR_FTDI:
226		switch (dd->idProduct) {
227		case USB_PRODUCT_FTDI_SERIAL_2232C:
228		case USB_PRODUCT_FTDI_SERIAL_8U232AM:
229		case USB_PRODUCT_FTDI_SEMC_DSS20:
230		case USB_PRODUCT_FTDI_CFA_631:
231		case USB_PRODUCT_FTDI_CFA_632:
232		case USB_PRODUCT_FTDI_CFA_633:
233		case USB_PRODUCT_FTDI_CFA_634:
234		case USB_PRODUCT_FTDI_CFA_635:
235		case USB_PRODUCT_FTDI_USBSERIAL:
236		case USB_PRODUCT_FTDI_MX2_3:
237		case USB_PRODUCT_FTDI_MX4_5:
238		case USB_PRODUCT_FTDI_LK202:
239		case USB_PRODUCT_FTDI_LK204:
240		case USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13M:
241		case USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13S:
242		case USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13U:
243		case USB_PRODUCT_FTDI_EISCOU:
244		case USB_PRODUCT_FTDI_UOPTBR:
245		case USB_PRODUCT_FTDI_EMCU2D:
246		case USB_PRODUCT_FTDI_PCMSFU:
247		case USB_PRODUCT_FTDI_EMCU2H:
248		case USB_PRODUCT_FTDI_232EX:
249			break;
250		default:
251			recognized = B_FALSE;
252			break;
253		}
254		break;
255	case USB_VENDOR_SIIG2:
256		switch (dd->idProduct) {
257		case USB_PRODUCT_SIIG2_US2308:
258			break;
259		default:
260			recognized = B_FALSE;
261			break;
262		}
263		break;
264	case USB_VENDOR_INTREPIDCS:
265		switch (dd->idProduct) {
266		case USB_PRODUCT_INTREPIDCS_VALUECAN:
267		case USB_PRODUCT_INTREPIDCS_NEOVI:
268			break;
269		default:
270			recognized = B_FALSE;
271			break;
272		}
273		break;
274	case USB_VENDOR_BBELECTRONICS:
275		switch (dd->idProduct) {
276		case USB_PRODUCT_BBELECTRONICS_USOTL4:
277			break;
278		default:
279			recognized = B_FALSE;
280			break;
281		}
282		break;
283	case USB_VENDOR_MELCO:
284		switch (dd->idProduct) {
285		case USB_PRODUCT_MELCO_PCOPRS1:
286			break;
287		default:
288			recognized = B_FALSE;
289			break;
290		}
291		break;
292	case USB_VENDOR_MARVELL:
293		switch (dd->idProduct) {
294		case USB_PRODUCT_MARVELL_SHEEVAPLUG:
295			break;
296		default:
297			recognized = B_FALSE;
298			break;
299		}
300		break;
301	default:
302		recognized = B_FALSE;
303		break;
304	}
305
306	/*
307	 * Set 'uftdi_attach_unrecognized' to non-zero to
308	 * experiment with newer devices ..
309	 */
310	if (!recognized && !uftdi_attach_unrecognized) {
311		uftdi_cleanup(uf, 3);
312		return (USB_FAILURE);
313	}
314
315	USB_DPRINTF_L3(DPRINT_ATTACH, uf->uf_lh,
316	    "uftdi: matched vendor 0x%x product 0x%x port %d",
317	    dd->idVendor, dd->idProduct, uf->uf_hwport);
318
319	uf->uf_def_ph = uf->uf_dev_data->dev_default_ph;
320
321	mutex_enter(&uf->uf_lock);
322	uf->uf_dev_state = USB_DEV_ONLINE;
323	uf->uf_port_state = UFTDI_PORT_CLOSED;
324	mutex_exit(&uf->uf_lock);
325
326	if (uftdi_create_pm_components(uf) != USB_SUCCESS) {
327		uftdi_cleanup(uf, 3);
328		return (USB_FAILURE);
329	}
330
331	if (usb_register_event_cbs(uf->uf_dip,
332	    uf->uf_usb_events, 0) != USB_SUCCESS) {
333		uftdi_cleanup(uf, 4);
334		return (USB_FAILURE);
335	}
336
337	if (uftdi_dev_attach(uf) != USB_SUCCESS) {
338		uftdi_cleanup(uf, 5);
339		return (USB_FAILURE);
340	}
341
342	return (USB_SUCCESS);
343}
344
345#define	FTDI_CLEANUP_LEVEL_MAX	6
346
347/*
348 * ds_detach
349 */
350static void
351uftdi_detach(ds_hdl_t hdl)
352{
353	uftdi_cleanup((uftdi_state_t *)hdl, FTDI_CLEANUP_LEVEL_MAX);
354}
355
356
357/*
358 * ds_register_cb
359 */
360/*ARGSUSED*/
361static int
362uftdi_register_cb(ds_hdl_t hdl, uint_t portno, ds_cb_t *cb)
363{
364	uftdi_state_t *uf = (uftdi_state_t *)hdl;
365
366	ASSERT(portno == 0);
367
368	uf->uf_cb = *cb;
369	return (USB_SUCCESS);
370}
371
372
373/*
374 * ds_unregister_cb
375 */
376/*ARGSUSED*/
377static void
378uftdi_unregister_cb(ds_hdl_t hdl, uint_t portno)
379{
380	uftdi_state_t *uf = (uftdi_state_t *)hdl;
381
382	ASSERT(portno == 0);
383
384	bzero(&uf->uf_cb, sizeof (uf->uf_cb));
385}
386
387
388/*
389 * ds_open_port
390 */
391/*ARGSUSED*/
392static int
393uftdi_open_port(ds_hdl_t hdl, uint_t portno)
394{
395	uftdi_state_t *uf = (uftdi_state_t *)hdl;
396	int rval;
397
398	USB_DPRINTF_L4(DPRINT_OPEN, uf->uf_lh, "uftdi_open_port %d", portno);
399
400	ASSERT(portno == 0);
401
402	mutex_enter(&uf->uf_lock);
403	if (uf->uf_dev_state == USB_DEV_DISCONNECTED ||
404	    uf->uf_port_state != UFTDI_PORT_CLOSED) {
405		mutex_exit(&uf->uf_lock);
406		return (USB_FAILURE);
407	}
408	mutex_exit(&uf->uf_lock);
409
410	if ((rval = uftdi_pm_set_busy(uf)) != USB_SUCCESS)
411		return (rval);
412
413	/* initialize hardware serial port */
414	rval = uftdi_open_hw_port(uf, 0);
415
416	if (rval == USB_SUCCESS) {
417		mutex_enter(&uf->uf_lock);
418
419		/* start to receive data */
420		if (uftdi_rx_start(uf) != USB_SUCCESS) {
421			mutex_exit(&uf->uf_lock);
422			return (USB_FAILURE);
423		}
424		uf->uf_port_state = UFTDI_PORT_OPEN;
425		mutex_exit(&uf->uf_lock);
426	} else
427		uftdi_pm_set_idle(uf);
428
429	return (rval);
430}
431
432
433/*
434 * ds_close_port
435 */
436/*ARGSUSED*/
437static int
438uftdi_close_port(ds_hdl_t hdl, uint_t portno)
439{
440	uftdi_state_t *uf = (uftdi_state_t *)hdl;
441
442	USB_DPRINTF_L4(DPRINT_CLOSE, uf->uf_lh, "uftdi_close_port %d", portno);
443
444	ASSERT(portno == 0);
445
446	mutex_enter(&uf->uf_lock);
447
448	/* free resources and finalize state */
449	freemsg(uf->uf_rx_mp);
450	uf->uf_rx_mp = NULL;
451
452	freemsg(uf->uf_tx_mp);
453	uf->uf_tx_mp = NULL;
454
455	uf->uf_port_state = UFTDI_PORT_CLOSED;
456	mutex_exit(&uf->uf_lock);
457
458	uftdi_pm_set_idle(uf);
459
460	return (USB_SUCCESS);
461}
462
463
464/*
465 * ds_usb_power
466 */
467/*ARGSUSED*/
468static int
469uftdi_usb_power(ds_hdl_t hdl, int comp, int level, int *new_state)
470{
471	uftdi_state_t *uf = (uftdi_state_t *)hdl;
472	uftdi_pm_t *pm = uf->uf_pm;
473	int rval;
474
475	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_usb_power");
476
477	if (!pm)
478		return (USB_FAILURE);
479
480	mutex_enter(&uf->uf_lock);
481
482	/*
483	 * check if we are transitioning to a legal power level
484	 */
485	if (USB_DEV_PWRSTATE_OK(pm->pm_pwr_states, level)) {
486		USB_DPRINTF_L2(DPRINT_PM, uf->uf_lh, "uftdi_usb_power: "
487		    "illegal power level %d, pwr_states=0x%x",
488		    level, pm->pm_pwr_states);
489		mutex_exit(&uf->uf_lock);
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(&uf->uf_lock);
498		return (USB_FAILURE);
499	}
500
501	switch (level) {
502	case USB_DEV_OS_PWR_OFF:
503		rval = uftdi_pwrlvl0(uf);
504		break;
505	case USB_DEV_OS_PWR_1:
506		rval = uftdi_pwrlvl1(uf);
507		break;
508	case USB_DEV_OS_PWR_2:
509		rval = uftdi_pwrlvl2(uf);
510		break;
511	case USB_DEV_OS_FULL_PWR:
512		rval = uftdi_pwrlvl3(uf);
513		/*
514		 * If usbser dev_state is DISCONNECTED or SUSPENDED, it shows
515		 * that the usb serial device is disconnected/suspended while it
516		 * is under power down state, now the device is powered up
517		 * before it is reconnected/resumed. xxx_pwrlvl3() will set dev
518		 * state to ONLINE, we need to set the dev state back to
519		 * DISCONNECTED/SUSPENDED.
520		 */
521		if (rval == USB_SUCCESS &&
522		    (*new_state == USB_DEV_DISCONNECTED ||
523		    *new_state == USB_DEV_SUSPENDED))
524			uf->uf_dev_state = *new_state;
525		break;
526	default:
527		ASSERT(0);	/* cannot happen */
528	}
529
530	*new_state = uf->uf_dev_state;
531	mutex_exit(&uf->uf_lock);
532
533	return (rval);
534}
535
536
537/*
538 * ds_suspend
539 */
540static int
541uftdi_suspend(ds_hdl_t hdl)
542{
543	uftdi_state_t *uf = (uftdi_state_t *)hdl;
544	int state = USB_DEV_SUSPENDED;
545
546	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_suspend");
547
548	/*
549	 * If the device is suspended while it is under PWRED_DOWN state, we
550	 * need to keep the PWRED_DOWN state so that it could be powered up
551	 * later. In the mean while, usbser dev state will be changed to
552	 * SUSPENDED state.
553	 */
554	mutex_enter(&uf->uf_lock);
555	if (uf->uf_dev_state != USB_DEV_PWRED_DOWN)
556		uf->uf_dev_state = USB_DEV_SUSPENDED;
557	mutex_exit(&uf->uf_lock);
558
559	uftdi_disconnect_pipes(uf);
560	return (state);
561}
562
563
564/*
565 * ds_resume
566 */
567static int
568uftdi_resume(ds_hdl_t hdl)
569{
570	uftdi_state_t *uf = (uftdi_state_t *)hdl;
571	int current_state;
572	int rval;
573
574	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_resume");
575
576	mutex_enter(&uf->uf_lock);
577	current_state = uf->uf_dev_state;
578	mutex_exit(&uf->uf_lock);
579
580	if (current_state == USB_DEV_ONLINE)
581		rval = USB_SUCCESS;
582	else
583		rval = uftdi_restore_device_state(uf);
584	return (rval);
585}
586
587
588/*
589 * ds_disconnect
590 */
591static int
592uftdi_disconnect(ds_hdl_t hdl)
593{
594	uftdi_state_t *uf = (uftdi_state_t *)hdl;
595	int state = USB_DEV_DISCONNECTED;
596
597	USB_DPRINTF_L4(DPRINT_HOTPLUG, uf->uf_lh, "uftdi_disconnect");
598
599	/*
600	 * If the device is disconnected while it is under PWRED_DOWN state, we
601	 * need to keep the PWRED_DOWN state so that it could be powered up
602	 * later. In the mean while, usbser dev state will be changed to
603	 * DISCONNECTED state.
604	 */
605	mutex_enter(&uf->uf_lock);
606	if (uf->uf_dev_state != USB_DEV_PWRED_DOWN)
607		uf->uf_dev_state = USB_DEV_DISCONNECTED;
608	mutex_exit(&uf->uf_lock);
609
610	uftdi_disconnect_pipes(uf);
611	return (state);
612}
613
614
615/*
616 * ds_reconnect
617 */
618static int
619uftdi_reconnect(ds_hdl_t hdl)
620{
621	uftdi_state_t *uf = (uftdi_state_t *)hdl;
622
623	USB_DPRINTF_L4(DPRINT_HOTPLUG, uf->uf_lh, "uftdi_reconnect");
624	return (uftdi_restore_device_state(uf));
625}
626
627/* translate parameters into device-specific bits */
628
629static int
630uftdi_param2regs(uftdi_state_t *uf, ds_port_params_t *tp, uftdi_regs_t *ur)
631{
632	ds_port_param_entry_t *pe;
633	int i;
634
635	ur->ur_data = 0;
636	ur->ur_flowval = 0;
637	ur->ur_flowidx = FTDI_SIO_DISABLE_FLOW_CTRL << 8;
638
639	for (i = 0, pe = tp->tp_entries; i < tp->tp_cnt; i++, pe++) {
640		switch (pe->param) {
641		case DS_PARAM_BAUD:
642			switch (pe->val.ui) {
643			case B300:
644				ur->ur_baud = ftdi_8u232am_b300;
645				break;
646			case B600:
647				ur->ur_baud = ftdi_8u232am_b600;
648				break;
649			case B1200:
650				ur->ur_baud = ftdi_8u232am_b1200;
651				break;
652			case B2400:
653				ur->ur_baud = ftdi_8u232am_b2400;
654				break;
655			case B4800:
656				ur->ur_baud = ftdi_8u232am_b4800;
657				break;
658			case B9600:
659				ur->ur_baud = ftdi_8u232am_b9600;
660				break;
661			case B19200:
662				ur->ur_baud = ftdi_8u232am_b19200;
663				break;
664			case B38400:
665				ur->ur_baud = ftdi_8u232am_b38400;
666				break;
667			case B57600:
668				ur->ur_baud = ftdi_8u232am_b57600;
669				break;
670			case B115200:
671				ur->ur_baud = ftdi_8u232am_b115200;
672				break;
673			case B230400:
674				ur->ur_baud = ftdi_8u232am_b230400;
675				break;
676			case B460800:
677				ur->ur_baud = ftdi_8u232am_b460800;
678				break;
679			case B921600:
680				ur->ur_baud = ftdi_8u232am_b921600;
681				break;
682			default:
683				USB_DPRINTF_L3(DPRINT_CTLOP, uf->uf_lh,
684				    "uftdi_param2regs: bad baud %d",
685				    pe->val.ui);
686				return (USB_FAILURE);
687			}
688			break;
689
690		case DS_PARAM_PARITY:
691			if (pe->val.ui & PARENB) {
692				if (pe->val.ui & PARODD)
693					ur->ur_data |=
694					    FTDI_SIO_SET_DATA_PARITY_ODD;
695				else
696					ur->ur_data |=
697					    FTDI_SIO_SET_DATA_PARITY_EVEN;
698			} else {
699				/* LINTED [E_EXPR_NULL_EFFECT] */
700				ur->ur_data |= FTDI_SIO_SET_DATA_PARITY_NONE;
701			}
702			break;
703
704		case DS_PARAM_STOPB:
705			if (pe->val.ui & CSTOPB)
706				ur->ur_data |= FTDI_SIO_SET_DATA_STOP_BITS_2;
707			else {
708				/* LINTED [E_EXPR_NULL_EFFECT] */
709				ur->ur_data |= FTDI_SIO_SET_DATA_STOP_BITS_1;
710			}
711			break;
712
713		case DS_PARAM_CHARSZ:
714			switch (pe->val.ui) {
715			case CS5:
716				ur->ur_data |= FTDI_SIO_SET_DATA_BITS(5);
717				break;
718			case CS6:
719				ur->ur_data |= FTDI_SIO_SET_DATA_BITS(6);
720				break;
721			case CS7:
722				ur->ur_data |= FTDI_SIO_SET_DATA_BITS(7);
723				break;
724			case CS8:
725			default:
726				ur->ur_data |= FTDI_SIO_SET_DATA_BITS(8);
727				break;
728			}
729			break;
730
731		case DS_PARAM_XON_XOFF:		/* Software flow control */
732			if ((pe->val.ui & IXON) || (pe->val.ui & IXOFF)) {
733				uint8_t xonc = pe->val.uc[0];
734				uint8_t xoffc = pe->val.uc[1];
735
736				ur->ur_flowval = (xoffc << 8) | xonc;
737				ur->ur_flowidx = FTDI_SIO_XON_XOFF_HS << 8;
738			}
739			break;
740
741		case DS_PARAM_FLOW_CTL:		/* Hardware flow control */
742			if (pe->val.ui & (RTSXOFF | CTSXON)) {
743				ur->ur_flowval = 0;
744				ur->ur_flowidx = FTDI_SIO_RTS_CTS_HS << 8;
745			}
746			if (pe->val.ui & DTRXOFF) {
747				ur->ur_flowval = 0;
748				ur->ur_flowidx = FTDI_SIO_DTR_DSR_HS << 8;
749			}
750			break;
751		default:
752			USB_DPRINTF_L2(DPRINT_CTLOP, uf->uf_lh,
753			    "uftdi_param2regs: bad param %d", pe->param);
754			break;
755		}
756	}
757	return (USB_SUCCESS);
758}
759
760/*
761 * Write the register set to the device and update the state structure.
762 * If there are errors, return the device to its previous state.
763 */
764static int
765uftdi_setregs(uftdi_state_t *uf, uftdi_regs_t *ur)
766{
767	int rval;
768	uftdi_regs_t uold;
769
770	mutex_enter(&uf->uf_lock);
771	uold = uf->uf_softr;
772	mutex_exit(&uf->uf_lock);
773
774	if (ur == NULL)
775		ur = &uold;	/* NULL => restore previous values */
776
777	rval = uftdi_cmd_vendor_write0(uf, FTDI_SIO_SET_BAUD_RATE,
778	    ur->ur_baud, uf->uf_hwport);
779	if (rval != USB_SUCCESS) {
780		(void) uftdi_cmd_vendor_write0(uf, FTDI_SIO_SET_BAUD_RATE,
781		    uold.ur_baud, uf->uf_hwport);
782		goto out;
783	} else {
784		mutex_enter(&uf->uf_lock);
785		uf->uf_softr.ur_baud = ur->ur_baud;
786		mutex_exit(&uf->uf_lock);
787	}
788
789	rval = uftdi_cmd_vendor_write0(uf, FTDI_SIO_SET_DATA,
790	    ur->ur_data, uf->uf_hwport);
791	if (rval != USB_SUCCESS) {
792		(void) uftdi_cmd_vendor_write0(uf, FTDI_SIO_SET_DATA,
793		    uold.ur_data, uf->uf_hwport);
794		goto out;
795	} else {
796		mutex_enter(&uf->uf_lock);
797		uf->uf_softr.ur_data = ur->ur_data;
798		mutex_exit(&uf->uf_lock);
799	}
800
801	rval = uftdi_cmd_vendor_write0(uf, FTDI_SIO_SET_FLOW_CTRL,
802	    ur->ur_flowval, ur->ur_flowidx | uf->uf_hwport);
803	if (rval != USB_SUCCESS) {
804		(void) uftdi_cmd_vendor_write0(uf, FTDI_SIO_SET_FLOW_CTRL,
805		    uold.ur_flowval, uold.ur_flowidx | uf->uf_hwport);
806		goto out;
807	} else {
808		mutex_enter(&uf->uf_lock);
809		uf->uf_softr.ur_flowval = ur->ur_flowval;
810		uf->uf_softr.ur_flowidx = ur->ur_flowidx;
811		mutex_exit(&uf->uf_lock);
812	}
813out:
814	return (rval);
815}
816
817/*
818 * ds_set_port_params
819 */
820static int
821uftdi_set_port_params(ds_hdl_t hdl, uint_t portno, ds_port_params_t *tp)
822{
823	uftdi_state_t *uf = (uftdi_state_t *)hdl;
824	int rval;
825	uftdi_regs_t uregs;
826
827	ASSERT(portno == 0);
828
829	USB_DPRINTF_L4(DPRINT_CTLOP, uf->uf_lh, "uftdi_set_port_params");
830
831	rval = uftdi_param2regs(uf, tp, &uregs);
832	if (rval == USB_SUCCESS)
833		rval = uftdi_setregs(uf, &uregs);
834	return (rval);
835}
836
837/*
838 * ds_set_modem_ctl
839 */
840static int
841uftdi_set_modem_ctl(ds_hdl_t hdl, uint_t portno, int mask, int val)
842{
843	uftdi_state_t *uf = (uftdi_state_t *)hdl;
844	int rval;
845	uint16_t mctl;
846
847	ASSERT(portno == 0);
848
849	USB_DPRINTF_L4(DPRINT_CTLOP, uf->uf_lh, "uftdi_set_modem_ctl");
850
851	/*
852	 * Note that we cannot set DTR and RTS simultaneously, so
853	 * we do separate operations for each bit.
854	 */
855
856	if (mask & TIOCM_DTR) {
857		mctl = (val & TIOCM_DTR) ?
858		    FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW;
859
860		rval = uftdi_cmd_vendor_write0(uf,
861		    FTDI_SIO_MODEM_CTRL, mctl, uf->uf_hwport);
862
863		if (rval == USB_SUCCESS) {
864			mutex_enter(&uf->uf_lock);
865			uf->uf_mctl &= ~FTDI_SIO_SET_DTR_HIGH;
866			uf->uf_mctl |= mctl & FTDI_SIO_SET_DTR_HIGH;
867			mutex_exit(&uf->uf_lock);
868		} else
869			return (rval);
870	}
871
872	if (mask & TIOCM_RTS) {
873		mctl = (val & TIOCM_RTS) ?
874		    FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW;
875
876		rval = uftdi_cmd_vendor_write0(uf,
877		    FTDI_SIO_MODEM_CTRL, mctl, uf->uf_hwport);
878
879		if (rval == USB_SUCCESS) {
880			mutex_enter(&uf->uf_lock);
881			uf->uf_mctl &= ~FTDI_SIO_SET_RTS_HIGH;
882			uf->uf_mctl |= mctl & FTDI_SIO_SET_RTS_HIGH;
883			mutex_exit(&uf->uf_lock);
884		}
885	}
886
887	return (rval);
888}
889
890/*
891 * ds_get_modem_ctl
892 */
893static int
894uftdi_get_modem_ctl(ds_hdl_t hdl, uint_t portno, int mask, int *valp)
895{
896	uftdi_state_t *uf = (uftdi_state_t *)hdl;
897	uint_t val = 0;
898
899	ASSERT(portno == 0);
900
901	USB_DPRINTF_L4(DPRINT_CTLOP, uf->uf_lh, "uftdi_get_modem_ctl");
902
903	mutex_enter(&uf->uf_lock);
904	/*
905	 * This status info is delivered to us at least every 40ms
906	 * while the receive pipe is active
907	 */
908	if (uf->uf_msr & FTDI_MSR_STATUS_CTS)
909		val |= TIOCM_CTS;
910	if (uf->uf_msr & FTDI_MSR_STATUS_DSR)
911		val |= TIOCM_DSR;
912	if (uf->uf_msr & FTDI_MSR_STATUS_RI)
913		val |= TIOCM_RI;
914	if (uf->uf_msr & FTDI_MSR_STATUS_RLSD)
915		val |= TIOCM_CD;
916
917	/*
918	 * Note, this status info is simply a replay of what we
919	 * asked it to be in some previous "set" command, and
920	 * is *not* directly sensed from the hardware.
921	 */
922	if ((uf->uf_mctl & FTDI_SIO_SET_RTS_HIGH) == FTDI_SIO_SET_RTS_HIGH)
923		val |= TIOCM_RTS;
924	if ((uf->uf_mctl & FTDI_SIO_SET_DTR_HIGH) == FTDI_SIO_SET_DTR_HIGH)
925		val |= TIOCM_DTR;
926	mutex_exit(&uf->uf_lock);
927
928	*valp = val & mask;
929
930	return (USB_SUCCESS);
931}
932
933
934/*
935 * ds_break_ctl
936 */
937static int
938uftdi_break_ctl(ds_hdl_t hdl, uint_t portno, int ctl)
939{
940	uftdi_state_t *uf = (uftdi_state_t *)hdl;
941	uftdi_regs_t *ur = &uf->uf_softr;
942	uint16_t data;
943
944	ASSERT(portno == 0);
945
946	USB_DPRINTF_L4(DPRINT_CTLOP, uf->uf_lh, "uftdi_break_ctl");
947
948	mutex_enter(&uf->uf_lock);
949	data = ur->ur_data | (ctl == DS_ON) ?  FTDI_SIO_SET_BREAK : 0;
950	mutex_exit(&uf->uf_lock);
951
952	return (uftdi_cmd_vendor_write0(uf, FTDI_SIO_SET_DATA,
953	    data, uf->uf_hwport));
954}
955
956
957/*
958 * ds_tx
959 */
960/*ARGSUSED*/
961static int
962uftdi_tx(ds_hdl_t hdl, uint_t portno, mblk_t *mp)
963{
964	uftdi_state_t *uf = (uftdi_state_t *)hdl;
965
966	ASSERT(portno == 0);
967
968	USB_DPRINTF_L4(DPRINT_CTLOP, uf->uf_lh, "uftdi_tx");
969
970	ASSERT(mp != NULL && MBLKL(mp) >= 1);
971
972	mutex_enter(&uf->uf_lock);
973	uftdi_put_tail(&uf->uf_tx_mp, mp);	/* add to the chain */
974	uftdi_tx_start(uf, NULL);
975	mutex_exit(&uf->uf_lock);
976
977	return (USB_SUCCESS);
978}
979
980
981/*
982 * ds_rx
983 */
984/*ARGSUSED*/
985static mblk_t *
986uftdi_rx(ds_hdl_t hdl, uint_t portno)
987{
988	uftdi_state_t *uf = (uftdi_state_t *)hdl;
989	mblk_t *mp;
990
991	ASSERT(portno == 0);
992
993	USB_DPRINTF_L4(DPRINT_CTLOP, uf->uf_lh, "uftdi_rx");
994
995	mutex_enter(&uf->uf_lock);
996	mp = uf->uf_rx_mp;
997	uf->uf_rx_mp = NULL;
998	mutex_exit(&uf->uf_lock);
999
1000	return (mp);
1001}
1002
1003
1004/*
1005 * ds_stop
1006 */
1007/*ARGSUSED*/
1008static void
1009uftdi_stop(ds_hdl_t hdl, uint_t portno, int dir)
1010{
1011	uftdi_state_t *uf = (uftdi_state_t *)hdl;
1012
1013	ASSERT(portno == 0);
1014
1015	USB_DPRINTF_L4(DPRINT_CTLOP, uf->uf_lh, "uftdi_stop");
1016
1017	if (dir & DS_TX) {
1018		mutex_enter(&uf->uf_lock);
1019		uf->uf_port_flags |= UFTDI_PORT_TX_STOPPED;
1020		mutex_exit(&uf->uf_lock);
1021	}
1022}
1023
1024
1025/*
1026 * ds_start
1027 */
1028/*ARGSUSED*/
1029static void
1030uftdi_start(ds_hdl_t hdl, uint_t portno, int dir)
1031{
1032	uftdi_state_t *uf = (uftdi_state_t *)hdl;
1033
1034	ASSERT(portno == 0);
1035
1036	USB_DPRINTF_L4(DPRINT_CTLOP, uf->uf_lh, "uftdi_start");
1037
1038	if (dir & DS_TX) {
1039		mutex_enter(&uf->uf_lock);
1040		if (uf->uf_port_flags & UFTDI_PORT_TX_STOPPED) {
1041			uf->uf_port_flags &= ~UFTDI_PORT_TX_STOPPED;
1042			uftdi_tx_start(uf, NULL);
1043		}
1044		mutex_exit(&uf->uf_lock);
1045	}
1046}
1047
1048
1049/*
1050 * ds_fifo_flush
1051 */
1052/*ARGSUSED*/
1053static int
1054uftdi_fifo_flush(ds_hdl_t hdl, uint_t portno, int dir)
1055{
1056	uftdi_state_t *uf = (uftdi_state_t *)hdl;
1057
1058	ASSERT(portno == 0);
1059
1060	USB_DPRINTF_L4(DPRINT_CTLOP, uf->uf_lh,
1061	    "uftdi_fifo_flush: dir=0x%x", dir);
1062
1063	mutex_enter(&uf->uf_lock);
1064	ASSERT(uf->uf_port_state == UFTDI_PORT_OPEN);
1065
1066	if (dir & DS_TX) {
1067		freemsg(uf->uf_tx_mp);
1068		uf->uf_tx_mp = NULL;
1069	}
1070
1071	if (dir & DS_RX) {
1072		freemsg(uf->uf_rx_mp);
1073		uf->uf_rx_mp = NULL;
1074	}
1075	mutex_exit(&uf->uf_lock);
1076
1077	if (dir & DS_TX)
1078		(void) uftdi_cmd_vendor_write0(uf,
1079		    FTDI_SIO_RESET, FTDI_SIO_RESET_PURGE_TX, uf->uf_hwport);
1080
1081	if (dir & DS_RX)
1082		(void) uftdi_cmd_vendor_write0(uf,
1083		    FTDI_SIO_RESET, FTDI_SIO_RESET_PURGE_RX, uf->uf_hwport);
1084
1085	return (USB_SUCCESS);
1086}
1087
1088
1089/*
1090 * ds_fifo_drain
1091 */
1092/*ARGSUSED*/
1093static int
1094uftdi_fifo_drain(ds_hdl_t hdl, uint_t portno, int timeout)
1095{
1096	uftdi_state_t *uf = (uftdi_state_t *)hdl;
1097	unsigned int count;
1098	const uint_t countmax = 50;	/* at least 500ms */
1099	const uint8_t txempty =
1100	    FTDI_LSR_STATUS_TEMT | FTDI_LSR_STATUS_THRE;
1101
1102	ASSERT(portno == 0);
1103
1104	USB_DPRINTF_L4(DPRINT_CTLOP, uf->uf_lh, "uftdi_fifo_drain");
1105
1106	mutex_enter(&uf->uf_lock);
1107	ASSERT(uf->uf_port_state == UFTDI_PORT_OPEN);
1108
1109	if (uftdi_wait_tx_drain(uf, 0) != USB_SUCCESS) {
1110		mutex_exit(&uf->uf_lock);
1111		return (USB_FAILURE);
1112	}
1113
1114	/*
1115	 * Wait for the TX fifo to indicate empty.
1116	 *
1117	 * At all but the slowest baud rates, this is
1118	 * likely to be a one-shot test that instantly
1119	 * succeeds, but poll for at least 'countmax'
1120	 * tries before giving up.
1121	 */
1122	for (count = 0; count < countmax; count++) {
1123		if ((uf->uf_lsr & txempty) == txempty)
1124			break;
1125		mutex_exit(&uf->uf_lock);
1126		delay(drv_usectohz(10*1000));	/* 10ms */
1127		mutex_enter(&uf->uf_lock);
1128	}
1129
1130	mutex_exit(&uf->uf_lock);
1131
1132	return (count < countmax ? USB_SUCCESS : USB_FAILURE);
1133}
1134
1135
1136/*
1137 * configuration clean up
1138 */
1139static void
1140uftdi_cleanup(uftdi_state_t *uf, int level)
1141{
1142	ASSERT(level > 0 && level <= UFTDI_CLEANUP_LEVEL_MAX);
1143
1144	switch (level) {
1145	default:
1146	case 6:
1147		uftdi_close_pipes(uf);
1148		/*FALLTHROUGH*/
1149	case 5:
1150		usb_unregister_event_cbs(uf->uf_dip, uf->uf_usb_events);
1151		/*FALLTHROUGH*/
1152	case 4:
1153		uftdi_destroy_pm_components(uf);
1154		/*FALLTHROUGH*/
1155	case 3:
1156		mutex_destroy(&uf->uf_lock);
1157		cv_destroy(&uf->uf_tx_cv);
1158
1159		usb_free_log_hdl(uf->uf_lh);
1160		uf->uf_lh = NULL;
1161
1162		usb_free_descr_tree(uf->uf_dip, uf->uf_dev_data);
1163		uf->uf_def_ph = NULL;
1164		/*FALLTHROUGH*/
1165	case 2:
1166		usb_client_detach(uf->uf_dip, uf->uf_dev_data);
1167		/*FALLTHROUGH*/
1168	case 1:
1169		kmem_free(uf, sizeof (*uf));
1170		break;
1171	}
1172}
1173
1174
1175/*
1176 * device specific attach
1177 */
1178static int
1179uftdi_dev_attach(uftdi_state_t *uf)
1180{
1181	return (uftdi_open_pipes(uf));
1182}
1183
1184
1185/*
1186 * restore device state after CPR resume or reconnect
1187 */
1188static int
1189uftdi_restore_device_state(uftdi_state_t *uf)
1190{
1191	int state;
1192
1193	mutex_enter(&uf->uf_lock);
1194	state = uf->uf_dev_state;
1195	mutex_exit(&uf->uf_lock);
1196
1197	if (state != USB_DEV_DISCONNECTED && state != USB_DEV_SUSPENDED)
1198		return (state);
1199
1200	if (usb_check_same_device(uf->uf_dip, uf->uf_lh, USB_LOG_L0,
1201	    DPRINT_MASK_ALL, USB_CHK_ALL, NULL) != USB_SUCCESS) {
1202		mutex_enter(&uf->uf_lock);
1203		state = uf->uf_dev_state = USB_DEV_DISCONNECTED;
1204		mutex_exit(&uf->uf_lock);
1205		return (state);
1206	}
1207
1208	if (state == USB_DEV_DISCONNECTED) {
1209		USB_DPRINTF_L0(DPRINT_HOTPLUG, uf->uf_lh,
1210		    "Device has been reconnected but data may have been lost");
1211	}
1212
1213	if (uftdi_reconnect_pipes(uf) != USB_SUCCESS)
1214		return (state);
1215
1216	/*
1217	 * init device state
1218	 */
1219	mutex_enter(&uf->uf_lock);
1220	state = uf->uf_dev_state = USB_DEV_ONLINE;
1221	mutex_exit(&uf->uf_lock);
1222
1223	if ((uftdi_restore_port_state(uf) != USB_SUCCESS)) {
1224		USB_DPRINTF_L2(DPRINT_HOTPLUG, uf->uf_lh,
1225		    "uftdi_restore_device_state: failed");
1226	}
1227
1228	return (state);
1229}
1230
1231
1232/*
1233 * restore ports state after CPR resume or reconnect
1234 */
1235static int
1236uftdi_restore_port_state(uftdi_state_t *uf)
1237{
1238	int rval;
1239
1240	mutex_enter(&uf->uf_lock);
1241	if (uf->uf_port_state != UFTDI_PORT_OPEN) {
1242		mutex_exit(&uf->uf_lock);
1243		return (USB_SUCCESS);
1244	}
1245	mutex_exit(&uf->uf_lock);
1246
1247	/* open hardware serial port, restoring old settings */
1248	if ((rval = uftdi_open_hw_port(uf, 1)) != USB_SUCCESS) {
1249		USB_DPRINTF_L2(DPRINT_HOTPLUG, uf->uf_lh,
1250		    "uftdi_restore_port_state: failed");
1251	}
1252
1253	return (rval);
1254}
1255
1256
1257/*
1258 * create PM components
1259 */
1260static int
1261uftdi_create_pm_components(uftdi_state_t *uf)
1262{
1263	dev_info_t	*dip = uf->uf_dip;
1264	uftdi_pm_t	*pm;
1265	uint_t		pwr_states;
1266
1267	if (usb_create_pm_components(dip, &pwr_states) != USB_SUCCESS) {
1268		USB_DPRINTF_L2(DPRINT_PM, uf->uf_lh,
1269		    "uftdi_create_pm_components: failed");
1270		return (USB_SUCCESS);
1271	}
1272
1273	pm = uf->uf_pm = kmem_zalloc(sizeof (*pm), KM_SLEEP);
1274
1275	pm->pm_pwr_states = (uint8_t)pwr_states;
1276	pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
1277	pm->pm_wakeup_enabled = usb_handle_remote_wakeup(dip,
1278	    USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS;
1279
1280	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1281
1282	return (USB_SUCCESS);
1283}
1284
1285
1286/*
1287 * destroy PM components
1288 */
1289static void
1290uftdi_destroy_pm_components(uftdi_state_t *uf)
1291{
1292	uftdi_pm_t *pm = uf->uf_pm;
1293	dev_info_t *dip = uf->uf_dip;
1294	int rval;
1295
1296	if (!pm)
1297		return;
1298
1299	if (uf->uf_dev_state != USB_DEV_DISCONNECTED) {
1300		if (pm->pm_wakeup_enabled) {
1301			rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1302			if (rval != DDI_SUCCESS) {
1303				USB_DPRINTF_L2(DPRINT_PM, uf->uf_lh,
1304				    "uftdi_destroy_pm_components: "
1305				    "raising power failed, rval=%d", rval);
1306			}
1307			rval = usb_handle_remote_wakeup(dip,
1308			    USB_REMOTE_WAKEUP_DISABLE);
1309			if (rval != USB_SUCCESS) {
1310				USB_DPRINTF_L2(DPRINT_PM, uf->uf_lh,
1311				    "uftdi_destroy_pm_components: disable "
1312				    "remote wakeup failed, rval=%d", rval);
1313			}
1314		}
1315		(void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
1316	}
1317	kmem_free(pm, sizeof (*pm));
1318	uf->uf_pm = NULL;
1319}
1320
1321
1322/*
1323 * mark device busy and raise power
1324 */
1325static int
1326uftdi_pm_set_busy(uftdi_state_t *uf)
1327{
1328	uftdi_pm_t	*pm = uf->uf_pm;
1329	dev_info_t	*dip = uf->uf_dip;
1330	int		rval;
1331
1332	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_pm_set_busy");
1333
1334	if (!pm)
1335		return (USB_SUCCESS);
1336
1337	mutex_enter(&uf->uf_lock);
1338	/* if already marked busy, just increment the counter */
1339	if (pm->pm_busy_cnt++ > 0) {
1340		mutex_exit(&uf->uf_lock);
1341		return (USB_SUCCESS);
1342	}
1343
1344	rval = pm_busy_component(dip, 0);
1345	ASSERT(rval == DDI_SUCCESS);
1346
1347	if (pm->pm_cur_power == USB_DEV_OS_FULL_PWR) {
1348		mutex_exit(&uf->uf_lock);
1349		return (USB_SUCCESS);
1350	}
1351
1352	/* need to raise power	*/
1353	pm->pm_raise_power = B_TRUE;
1354	mutex_exit(&uf->uf_lock);
1355
1356	rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1357	if (rval != DDI_SUCCESS) {
1358		USB_DPRINTF_L2(DPRINT_PM, uf->uf_lh, "raising power failed");
1359	}
1360
1361	mutex_enter(&uf->uf_lock);
1362	pm->pm_raise_power = B_FALSE;
1363	mutex_exit(&uf->uf_lock);
1364
1365	return (USB_SUCCESS);
1366}
1367
1368
1369/*
1370 * mark device idle
1371 */
1372static void
1373uftdi_pm_set_idle(uftdi_state_t *uf)
1374{
1375	uftdi_pm_t *pm = uf->uf_pm;
1376	dev_info_t *dip = uf->uf_dip;
1377
1378	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_pm_set_idle");
1379
1380	if (!pm)
1381		return;
1382
1383	/*
1384	 * if more ports use the device, do not mark as yet
1385	 */
1386	mutex_enter(&uf->uf_lock);
1387	if (--pm->pm_busy_cnt > 0) {
1388		mutex_exit(&uf->uf_lock);
1389		return;
1390	}
1391	(void) pm_idle_component(dip, 0);
1392	mutex_exit(&uf->uf_lock);
1393}
1394
1395
1396/*
1397 * Functions to handle power transition for OS levels 0 -> 3
1398 * The same level as OS state, different from USB state
1399 */
1400static int
1401uftdi_pwrlvl0(uftdi_state_t *uf)
1402{
1403	int	rval;
1404
1405	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_pwrlvl0");
1406
1407	switch (uf->uf_dev_state) {
1408	case USB_DEV_ONLINE:
1409		/* issue USB D3 command to the device */
1410		rval = usb_set_device_pwrlvl3(uf->uf_dip);
1411		ASSERT(rval == USB_SUCCESS);
1412
1413		uf->uf_dev_state = USB_DEV_PWRED_DOWN;
1414		uf->uf_pm->pm_cur_power = USB_DEV_OS_PWR_OFF;
1415
1416		/*FALLTHROUGH*/
1417	case USB_DEV_DISCONNECTED:
1418	case USB_DEV_SUSPENDED:
1419		/* allow a disconnect/cpr'ed device to go to lower power */
1420		return (USB_SUCCESS);
1421	case USB_DEV_PWRED_DOWN:
1422	default:
1423		USB_DPRINTF_L2(DPRINT_PM, uf->uf_lh,
1424		    "uftdi_pwrlvl0: illegal device state");
1425		return (USB_FAILURE);
1426	}
1427}
1428
1429
1430static int
1431uftdi_pwrlvl1(uftdi_state_t *uf)
1432{
1433	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_pwrlvl1");
1434
1435	/* issue USB D2 command to the device */
1436	(void) usb_set_device_pwrlvl2(uf->uf_dip);
1437	return (USB_FAILURE);
1438}
1439
1440
1441static int
1442uftdi_pwrlvl2(uftdi_state_t *uf)
1443{
1444	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_pwrlvl2");
1445
1446	/* issue USB D1 command to the device */
1447	(void) usb_set_device_pwrlvl1(uf->uf_dip);
1448	return (USB_FAILURE);
1449}
1450
1451
1452static int
1453uftdi_pwrlvl3(uftdi_state_t *uf)
1454{
1455	int rval;
1456
1457	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_pwrlvl3");
1458
1459	switch (uf->uf_dev_state) {
1460	case USB_DEV_PWRED_DOWN:
1461		/* Issue USB D0 command to the device here */
1462		rval = usb_set_device_pwrlvl0(uf->uf_dip);
1463		ASSERT(rval == USB_SUCCESS);
1464
1465		uf->uf_dev_state = USB_DEV_ONLINE;
1466		uf->uf_pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
1467
1468		/*FALLTHROUGH*/
1469	case USB_DEV_ONLINE:
1470		/* we are already in full power */
1471
1472		/*FALLTHROUGH*/
1473	case USB_DEV_DISCONNECTED:
1474	case USB_DEV_SUSPENDED:
1475		return (USB_SUCCESS);
1476	default:
1477		USB_DPRINTF_L2(DPRINT_PM, uf->uf_lh,
1478		    "uftdi_pwrlvl3: illegal device state");
1479		return (USB_FAILURE);
1480	}
1481}
1482
1483
1484/*
1485 * pipe operations
1486 */
1487static int
1488uftdi_open_pipes(uftdi_state_t *uf)
1489{
1490	int ifc, alt;
1491	usb_pipe_policy_t policy;
1492	usb_ep_data_t *in_data, *out_data;
1493	size_t max_xfer_sz;
1494
1495	/* get max transfer size */
1496	if (usb_pipe_get_max_bulk_transfer_size(uf->uf_dip, &max_xfer_sz)
1497	    != USB_SUCCESS)
1498		return (USB_FAILURE);
1499
1500	/* get ep data */
1501	ifc = uf->uf_dev_data->dev_curr_if;
1502	alt = 0;
1503
1504	in_data = usb_lookup_ep_data(uf->uf_dip, uf->uf_dev_data, ifc, alt,
1505	    0, USB_EP_ATTR_BULK, USB_EP_DIR_IN);
1506
1507	out_data = usb_lookup_ep_data(uf->uf_dip, uf->uf_dev_data, ifc, alt,
1508	    0, USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
1509
1510	if (in_data == NULL || out_data == NULL) {
1511		USB_DPRINTF_L2(DPRINT_ATTACH, uf->uf_lh,
1512		    "uftdi_open_pipes: can't get ep data");
1513		return (USB_FAILURE);
1514	}
1515
1516	/*
1517	 * Set buffer sizes. Default to UFTDI_XFER_SZ_MAX.
1518	 * Use wMaxPacketSize from endpoint descriptor if it is nonzero.
1519	 * Cap at a max transfer size of host controller.
1520	 */
1521	uf->uf_ibuf_sz = uf->uf_obuf_sz = UFTDI_XFER_SZ_MAX;
1522
1523	if (in_data->ep_descr.wMaxPacketSize)
1524		uf->uf_ibuf_sz = in_data->ep_descr.wMaxPacketSize;
1525	uf->uf_ibuf_sz = min(uf->uf_ibuf_sz, max_xfer_sz);
1526
1527	if (out_data->ep_descr.wMaxPacketSize)
1528		uf->uf_obuf_sz = out_data->ep_descr.wMaxPacketSize;
1529	uf->uf_obuf_sz = min(uf->uf_obuf_sz, max_xfer_sz);
1530
1531	/* open pipes */
1532	policy.pp_max_async_reqs = 2;
1533
1534	if (usb_pipe_open(uf->uf_dip, &in_data->ep_descr, &policy,
1535	    USB_FLAGS_SLEEP, &uf->uf_bulkin_ph) != USB_SUCCESS)
1536		return (USB_FAILURE);
1537
1538	if (usb_pipe_open(uf->uf_dip, &out_data->ep_descr, &policy,
1539	    USB_FLAGS_SLEEP, &uf->uf_bulkout_ph) != USB_SUCCESS) {
1540		usb_pipe_close(uf->uf_dip, uf->uf_bulkin_ph, USB_FLAGS_SLEEP,
1541		    NULL, NULL);
1542		return (USB_FAILURE);
1543	}
1544
1545	mutex_enter(&uf->uf_lock);
1546	uf->uf_bulkin_state = UFTDI_PIPE_IDLE;
1547	uf->uf_bulkout_state = UFTDI_PIPE_IDLE;
1548	mutex_exit(&uf->uf_lock);
1549
1550	return (USB_SUCCESS);
1551}
1552
1553
1554static void
1555uftdi_close_pipes(uftdi_state_t *uf)
1556{
1557	if (uf->uf_bulkin_ph)
1558		usb_pipe_close(uf->uf_dip, uf->uf_bulkin_ph,
1559		    USB_FLAGS_SLEEP, 0, 0);
1560	if (uf->uf_bulkout_ph)
1561		usb_pipe_close(uf->uf_dip, uf->uf_bulkout_ph,
1562		    USB_FLAGS_SLEEP, 0, 0);
1563
1564	mutex_enter(&uf->uf_lock);
1565	uf->uf_bulkin_state = UFTDI_PIPE_CLOSED;
1566	uf->uf_bulkout_state = UFTDI_PIPE_CLOSED;
1567	mutex_exit(&uf->uf_lock);
1568}
1569
1570
1571static void
1572uftdi_disconnect_pipes(uftdi_state_t *uf)
1573{
1574	uftdi_close_pipes(uf);
1575}
1576
1577
1578static int
1579uftdi_reconnect_pipes(uftdi_state_t *uf)
1580{
1581	return (uftdi_open_pipes(uf));
1582}
1583
1584
1585static void
1586uftdi_rxerr_put(mblk_t **rx_mpp, mblk_t *data, uint8_t lsr)
1587{
1588	uchar_t errflg;
1589
1590	if (lsr & FTDI_LSR_STATUS_BI) {
1591		/*
1592		 * parity and framing errors only "count" if they
1593		 * occur independently of a break being received.
1594		 */
1595		lsr &= ~(uint8_t)(FTDI_LSR_STATUS_PE | FTDI_LSR_STATUS_FE);
1596	}
1597	errflg =
1598	    ((lsr & FTDI_LSR_STATUS_OE) ? DS_OVERRUN_ERR : 0) |
1599	    ((lsr & FTDI_LSR_STATUS_PE) ? DS_PARITY_ERR : 0) |
1600	    ((lsr & FTDI_LSR_STATUS_FE) ? DS_FRAMING_ERR : 0) |
1601	    ((lsr & FTDI_LSR_STATUS_BI) ? DS_BREAK_ERR : 0);
1602
1603	/*
1604	 * If there's no actual data, we send a NUL character along
1605	 * with the error flags.  Otherwise, the data mblk contains
1606	 * some number of highly questionable characters.
1607	 *
1608	 * According to FTDI tech support, there is no synchronous
1609	 * error reporting i.e. we cannot assume that only the
1610	 * first character in the mblk is bad -- so we treat all
1611	 * of them them as if they have the error noted in the LSR.
1612	 */
1613	do {
1614		mblk_t *mp;
1615		uchar_t c = (MBLKL(data) == 0) ? '\0' : *data->b_rptr++;
1616
1617		if ((mp = allocb(2, BPRI_HI)) != NULL) {
1618			DB_TYPE(mp) = M_BREAK;
1619			*mp->b_wptr++ = errflg;
1620			*mp->b_wptr++ = c;
1621			uftdi_put_tail(rx_mpp, mp);
1622		} else {
1623			/*
1624			 * low memory - just discard the bad data
1625			 */
1626			data->b_rptr = data->b_wptr;
1627			break;
1628		}
1629	} while (MBLKL(data) > 0);
1630}
1631
1632
1633/*
1634 * bulk in pipe normal and exception callback handler
1635 */
1636/*ARGSUSED*/
1637static void
1638uftdi_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
1639{
1640	uftdi_state_t *uf = (uftdi_state_t *)req->bulk_client_private;
1641	mblk_t *data;
1642	int data_len;
1643
1644	data = req->bulk_data;
1645	data_len = data ? MBLKL(data) : 0;
1646
1647	/*
1648	 * The first two bytes of data are status register bytes
1649	 * that arrive with every packet from the device.  Process
1650	 * them here before handing the rest of the data on.
1651	 *
1652	 * When active, the device will send us these bytes at least
1653	 * every 40 milliseconds, even if there's no received data.
1654	 */
1655	if (req->bulk_completion_reason == USB_CR_OK && data_len >= 2) {
1656		uint8_t msr = FTDI_GET_MSR(data->b_rptr);
1657		uint8_t lsr = FTDI_GET_LSR(data->b_rptr);
1658		int new_rx_err;
1659
1660		data->b_rptr += 2;
1661
1662		mutex_enter(&uf->uf_lock);
1663
1664		if (uf->uf_msr != msr) {
1665			/*
1666			 * modem status register changed
1667			 */
1668			USB_DPRINTF_L3(DPRINT_IN_PIPE, uf->uf_lh,
1669			    "uftdi_bulkin_cb: new msr: 0x%02x -> 0x%02x",
1670			    uf->uf_msr, msr);
1671
1672			uf->uf_msr = msr;
1673
1674			if (uf->uf_port_state == UFTDI_PORT_OPEN &&
1675			    uf->uf_cb.cb_status) {
1676				mutex_exit(&uf->uf_lock);
1677				uf->uf_cb.cb_status(uf->uf_cb.cb_arg);
1678				mutex_enter(&uf->uf_lock);
1679			}
1680		}
1681
1682		if ((uf->uf_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK)) {
1683			/*
1684			 * line status register *receive* bits changed
1685			 *
1686			 * (The THRE and TEMT (transmit) status bits are
1687			 * masked out above.)
1688			 */
1689			USB_DPRINTF_L3(DPRINT_IN_PIPE, uf->uf_lh,
1690			    "uftdi_bulkin_cb: new lsr: 0x%02x -> 0x%02x",
1691			    uf->uf_lsr, lsr);
1692			new_rx_err = B_TRUE;
1693		} else
1694			new_rx_err = B_FALSE;
1695
1696		uf->uf_lsr = lsr;	/* THRE and TEMT captured here */
1697
1698		if ((lsr & FTDI_LSR_MASK) != 0 &&
1699		    (MBLKL(data) > 0 || new_rx_err) &&
1700		    uf->uf_port_state == UFTDI_PORT_OPEN) {
1701			/*
1702			 * The current line status register value indicates
1703			 * that there's been some sort of unusual condition
1704			 * on the receive side.  We either received a break,
1705			 * or got some badly formed characters from the
1706			 * serial port - framing errors, overrun, parity etc.
1707			 * So there's either some new data to post, or a
1708			 * new error (break) to post, or both.
1709			 *
1710			 * Invoke uftdi_rxerr_put() to place the inbound
1711			 * characters as M_BREAK messages on the receive
1712			 * mblk chain, decorated with error flag(s) for
1713			 * upper-level modules (e.g. ldterm) to process.
1714			 */
1715			mutex_exit(&uf->uf_lock);
1716			uftdi_rxerr_put(&uf->uf_rx_mp, data, lsr);
1717			ASSERT(MBLKL(data) == 0);
1718
1719			/*
1720			 * Since we've converted all the received
1721			 * characters into M_BREAK messages, we
1722			 * invoke the rx callback to shove the mblks
1723			 * up the STREAM.
1724			 */
1725			if (uf->uf_cb.cb_rx)
1726				uf->uf_cb.cb_rx(uf->uf_cb.cb_arg);
1727			mutex_enter(&uf->uf_lock);
1728		}
1729
1730		mutex_exit(&uf->uf_lock);
1731		data_len = MBLKL(data);
1732	}
1733
1734	USB_DPRINTF_L4(DPRINT_IN_PIPE, uf->uf_lh, "uftdi_bulkin_cb: "
1735	    "cr=%d len=%d", req->bulk_completion_reason, data_len);
1736
1737	/* save data and notify GSD */
1738	if (data_len > 0 &&
1739	    uf->uf_port_state == UFTDI_PORT_OPEN &&
1740	    req->bulk_completion_reason == USB_CR_OK) {
1741		req->bulk_data = NULL;
1742		uftdi_put_tail(&uf->uf_rx_mp, data);
1743		if (uf->uf_cb.cb_rx)
1744			uf->uf_cb.cb_rx(uf->uf_cb.cb_arg);
1745	}
1746
1747	usb_free_bulk_req(req);
1748
1749	/* receive more */
1750	mutex_enter(&uf->uf_lock);
1751	uf->uf_bulkin_state = UFTDI_PIPE_IDLE;
1752	if (uf->uf_port_state == UFTDI_PORT_OPEN &&
1753	    uf->uf_dev_state == USB_DEV_ONLINE) {
1754		if (uftdi_rx_start(uf) != USB_SUCCESS) {
1755			USB_DPRINTF_L2(DPRINT_IN_PIPE, uf->uf_lh,
1756			    "uftdi_bulkin_cb: restart rx fail");
1757		}
1758	}
1759	mutex_exit(&uf->uf_lock);
1760}
1761
1762
1763/*
1764 * bulk out common and exception callback
1765 */
1766/*ARGSUSED*/
1767static void
1768uftdi_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
1769{
1770	uftdi_state_t	*uf = (uftdi_state_t *)req->bulk_client_private;
1771	int		data_len;
1772	mblk_t		*data = req->bulk_data;
1773
1774	data_len = data ? MBLKL(data) : 0;
1775
1776	USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh,
1777	    "uftdi_bulkout_cb: cr=%d len=%d",
1778	    req->bulk_completion_reason, data_len);
1779
1780	if (uf->uf_port_state == UFTDI_PORT_OPEN &&
1781	    req->bulk_completion_reason && data_len > 0) {
1782		uftdi_put_head(&uf->uf_tx_mp, data);
1783		req->bulk_data = NULL;
1784	}
1785
1786	usb_free_bulk_req(req);
1787
1788	/* notify GSD */
1789	if (uf->uf_cb.cb_tx)
1790		uf->uf_cb.cb_tx(uf->uf_cb.cb_arg);
1791
1792	/* send more */
1793	mutex_enter(&uf->uf_lock);
1794	uf->uf_bulkout_state = UFTDI_PIPE_IDLE;
1795	if (uf->uf_tx_mp == NULL)
1796		cv_broadcast(&uf->uf_tx_cv);
1797	else
1798		uftdi_tx_start(uf, NULL);
1799	mutex_exit(&uf->uf_lock);
1800}
1801
1802
1803/*
1804 * start receiving data
1805 */
1806static int
1807uftdi_rx_start(uftdi_state_t *uf)
1808{
1809	usb_bulk_req_t *br;
1810	int rval;
1811
1812	USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh, "uftdi_rx_start");
1813
1814	ASSERT(mutex_owned(&uf->uf_lock));
1815
1816	uf->uf_bulkin_state = UFTDI_PIPE_BUSY;
1817	mutex_exit(&uf->uf_lock);
1818
1819	br = usb_alloc_bulk_req(uf->uf_dip, uf->uf_ibuf_sz, USB_FLAGS_SLEEP);
1820	br->bulk_len = uf->uf_ibuf_sz;
1821	br->bulk_timeout = UFTDI_BULKIN_TIMEOUT;
1822	br->bulk_cb = uftdi_bulkin_cb;
1823	br->bulk_exc_cb = uftdi_bulkin_cb;
1824	br->bulk_client_private = (usb_opaque_t)uf;
1825	br->bulk_attributes = USB_ATTRS_AUTOCLEARING | USB_ATTRS_SHORT_XFER_OK;
1826
1827	rval = usb_pipe_bulk_xfer(uf->uf_bulkin_ph, br, 0);
1828
1829	if (rval != USB_SUCCESS) {
1830		USB_DPRINTF_L2(DPRINT_IN_PIPE, uf->uf_lh,
1831		    "uftdi_rx_start: xfer failed %d", rval);
1832		usb_free_bulk_req(br);
1833	}
1834
1835	mutex_enter(&uf->uf_lock);
1836	if (rval != USB_SUCCESS)
1837		uf->uf_bulkin_state = UFTDI_PIPE_IDLE;
1838
1839	return (rval);
1840}
1841
1842
1843/*
1844 * start data transmit
1845 */
1846static void
1847uftdi_tx_start(uftdi_state_t *uf, int *xferd)
1848{
1849	int		len;		/* bytes we can transmit */
1850	mblk_t		*data;		/* data to be transmitted */
1851	int		data_len;	/* bytes in 'data' */
1852	mblk_t		*mp;		/* current msgblk */
1853	int		copylen;	/* bytes copy from 'mp' to 'data' */
1854	int		rval;
1855
1856	USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh, "uftdi_tx_start");
1857	ASSERT(mutex_owned(&uf->uf_lock));
1858	ASSERT(uf->uf_port_state != UFTDI_PORT_CLOSED);
1859
1860	if (xferd)
1861		*xferd = 0;
1862	if ((uf->uf_port_flags & UFTDI_PORT_TX_STOPPED) ||
1863	    uf->uf_tx_mp == NULL) {
1864		return;
1865	}
1866	if (uf->uf_bulkout_state != UFTDI_PIPE_IDLE) {
1867		USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh,
1868		    "uftdi_tx_start: pipe busy");
1869		return;
1870	}
1871	ASSERT(MBLKL(uf->uf_tx_mp) > 0);
1872
1873	/* send as much data as port can receive */
1874	len = min(msgdsize(uf->uf_tx_mp), uf->uf_obuf_sz);
1875
1876	if (len <= 0)
1877		return;
1878	if ((data = allocb(len, BPRI_LO)) == NULL)
1879		return;
1880
1881	/*
1882	 * copy no more than 'len' bytes from mblk chain to transmit mblk 'data'
1883	 */
1884	data_len = 0;
1885	while (data_len < len && uf->uf_tx_mp) {
1886		mp = uf->uf_tx_mp;
1887		copylen = min(MBLKL(mp), len - data_len);
1888		bcopy(mp->b_rptr, data->b_wptr, copylen);
1889		mp->b_rptr += copylen;
1890		data->b_wptr += copylen;
1891		data_len += copylen;
1892
1893		if (MBLKL(mp) < 1) {
1894			uf->uf_tx_mp = unlinkb(mp);
1895			freeb(mp);
1896		} else {
1897			ASSERT(data_len == len);
1898		}
1899	}
1900
1901	ASSERT(data_len > 0);
1902
1903	uf->uf_bulkout_state = UFTDI_PIPE_BUSY;
1904	mutex_exit(&uf->uf_lock);
1905
1906	rval = uftdi_send_data(uf, data);
1907	mutex_enter(&uf->uf_lock);
1908
1909	if (rval != USB_SUCCESS) {
1910		uf->uf_bulkout_state = UFTDI_PIPE_IDLE;
1911		uftdi_put_head(&uf->uf_tx_mp, data);
1912	} else {
1913		if (xferd)
1914			*xferd = data_len;
1915	}
1916}
1917
1918
1919static int
1920uftdi_send_data(uftdi_state_t *uf, mblk_t *data)
1921{
1922	usb_bulk_req_t *br;
1923	int len = MBLKL(data);
1924	int rval;
1925
1926	USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh,
1927	    "uftdi_send_data: %d 0x%x 0x%x 0x%x", len, data->b_rptr[0],
1928	    (len > 1) ? data->b_rptr[1] : 0, (len > 2) ? data->b_rptr[2] : 0);
1929
1930	ASSERT(!mutex_owned(&uf->uf_lock));
1931
1932	br = usb_alloc_bulk_req(uf->uf_dip, 0, USB_FLAGS_SLEEP);
1933	br->bulk_data = data;
1934	br->bulk_len = len;
1935	br->bulk_timeout = UFTDI_BULKOUT_TIMEOUT;
1936	br->bulk_cb = uftdi_bulkout_cb;
1937	br->bulk_exc_cb = uftdi_bulkout_cb;
1938	br->bulk_client_private = (usb_opaque_t)uf;
1939	br->bulk_attributes = USB_ATTRS_AUTOCLEARING;
1940
1941	rval = usb_pipe_bulk_xfer(uf->uf_bulkout_ph, br, 0);
1942
1943	if (rval != USB_SUCCESS) {
1944		USB_DPRINTF_L2(DPRINT_OUT_PIPE, uf->uf_lh,
1945		    "uftdi_send_data: xfer failed %d", rval);
1946		br->bulk_data = NULL;
1947		usb_free_bulk_req(br);
1948	}
1949
1950	return (rval);
1951}
1952
1953
1954/*
1955 * wait until local tx buffer drains.
1956 * 'timeout' is in seconds, zero means wait forever
1957 */
1958static int
1959uftdi_wait_tx_drain(uftdi_state_t *uf, int timeout)
1960{
1961	clock_t	until;
1962	int over = 0;
1963
1964	until = ddi_get_lbolt() + drv_usectohz(1000 * 1000 * timeout);
1965
1966	while (uf->uf_tx_mp && !over) {
1967		if (timeout > 0) {
1968			/* whether timedout or signal pending */
1969			over = cv_timedwait_sig(&uf->uf_tx_cv,
1970			    &uf->uf_lock, until) <= 0;
1971		} else {
1972			/* whether a signal is pending */
1973			over = cv_wait_sig(&uf->uf_tx_cv,
1974			    &uf->uf_lock) == 0;
1975		}
1976	}
1977
1978	return (uf->uf_tx_mp == NULL ? USB_SUCCESS : USB_FAILURE);
1979}
1980
1981/*
1982 * initialize hardware serial port
1983 */
1984static int
1985uftdi_open_hw_port(uftdi_state_t *uf, int dorestore)
1986{
1987	int rval;
1988
1989	/*
1990	 * Perform a full reset on the device
1991	 */
1992	rval = uftdi_cmd_vendor_write0(uf,
1993	    FTDI_SIO_RESET, FTDI_SIO_RESET_SIO, uf->uf_hwport);
1994	if (rval != USB_SUCCESS) {
1995		USB_DPRINTF_L2(DPRINT_DEF_PIPE, uf->uf_lh,
1996		    "uftdi_open_hw_port: failed to reset!");
1997		return (rval);
1998	}
1999
2000	if (dorestore) {
2001		/*
2002		 * Restore settings from our soft copy of HW registers
2003		 */
2004		(void) uftdi_setregs(uf, NULL);
2005	} else {
2006		/*
2007		 * 9600 baud, 2 stop bits, no parity, 8-bit, h/w flow control
2008		 */
2009		static ds_port_param_entry_t ents[] = {
2010#if defined(__lock_lint)
2011			/*
2012			 * (Sigh - wlcc doesn't understand this newer
2013			 * form of structure member initialization.)
2014			 */
2015			{ 0 }
2016#else
2017			{ DS_PARAM_BAUD,	.val.ui = B9600 },
2018			{ DS_PARAM_STOPB,	.val.ui = CSTOPB },
2019			{ DS_PARAM_PARITY,	.val.ui = 0 },
2020			{ DS_PARAM_CHARSZ,	.val.ui = CS8 },
2021			{ DS_PARAM_FLOW_CTL,	.val.ui = CTSXON }
2022#endif
2023		};
2024		static ds_port_params_t params = {
2025			ents,
2026			sizeof (ents) / sizeof (ents[0])
2027		};
2028
2029		rval = uftdi_set_port_params(uf, 0, &params);
2030		if (rval != USB_SUCCESS) {
2031			USB_DPRINTF_L2(DPRINT_DEF_PIPE, uf->uf_lh,
2032			    "uftdi_open_hw_port: failed 9600/2/n/8 rval %d",
2033			    rval);
2034		}
2035	}
2036
2037	return (rval);
2038}
2039
2040static int
2041uftdi_cmd_vendor_write0(uftdi_state_t *uf,
2042    uint16_t reqno, uint16_t val, uint16_t idx)
2043{
2044	usb_ctrl_setup_t req;
2045	usb_cb_flags_t cb_flags;
2046	usb_cr_t cr;
2047	int rval;
2048
2049	ASSERT(!mutex_owned(&uf->uf_lock));
2050
2051	req.bmRequestType =
2052	    USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_HOST_TO_DEV;
2053	req.bRequest = (uchar_t)reqno;
2054	req.wValue = val;
2055	req.wIndex = idx;
2056	req.wLength = 0;
2057	req.attrs = USB_ATTRS_NONE;
2058
2059	if ((rval = usb_pipe_ctrl_xfer_wait(uf->uf_def_ph,
2060	    &req, NULL, &cr, &cb_flags, 0)) != USB_SUCCESS) {
2061		USB_DPRINTF_L2(DPRINT_DEF_PIPE, uf->uf_lh,
2062		    "uftdi_cmd_vendor_write0: 0x%x 0x%x 0x%x failed %d %d 0x%x",
2063		    reqno, val, idx, rval, cr, cb_flags);
2064	}
2065
2066	return (rval);
2067}
2068
2069/*
2070 * misc routines
2071 */
2072
2073/*
2074 * link a message block to tail of message
2075 * account for the case when message is null
2076 */
2077static void
2078uftdi_put_tail(mblk_t **mpp, mblk_t *bp)
2079{
2080	if (*mpp)
2081		linkb(*mpp, bp);
2082	else
2083		*mpp = bp;
2084}
2085
2086/*
2087 * put a message block at the head of the message
2088 * account for the case when message is null
2089 */
2090static void
2091uftdi_put_head(mblk_t **mpp, mblk_t *bp)
2092{
2093	if (*mpp)
2094		linkb(bp, *mpp);
2095	*mpp = bp;
2096}
2097
2098/*ARGSUSED*/
2099static usb_pipe_handle_t
2100uftdi_out_pipe(ds_hdl_t hdl, uint_t portno)
2101{
2102	ASSERT(portno == 0);
2103
2104	return (((uftdi_state_t *)hdl)->uf_bulkout_ph);
2105}
2106
2107/*ARGSUSED*/
2108static usb_pipe_handle_t
2109uftdi_in_pipe(ds_hdl_t hdl, uint_t portno)
2110{
2111	ASSERT(portno == 0);
2112
2113	return (((uftdi_state_t *)hdl)->uf_bulkin_ph);
2114}
2115