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