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