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