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