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 2007 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 break; 520 default: 521 ASSERT(0); /* cannot happen */ 522 } 523 524 *new_state = plp->pl_dev_state; 525 mutex_exit(&plp->pl_mutex); 526 527 return (rval); 528 } 529 530 531 /* 532 * ds_suspend 533 */ 534 static int 535 pl2303_suspend(ds_hdl_t hdl) 536 { 537 pl2303_state_t *plp = (pl2303_state_t *)hdl; 538 int state; 539 540 USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_suspend"); 541 542 mutex_enter(&plp->pl_mutex); 543 state = plp->pl_dev_state = USB_DEV_SUSPENDED; 544 mutex_exit(&plp->pl_mutex); 545 546 pl2303_disconnect_pipes(plp); 547 548 return (state); 549 } 550 551 552 /* 553 * ds_resume 554 */ 555 static int 556 pl2303_resume(ds_hdl_t hdl) 557 { 558 pl2303_state_t *plp = (pl2303_state_t *)hdl; 559 int current_state; 560 int rval; 561 562 USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_resume"); 563 564 (void) pm_busy_component(plp->pl_dip, 0); 565 (void) pm_raise_power(plp->pl_dip, 0, USB_DEV_OS_FULL_PWR); 566 567 mutex_enter(&plp->pl_mutex); 568 current_state = plp->pl_dev_state; 569 mutex_exit(&plp->pl_mutex); 570 571 if (current_state != USB_DEV_ONLINE) { 572 rval = pl2303_restore_device_state(plp); 573 } else { 574 rval = USB_SUCCESS; 575 } 576 577 (void) pm_idle_component(plp->pl_dip, 0); 578 579 return (rval); 580 } 581 582 583 /* 584 * ds_disconnect 585 */ 586 static int 587 pl2303_disconnect(ds_hdl_t hdl) 588 { 589 pl2303_state_t *plp = (pl2303_state_t *)hdl; 590 int state; 591 592 USB_DPRINTF_L4(DPRINT_HOTPLUG, plp->pl_lh, "pl2303_disconnect"); 593 594 mutex_enter(&plp->pl_mutex); 595 state = plp->pl_dev_state = USB_DEV_DISCONNECTED; 596 mutex_exit(&plp->pl_mutex); 597 598 pl2303_disconnect_pipes(plp); 599 600 return (state); 601 } 602 603 604 /* 605 * ds_reconnect 606 */ 607 static int 608 pl2303_reconnect(ds_hdl_t hdl) 609 { 610 pl2303_state_t *plp = (pl2303_state_t *)hdl; 611 612 USB_DPRINTF_L4(DPRINT_HOTPLUG, plp->pl_lh, "pl2303_reconnect"); 613 614 return (pl2303_restore_device_state(plp)); 615 } 616 617 618 /* 619 * standard UART operations 620 * ------------------------ 621 * 622 * 623 * ds_set_port_params 624 */ 625 /*ARGSUSED*/ 626 static int 627 pl2303_set_port_params(ds_hdl_t hdl, uint_t port_num, ds_port_params_t *tp) 628 { 629 pl2303_state_t *plp = (pl2303_state_t *)hdl; 630 int rval = USB_FAILURE; 631 mblk_t *bp; 632 int i; 633 uint_t ui; 634 int baud; 635 int cnt; 636 ds_port_param_entry_t *pe; 637 uint16_t xonxoff_symbol; 638 uint8_t xon_char; 639 uint8_t xoff_char; 640 641 if (tp == NULL) { 642 643 return (rval); 644 } 645 646 cnt = tp->tp_cnt; 647 pe = tp->tp_entries; 648 649 USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_set_port_params"); 650 651 /* 652 * get Line Coding Structure Request 653 * including: baud rate, stop bit, parity type and data bit 654 */ 655 if ((rval = pl2303_cmd_get_line(plp, &bp)) != USB_SUCCESS) { 656 657 return (rval); 658 } 659 660 /* translate parameters into device-specific bits */ 661 for (i = 0; i < cnt; i++, pe++) { 662 switch (pe->param) { 663 case DS_PARAM_BAUD: 664 ui = pe->val.ui; 665 666 /* if we don't support this speed, return USB_FAILURE */ 667 if ((ui >= NELEM(pl2303_speedtab)) || 668 ((ui > 0) && (pl2303_speedtab[ui] == 0))) { 669 USB_DPRINTF_L3(DPRINT_CTLOP, plp->pl_lh, 670 "pl2303_set_port_params: bad baud %d", ui); 671 672 freeb(bp); 673 674 return (USB_FAILURE); 675 } 676 677 baud = pl2303_speedtab[ui]; 678 bp->b_rptr[0] = baud & 0xff; 679 bp->b_rptr[1] = (baud >> 8) & 0xff; 680 bp->b_rptr[2] = (baud >> 16) & 0xff; 681 bp->b_rptr[3] = (baud >> 24) & 0xff; 682 683 break; 684 case DS_PARAM_PARITY: 685 if (pe->val.ui & PARENB) { 686 if (pe->val.ui & PARODD) { 687 bp->b_rptr[5] = 1; 688 } else { 689 bp->b_rptr[5] = 2; 690 } 691 } else { 692 bp->b_rptr[5] = 0; 693 } 694 695 break; 696 case DS_PARAM_STOPB: 697 if (pe->val.ui & CSTOPB) { 698 bp->b_rptr[4] = 2; 699 } else { 700 bp->b_rptr[4] = 0; 701 } 702 703 break; 704 case DS_PARAM_CHARSZ: 705 switch (pe->val.ui) { 706 case CS5: 707 bp->b_rptr[6] = 5; 708 709 break; 710 case CS6: 711 bp->b_rptr[6] = 6; 712 713 break; 714 case CS7: 715 bp->b_rptr[6] = 7; 716 717 break; 718 case CS8: 719 default: 720 bp->b_rptr[6] = 8; 721 722 break; 723 } 724 725 break; 726 case DS_PARAM_XON_XOFF: 727 /* 728 * Software flow control: XON/XOFF 729 * not supported by PL-2303H, HX chips 730 */ 731 if (pe->val.ui & IXON || pe->val.ui & IXOFF) { 732 /* not supported by PL-2303H chip */ 733 switch (plp->pl_chiptype) { 734 case pl2303_H: 735 736 break; 737 case pl2303_X: 738 case pl2303_HX_CHIP_D: 739 xon_char = pe->val.uc[0]; 740 xoff_char = pe->val.uc[1]; 741 xonxoff_symbol = (xoff_char << 8) 742 | xon_char; 743 744 rval = pl2303_cmd_vendor_write0( 745 plp, SET_XONXOFF, 746 xonxoff_symbol); 747 748 if (rval != USB_SUCCESS) { 749 USB_DPRINTF_L3(DPRINT_CTLOP, 750 plp->pl_lh, 751 "pl2303_set_port_params: " 752 "set XonXoff failed"); 753 } 754 755 break; 756 case pl2303_UNKNOWN: 757 default: 758 759 break; 760 } 761 } 762 763 break; 764 case DS_PARAM_FLOW_CTL: 765 /* Hardware flow control */ 766 if (pe->val.ui & CTSXON) { 767 if ((rval = pl2303_cmd_set_rtscts(plp)) 768 != USB_SUCCESS) { 769 770 USB_DPRINTF_L3(DPRINT_CTLOP, 771 plp->pl_lh, 772 "pl2303_set_port_params: " 773 "pl2303_cmd_set_rtscts failed"); 774 } 775 } 776 777 break; 778 default: 779 USB_DPRINTF_L2(DPRINT_CTLOP, plp->pl_lh, 780 "pl2303_set_port_params: bad param %d", pe->param); 781 782 break; 783 } 784 } 785 786 /* set new values for Line Coding Structure */ 787 rval = pl2303_cmd_set_line(plp, bp); 788 789 freeb(bp); 790 791 if (rval != USB_SUCCESS) { 792 793 return (rval); 794 } 795 796 /* hardware need to get Line Coding Structure again */ 797 if ((rval = pl2303_cmd_get_line(plp, &bp)) != USB_SUCCESS) { 798 799 return (rval); 800 } 801 802 freeb(bp); 803 804 return (USB_SUCCESS); 805 } 806 807 808 /* 809 * ds_set_modem_ctl 810 */ 811 /*ARGSUSED*/ 812 static int 813 pl2303_set_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int val) 814 { 815 pl2303_state_t *plp = (pl2303_state_t *)hdl; 816 int rval = USB_FAILURE; 817 uint8_t new_mctl; 818 819 USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_set_modem_ctl"); 820 821 mutex_enter(&plp->pl_mutex); 822 new_mctl = plp->pl_mctl; 823 mutex_exit(&plp->pl_mutex); 824 825 /* set RTS and DTR */ 826 pl2303_mctl2reg(mask, val, &new_mctl); 827 828 if ((rval = pl2303_cmd_set_ctl(plp, new_mctl)) == USB_SUCCESS) { 829 mutex_enter(&plp->pl_mutex); 830 plp->pl_mctl = new_mctl; 831 mutex_exit(&plp->pl_mutex); 832 } 833 834 return (rval); 835 } 836 837 838 /* 839 * ds_get_modem_ctl 840 */ 841 /*ARGSUSED*/ 842 static int 843 pl2303_get_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int *valp) 844 { 845 pl2303_state_t *plp = (pl2303_state_t *)hdl; 846 847 USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_get_modem_ctl"); 848 849 mutex_enter(&plp->pl_mutex); 850 851 /* get RTS and DTR */ 852 *valp = pl2303_reg2mctl(plp->pl_mctl) & mask; 853 *valp |= (mask & (TIOCM_CD | TIOCM_CTS | TIOCM_DSR | TIOCM_RI)); 854 mutex_exit(&plp->pl_mutex); 855 856 return (USB_SUCCESS); 857 } 858 859 860 /* 861 * ds_break_ctl 862 */ 863 /*ARGSUSED*/ 864 static int 865 pl2303_break_ctl(ds_hdl_t hdl, uint_t port_num, int ctl) 866 { 867 pl2303_state_t *plp = (pl2303_state_t *)hdl; 868 869 USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_break_ctl"); 870 871 return (pl2303_cmd_break(plp, ctl)); 872 } 873 874 875 /* 876 * ds_tx 877 */ 878 /*ARGSUSED*/ 879 static int 880 pl2303_tx(ds_hdl_t hdl, uint_t port_num, mblk_t *mp) 881 { 882 pl2303_state_t *plp = (pl2303_state_t *)hdl; 883 int xferd; 884 885 USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_tx"); 886 887 /* 888 * sanity checks 889 */ 890 if (mp == NULL) { 891 USB_DPRINTF_L3(DPRINT_CTLOP, plp->pl_lh, "pl2303_tx: mp=NULL"); 892 893 return (USB_SUCCESS); 894 } 895 if (MBLKL(mp) <= 0) { 896 USB_DPRINTF_L3(DPRINT_CTLOP, plp->pl_lh, "pl2303_tx: len<=0"); 897 freemsg(mp); 898 899 return (USB_SUCCESS); 900 } 901 902 mutex_enter(&plp->pl_mutex); 903 904 pl2303_put_tail(&plp->pl_tx_mp, mp); /* add to the chain */ 905 906 pl2303_tx_start(plp, &xferd); 907 908 mutex_exit(&plp->pl_mutex); 909 910 return (USB_SUCCESS); 911 } 912 913 914 /* 915 * ds_rx 916 * the real data receiving is in pl2303_open_port 917 */ 918 /*ARGSUSED*/ 919 static mblk_t * 920 pl2303_rx(ds_hdl_t hdl, uint_t port_num) 921 { 922 pl2303_state_t *plp = (pl2303_state_t *)hdl; 923 mblk_t *mp; 924 925 USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_rx"); 926 927 mutex_enter(&plp->pl_mutex); 928 mp = plp->pl_rx_mp; 929 plp->pl_rx_mp = NULL; 930 mutex_exit(&plp->pl_mutex); 931 932 return (mp); 933 } 934 935 936 /* 937 * ds_stop 938 */ 939 /*ARGSUSED*/ 940 static void 941 pl2303_stop(ds_hdl_t hdl, uint_t port_num, int dir) 942 { 943 pl2303_state_t *plp = (pl2303_state_t *)hdl; 944 945 USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_stop"); 946 947 if (dir & DS_TX) { 948 mutex_enter(&plp->pl_mutex); 949 plp->pl_port_flags |= PL2303_PORT_TX_STOPPED; 950 mutex_exit(&plp->pl_mutex); 951 } 952 } 953 954 955 /* 956 * ds_start 957 */ 958 /*ARGSUSED*/ 959 static void 960 pl2303_start(ds_hdl_t hdl, uint_t port_num, int dir) 961 { 962 pl2303_state_t *plp = (pl2303_state_t *)hdl; 963 964 USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_start"); 965 966 if (dir & DS_TX) { 967 mutex_enter(&plp->pl_mutex); 968 if (plp->pl_port_flags & PL2303_PORT_TX_STOPPED) { 969 plp->pl_port_flags &= ~PL2303_PORT_TX_STOPPED; 970 pl2303_tx_start(plp, NULL); 971 } 972 mutex_exit(&plp->pl_mutex); 973 } 974 } 975 976 977 /* 978 * ds_fifo_flush 979 */ 980 /*ARGSUSED*/ 981 static int 982 pl2303_fifo_flush(ds_hdl_t hdl, uint_t port_num, int dir) 983 { 984 pl2303_state_t *plp = (pl2303_state_t *)hdl; 985 986 USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_fifo_flush: dir=%x", 987 dir); 988 989 mutex_enter(&plp->pl_mutex); 990 ASSERT(plp->pl_port_state == PL2303_PORT_OPEN); 991 992 if ((dir & DS_TX) && plp->pl_tx_mp) { 993 freemsg(plp->pl_tx_mp); 994 plp->pl_tx_mp = NULL; 995 } 996 if ((dir & DS_RX) && plp->pl_rx_mp) { 997 freemsg(plp->pl_rx_mp); 998 plp->pl_rx_mp = NULL; 999 } 1000 mutex_exit(&plp->pl_mutex); 1001 1002 return (USB_SUCCESS); 1003 } 1004 1005 1006 /* 1007 * ds_fifo_drain 1008 */ 1009 /*ARGSUSED*/ 1010 static int 1011 pl2303_fifo_drain(ds_hdl_t hdl, uint_t port_num, int timeout) 1012 { 1013 pl2303_state_t *plp = (pl2303_state_t *)hdl; 1014 int rval = USB_SUCCESS; 1015 1016 USB_DPRINTF_L4(DPRINT_CTLOP, plp->pl_lh, "pl2303_fifo_drain"); 1017 1018 mutex_enter(&plp->pl_mutex); 1019 ASSERT(plp->pl_port_state == PL2303_PORT_OPEN); 1020 1021 /* 1022 * for the reason of hardware, set timeout 0 1023 */ 1024 if (pl2303_wait_tx_drain(plp, 0) != USB_SUCCESS) { 1025 1026 mutex_exit(&plp->pl_mutex); 1027 1028 return (USB_FAILURE); 1029 } 1030 1031 mutex_exit(&plp->pl_mutex); 1032 1033 /* wait 500 ms until hw fifo drains */ 1034 delay(drv_usectohz(500*1000)); 1035 1036 return (rval); 1037 } 1038 1039 1040 /* 1041 * configuration routines 1042 * ---------------------- 1043 * 1044 * clean up routine 1045 */ 1046 static void 1047 pl2303_cleanup(pl2303_state_t *plp, int level) 1048 { 1049 ASSERT((level > 0) && (level <= PL2303_CLEANUP_LEVEL_MAX)); 1050 1051 switch (level) { 1052 default: 1053 pl2303_close_pipes(plp); 1054 /* FALLTHRU */ 1055 case 5: 1056 usb_unregister_event_cbs(plp->pl_dip, plp->pl_usb_events); 1057 /* FALLTHRU */ 1058 case 4: 1059 pl2303_destroy_pm_components(plp); 1060 /* FALLTHRU */ 1061 case 3: 1062 mutex_destroy(&plp->pl_mutex); 1063 cv_destroy(&plp->pl_tx_cv); 1064 1065 usb_free_log_hdl(plp->pl_lh); 1066 plp->pl_lh = NULL; 1067 1068 usb_free_descr_tree(plp->pl_dip, plp->pl_dev_data); 1069 plp->pl_def_ph = NULL; 1070 /* FALLTHRU */ 1071 case 2: 1072 usb_client_detach(plp->pl_dip, plp->pl_dev_data); 1073 /* FALLTHRU */ 1074 case 1: 1075 kmem_free(plp, sizeof (pl2303_state_t)); 1076 } 1077 } 1078 1079 1080 /* 1081 * device specific attach 1082 */ 1083 static int 1084 pl2303_dev_attach(pl2303_state_t *plp) 1085 { 1086 if (pl2303_open_pipes(plp) != USB_SUCCESS) { 1087 return (USB_FAILURE); 1088 } 1089 1090 return (USB_SUCCESS); 1091 } 1092 1093 1094 /* 1095 * hotplug 1096 * ------- 1097 * 1098 * 1099 * restore device state after CPR resume or reconnect 1100 */ 1101 static int 1102 pl2303_restore_device_state(pl2303_state_t *plp) 1103 { 1104 int state; 1105 1106 mutex_enter(&plp->pl_mutex); 1107 state = plp->pl_dev_state; 1108 mutex_exit(&plp->pl_mutex); 1109 1110 if ((state != USB_DEV_DISCONNECTED) && (state != USB_DEV_SUSPENDED)) { 1111 1112 return (state); 1113 } 1114 1115 if (usb_check_same_device(plp->pl_dip, plp->pl_lh, USB_LOG_L0, 1116 DPRINT_MASK_ALL, USB_CHK_ALL, NULL) != USB_SUCCESS) { 1117 mutex_enter(&plp->pl_mutex); 1118 state = plp->pl_dev_state = USB_DEV_DISCONNECTED; 1119 mutex_exit(&plp->pl_mutex); 1120 1121 return (state); 1122 } 1123 1124 if (state == USB_DEV_DISCONNECTED) { 1125 USB_DPRINTF_L0(DPRINT_HOTPLUG, plp->pl_lh, 1126 "Device has been reconnected but data may have been lost"); 1127 } 1128 1129 if (pl2303_reconnect_pipes(plp) != USB_SUCCESS) { 1130 1131 return (state); 1132 } 1133 1134 /* 1135 * init device state 1136 */ 1137 mutex_enter(&plp->pl_mutex); 1138 state = plp->pl_dev_state = USB_DEV_ONLINE; 1139 mutex_exit(&plp->pl_mutex); 1140 1141 if ((pl2303_restore_port_state(plp) != USB_SUCCESS)) { 1142 USB_DPRINTF_L2(DPRINT_HOTPLUG, plp->pl_lh, 1143 "pl2303_restore_device_state: failed"); 1144 } 1145 1146 return (state); 1147 } 1148 1149 1150 /* 1151 * restore ports state after CPR resume or reconnect 1152 */ 1153 static int 1154 pl2303_restore_port_state(pl2303_state_t *plp) 1155 { 1156 int rval; 1157 1158 mutex_enter(&plp->pl_mutex); 1159 if (plp->pl_port_state != PL2303_PORT_OPEN) { 1160 mutex_exit(&plp->pl_mutex); 1161 1162 return (USB_SUCCESS); 1163 } 1164 mutex_exit(&plp->pl_mutex); 1165 1166 /* open hardware serial port */ 1167 if ((rval = pl2303_open_hw_port(plp)) != USB_SUCCESS) { 1168 USB_DPRINTF_L2(DPRINT_HOTPLUG, plp->pl_lh, 1169 "pl2303_restore_ports_state: failed"); 1170 } 1171 1172 return (rval); 1173 } 1174 1175 1176 /* 1177 * power management 1178 * ---------------- 1179 * 1180 * 1181 * create PM components 1182 */ 1183 static int 1184 pl2303_create_pm_components(pl2303_state_t *plp) 1185 { 1186 dev_info_t *dip = plp->pl_dip; 1187 pl2303_pm_t *pm; 1188 uint_t pwr_states; 1189 1190 if (usb_create_pm_components(dip, &pwr_states) != USB_SUCCESS) { 1191 USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh, 1192 "pl2303_create_pm_components: failed"); 1193 1194 return (USB_SUCCESS); 1195 } 1196 1197 pm = plp->pl_pm = kmem_zalloc(sizeof (pl2303_pm_t), KM_SLEEP); 1198 1199 pm->pm_pwr_states = (uint8_t)pwr_states; 1200 pm->pm_cur_power = USB_DEV_OS_FULL_PWR; 1201 pm->pm_wakeup_enabled = (usb_handle_remote_wakeup(dip, 1202 USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS); 1203 1204 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 1205 1206 return (USB_SUCCESS); 1207 } 1208 1209 1210 /* 1211 * destroy PM components 1212 */ 1213 static void 1214 pl2303_destroy_pm_components(pl2303_state_t *plp) 1215 { 1216 pl2303_pm_t *pm = plp->pl_pm; 1217 dev_info_t *dip = plp->pl_dip; 1218 int rval; 1219 1220 if (!pm) 1221 1222 return; 1223 1224 if (plp->pl_dev_state != USB_DEV_DISCONNECTED) { 1225 if (pm->pm_wakeup_enabled) { 1226 rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 1227 if (rval != DDI_SUCCESS) { 1228 USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh, 1229 "pl2303_destroy_pm_components:" 1230 "raising power failed, rval=%d", rval); 1231 } 1232 1233 rval = usb_handle_remote_wakeup(dip, 1234 USB_REMOTE_WAKEUP_DISABLE); 1235 if (rval != USB_SUCCESS) { 1236 USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh, 1237 "pl2303_destroy_pm_components: disable " 1238 "remote wakeup failed, rval=%d", rval); 1239 } 1240 } 1241 1242 (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF); 1243 } 1244 kmem_free(pm, sizeof (pl2303_pm_t)); 1245 plp->pl_pm = NULL; 1246 } 1247 1248 1249 /* 1250 * mark device busy and raise power 1251 */ 1252 static int 1253 pl2303_pm_set_busy(pl2303_state_t *plp) 1254 { 1255 pl2303_pm_t *pm = plp->pl_pm; 1256 dev_info_t *dip = plp->pl_dip; 1257 int rval; 1258 1259 USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pm_set_busy"); 1260 1261 if (!pm) { 1262 1263 return (USB_SUCCESS); 1264 } 1265 1266 mutex_enter(&plp->pl_mutex); 1267 /* if already marked busy, just increment the counter */ 1268 if (pm->pm_busy_cnt++ > 0) { 1269 mutex_exit(&plp->pl_mutex); 1270 1271 return (USB_SUCCESS); 1272 } 1273 1274 rval = pm_busy_component(dip, 0); 1275 ASSERT(rval == DDI_SUCCESS); 1276 1277 if (pm->pm_cur_power == USB_DEV_OS_FULL_PWR) { 1278 mutex_exit(&plp->pl_mutex); 1279 1280 return (USB_SUCCESS); 1281 } 1282 1283 /* need to raise power */ 1284 pm->pm_raise_power = B_TRUE; 1285 mutex_exit(&plp->pl_mutex); 1286 1287 rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 1288 if (rval != DDI_SUCCESS) { 1289 USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh, "raising power failed"); 1290 } 1291 1292 mutex_enter(&plp->pl_mutex); 1293 pm->pm_raise_power = B_FALSE; 1294 mutex_exit(&plp->pl_mutex); 1295 1296 return (USB_SUCCESS); 1297 } 1298 1299 1300 /* 1301 * mark device idle 1302 */ 1303 static void 1304 pl2303_pm_set_idle(pl2303_state_t *plp) 1305 { 1306 pl2303_pm_t *pm = plp->pl_pm; 1307 dev_info_t *dip = plp->pl_dip; 1308 1309 USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pm_set_idle"); 1310 1311 if (!pm) { 1312 1313 return; 1314 } 1315 1316 /* 1317 * if more ports use the device, do not mark as yet 1318 */ 1319 mutex_enter(&plp->pl_mutex); 1320 if (--pm->pm_busy_cnt > 0) { 1321 mutex_exit(&plp->pl_mutex); 1322 1323 return; 1324 } 1325 1326 if (pm) { 1327 (void) pm_idle_component(dip, 0); 1328 } 1329 mutex_exit(&plp->pl_mutex); 1330 } 1331 1332 1333 /* 1334 * Functions to handle power transition for OS levels 0 -> 3 1335 * The same level as OS state, different from USB state 1336 */ 1337 static int 1338 pl2303_pwrlvl0(pl2303_state_t *plp) 1339 { 1340 int rval; 1341 1342 USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pwrlvl0"); 1343 1344 switch (plp->pl_dev_state) { 1345 case USB_DEV_ONLINE: 1346 /* issue USB D3 command to the device */ 1347 rval = usb_set_device_pwrlvl3(plp->pl_dip); 1348 ASSERT(rval == USB_SUCCESS); 1349 1350 plp->pl_dev_state = USB_DEV_PWRED_DOWN; 1351 plp->pl_pm->pm_cur_power = USB_DEV_OS_PWR_OFF; 1352 1353 /* FALLTHRU */ 1354 case USB_DEV_DISCONNECTED: 1355 case USB_DEV_SUSPENDED: 1356 /* allow a disconnect/cpr'ed device to go to lower power */ 1357 1358 return (USB_SUCCESS); 1359 case USB_DEV_PWRED_DOWN: 1360 default: 1361 USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh, 1362 "pl2303_pwrlvl0: illegal device state"); 1363 1364 return (USB_FAILURE); 1365 } 1366 } 1367 1368 1369 static int 1370 pl2303_pwrlvl1(pl2303_state_t *plp) 1371 { 1372 USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pwrlvl1"); 1373 1374 /* issue USB D2 command to the device */ 1375 (void) usb_set_device_pwrlvl2(plp->pl_dip); 1376 1377 return (USB_FAILURE); 1378 } 1379 1380 1381 static int 1382 pl2303_pwrlvl2(pl2303_state_t *plp) 1383 { 1384 USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pwrlvl2"); 1385 1386 /* issue USB D1 command to the device */ 1387 (void) usb_set_device_pwrlvl1(plp->pl_dip); 1388 1389 return (USB_FAILURE); 1390 } 1391 1392 1393 static int 1394 pl2303_pwrlvl3(pl2303_state_t *plp) 1395 { 1396 int rval; 1397 1398 USB_DPRINTF_L4(DPRINT_PM, plp->pl_lh, "pl2303_pwrlvl3"); 1399 1400 switch (plp->pl_dev_state) { 1401 case USB_DEV_PWRED_DOWN: 1402 /* Issue USB D0 command to the device here */ 1403 rval = usb_set_device_pwrlvl0(plp->pl_dip); 1404 ASSERT(rval == USB_SUCCESS); 1405 1406 plp->pl_dev_state = USB_DEV_ONLINE; 1407 plp->pl_pm->pm_cur_power = USB_DEV_OS_FULL_PWR; 1408 1409 /* FALLTHRU */ 1410 case USB_DEV_ONLINE: 1411 /* we are already in full power */ 1412 1413 /* FALLTHRU */ 1414 case USB_DEV_DISCONNECTED: 1415 case USB_DEV_SUSPENDED: 1416 1417 return (USB_SUCCESS); 1418 default: 1419 USB_DPRINTF_L2(DPRINT_PM, plp->pl_lh, 1420 "pl2303_pwrlvl3: illegal device state"); 1421 1422 return (USB_FAILURE); 1423 } 1424 } 1425 1426 1427 /* 1428 * pipe operations 1429 * --------------- 1430 * 1431 * 1432 */ 1433 static int 1434 pl2303_open_pipes(pl2303_state_t *plp) 1435 { 1436 int ifc, alt; 1437 usb_pipe_policy_t policy; 1438 usb_ep_data_t *in_data, *out_data; 1439 1440 /* get ep data */ 1441 ifc = plp->pl_dev_data->dev_curr_if; 1442 alt = 0; 1443 1444 in_data = usb_lookup_ep_data(plp->pl_dip, plp->pl_dev_data, ifc, alt, 1445 0, USB_EP_ATTR_BULK, USB_EP_DIR_IN); 1446 1447 out_data = usb_lookup_ep_data(plp->pl_dip, plp->pl_dev_data, ifc, alt, 1448 0, USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 1449 1450 if ((in_data == NULL) || (out_data == NULL)) { 1451 USB_DPRINTF_L2(DPRINT_ATTACH, plp->pl_lh, 1452 "pl2303_open_pipes: can't get ep data"); 1453 1454 return (USB_FAILURE); 1455 } 1456 1457 /* open pipes */ 1458 policy.pp_max_async_reqs = 2; 1459 1460 if (usb_pipe_open(plp->pl_dip, &in_data->ep_descr, &policy, 1461 USB_FLAGS_SLEEP, &plp->pl_bulkin_ph) != USB_SUCCESS) { 1462 1463 return (USB_FAILURE); 1464 } 1465 1466 if (usb_pipe_open(plp->pl_dip, &out_data->ep_descr, &policy, 1467 USB_FLAGS_SLEEP, &plp->pl_bulkout_ph) != USB_SUCCESS) { 1468 usb_pipe_close(plp->pl_dip, plp->pl_bulkin_ph, USB_FLAGS_SLEEP, 1469 NULL, NULL); 1470 1471 return (USB_FAILURE); 1472 } 1473 1474 mutex_enter(&plp->pl_mutex); 1475 plp->pl_bulkin_state = PL2303_PIPE_IDLE; 1476 plp->pl_bulkout_state = PL2303_PIPE_IDLE; 1477 mutex_exit(&plp->pl_mutex); 1478 1479 return (USB_SUCCESS); 1480 } 1481 1482 1483 static void 1484 pl2303_close_pipes(pl2303_state_t *plp) 1485 { 1486 if (plp->pl_bulkin_ph) { 1487 usb_pipe_close(plp->pl_dip, plp->pl_bulkin_ph, 1488 USB_FLAGS_SLEEP, 0, 0); 1489 } 1490 if (plp->pl_bulkout_ph) { 1491 usb_pipe_close(plp->pl_dip, plp->pl_bulkout_ph, 1492 USB_FLAGS_SLEEP, 0, 0); 1493 } 1494 1495 mutex_enter(&plp->pl_mutex); 1496 plp->pl_bulkin_state = PL2303_PIPE_CLOSED; 1497 plp->pl_bulkout_state = PL2303_PIPE_CLOSED; 1498 mutex_exit(&plp->pl_mutex); 1499 } 1500 1501 1502 static void 1503 pl2303_disconnect_pipes(pl2303_state_t *plp) 1504 { 1505 pl2303_close_pipes(plp); 1506 } 1507 1508 1509 static int 1510 pl2303_reconnect_pipes(pl2303_state_t *plp) 1511 { 1512 if ((pl2303_open_pipes(plp) != USB_SUCCESS)) { 1513 1514 return (USB_FAILURE); 1515 } 1516 1517 return (USB_SUCCESS); 1518 } 1519 1520 1521 /* 1522 * pipe callbacks 1523 * -------------- 1524 * 1525 * 1526 * bulk in common and exeception callback 1527 * 1528 */ 1529 /*ARGSUSED*/ 1530 void 1531 pl2303_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 1532 { 1533 pl2303_state_t *plp = (pl2303_state_t *)req->bulk_client_private; 1534 mblk_t *data; 1535 int data_len; 1536 1537 data = req->bulk_data; 1538 data_len = (data) ? MBLKL(data) : 0; 1539 1540 USB_DPRINTF_L4(DPRINT_IN_PIPE, plp->pl_lh, "pl2303_bulkin_cb: " 1541 "cr=%d len=%d", 1542 req->bulk_completion_reason, 1543 data_len); 1544 1545 /* save data and notify GSD */ 1546 if ((plp->pl_port_state == PL2303_PORT_OPEN) && (data_len) && 1547 (req->bulk_completion_reason == USB_CR_OK)) { 1548 req->bulk_data = NULL; 1549 pl2303_put_tail(&plp->pl_rx_mp, data); 1550 if (plp->pl_cb.cb_rx) { 1551 plp->pl_cb.cb_rx(plp->pl_cb.cb_arg); 1552 } 1553 } 1554 1555 usb_free_bulk_req(req); 1556 1557 /* receive more */ 1558 mutex_enter(&plp->pl_mutex); 1559 plp->pl_bulkin_state = PL2303_PIPE_IDLE; 1560 if ((plp->pl_port_state == PL2303_PORT_OPEN) && 1561 (plp->pl_dev_state == USB_DEV_ONLINE)) { 1562 if (pl2303_rx_start(plp) != USB_SUCCESS) { 1563 USB_DPRINTF_L2(DPRINT_IN_PIPE, plp->pl_lh, 1564 "pl2303_bulkin_cb: restart rx fail"); 1565 } 1566 } 1567 mutex_exit(&plp->pl_mutex); 1568 } 1569 1570 1571 /* 1572 * bulk out common and exeception callback 1573 */ 1574 /*ARGSUSED*/ 1575 void 1576 pl2303_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 1577 { 1578 pl2303_state_t *plp = (pl2303_state_t *)req->bulk_client_private; 1579 int data_len; 1580 mblk_t *data = req->bulk_data; 1581 1582 data_len = (req->bulk_data) ? MBLKL(req->bulk_data) : 0; 1583 1584 USB_DPRINTF_L4(DPRINT_OUT_PIPE, plp->pl_lh, 1585 "pl2303_bulkout_cb: cr=%d len=%d", 1586 req->bulk_completion_reason, 1587 data_len); 1588 1589 if (req->bulk_completion_reason && (data_len > 0)) { 1590 pl2303_put_head(&plp->pl_tx_mp, data); 1591 req->bulk_data = NULL; 1592 } 1593 1594 usb_free_bulk_req(req); 1595 1596 /* notify GSD */ 1597 if (plp->pl_cb.cb_tx) { 1598 plp->pl_cb.cb_tx(plp->pl_cb.cb_arg); 1599 } 1600 1601 /* send more */ 1602 mutex_enter(&plp->pl_mutex); 1603 plp->pl_bulkout_state = PL2303_PIPE_IDLE; 1604 if (plp->pl_tx_mp == NULL) { 1605 cv_broadcast(&plp->pl_tx_cv); 1606 } else { 1607 pl2303_tx_start(plp, NULL); 1608 } 1609 mutex_exit(&plp->pl_mutex); 1610 } 1611 1612 1613 /* 1614 * data transfer routines 1615 * ---------------------- 1616 * 1617 * 1618 * start data receipt 1619 */ 1620 static int 1621 pl2303_rx_start(pl2303_state_t *plp) 1622 { 1623 usb_bulk_req_t *br; 1624 int rval = USB_FAILURE; 1625 1626 USB_DPRINTF_L4(DPRINT_OUT_PIPE, plp->pl_lh, "pl2303_rx_start"); 1627 1628 ASSERT(mutex_owned(&plp->pl_mutex)); 1629 1630 plp->pl_bulkin_state = PL2303_PIPE_BUSY; 1631 mutex_exit(&plp->pl_mutex); 1632 1633 br = usb_alloc_bulk_req(plp->pl_dip, plp->pl_xfer_sz, USB_FLAGS_SLEEP); 1634 br->bulk_len = plp->pl_xfer_sz; 1635 br->bulk_timeout = PL2303_BULKIN_TIMEOUT; 1636 br->bulk_cb = pl2303_bulkin_cb; 1637 br->bulk_exc_cb = pl2303_bulkin_cb; 1638 br->bulk_client_private = (usb_opaque_t)plp; 1639 br->bulk_attributes = USB_ATTRS_AUTOCLEARING | USB_ATTRS_SHORT_XFER_OK; 1640 1641 rval = usb_pipe_bulk_xfer(plp->pl_bulkin_ph, br, 0); 1642 1643 if (rval != USB_SUCCESS) { 1644 USB_DPRINTF_L2(DPRINT_IN_PIPE, plp->pl_lh, 1645 "pl2303_rx_start: xfer failed %d", rval); 1646 usb_free_bulk_req(br); 1647 } 1648 1649 mutex_enter(&plp->pl_mutex); 1650 if (rval != USB_SUCCESS) { 1651 plp->pl_bulkin_state = PL2303_PIPE_IDLE; 1652 } 1653 1654 return (rval); 1655 } 1656 1657 1658 /* 1659 * start data transmit 1660 */ 1661 static void 1662 pl2303_tx_start(pl2303_state_t *plp, int *xferd) 1663 { 1664 int len; /* bytes we can transmit */ 1665 mblk_t *data; /* data to be transmitted */ 1666 int data_len; /* bytes in 'data' */ 1667 mblk_t *mp; /* current msgblk */ 1668 int copylen; /* bytes copy from 'mp' to 'data' */ 1669 int rval; 1670 1671 USB_DPRINTF_L4(DPRINT_OUT_PIPE, plp->pl_lh, "pl2303_tx_start"); 1672 ASSERT(mutex_owned(&plp->pl_mutex)); 1673 ASSERT(plp->pl_port_state != PL2303_PORT_CLOSED); 1674 1675 if (xferd) { 1676 *xferd = 0; 1677 } 1678 if ((plp->pl_port_flags & PL2303_PORT_TX_STOPPED) || 1679 (plp->pl_tx_mp == NULL)) { 1680 1681 return; 1682 } 1683 if (plp->pl_bulkout_state != PL2303_PIPE_IDLE) { 1684 USB_DPRINTF_L4(DPRINT_OUT_PIPE, plp->pl_lh, 1685 "pl2303_tx_start: pipe busy"); 1686 1687 return; 1688 } 1689 ASSERT(MBLKL(plp->pl_tx_mp) > 0); 1690 1691 /* send as much data as port can receive */ 1692 len = min(msgdsize(plp->pl_tx_mp), plp->pl_xfer_sz); 1693 1694 if (len == 0) { 1695 1696 return; 1697 } 1698 1699 if ((data = allocb(len, BPRI_LO)) == NULL) { 1700 1701 return; 1702 } 1703 1704 /* 1705 * copy no more than 'len' bytes from mblk chain to transmit mblk 'data' 1706 */ 1707 data_len = 0; 1708 1709 while ((data_len < len) && plp->pl_tx_mp) { 1710 mp = plp->pl_tx_mp; 1711 copylen = min(MBLKL(mp), len - data_len); 1712 bcopy(mp->b_rptr, data->b_wptr, copylen); 1713 mp->b_rptr += copylen; 1714 data->b_wptr += copylen; 1715 data_len += copylen; 1716 1717 if (MBLKL(mp) <= 0) { 1718 plp->pl_tx_mp = unlinkb(mp); 1719 freeb(mp); 1720 } else { 1721 ASSERT(data_len == len); 1722 } 1723 } 1724 1725 if (data_len <= 0) { 1726 USB_DPRINTF_L3(DPRINT_OUT_PIPE, plp->pl_lh, 1727 "pl2303_tx_start: copied zero bytes"); 1728 freeb(data); 1729 1730 return; 1731 } 1732 1733 plp->pl_bulkout_state = PL2303_PIPE_BUSY; 1734 mutex_exit(&plp->pl_mutex); 1735 1736 rval = pl2303_send_data(plp, data); 1737 mutex_enter(&plp->pl_mutex); 1738 1739 if (rval != USB_SUCCESS) { 1740 plp->pl_bulkout_state = PL2303_PIPE_IDLE; 1741 pl2303_put_head(&plp->pl_tx_mp, data); 1742 } else { 1743 if (xferd) { 1744 *xferd = data_len; 1745 } 1746 } 1747 } 1748 1749 1750 static int 1751 pl2303_send_data(pl2303_state_t *plp, mblk_t *data) 1752 { 1753 usb_bulk_req_t *br; 1754 int len = MBLKL(data); 1755 int rval; 1756 1757 USB_DPRINTF_L4(DPRINT_OUT_PIPE, plp->pl_lh, "pl2303_send_data: %d " 1758 "%x %x %x", len, data->b_rptr[0], 1759 (len > 1) ? data->b_rptr[1] : 0, 1760 (len > 2) ? data->b_rptr[2] : 0); 1761 ASSERT(!mutex_owned(&plp->pl_mutex)); 1762 1763 br = usb_alloc_bulk_req(plp->pl_dip, 0, USB_FLAGS_SLEEP); 1764 br->bulk_data = data; 1765 br->bulk_len = len; 1766 br->bulk_timeout = PL2303_BULKOUT_TIMEOUT; 1767 br->bulk_cb = pl2303_bulkout_cb; 1768 br->bulk_exc_cb = pl2303_bulkout_cb; 1769 br->bulk_client_private = (usb_opaque_t)plp; 1770 br->bulk_attributes = USB_ATTRS_AUTOCLEARING; 1771 1772 rval = usb_pipe_bulk_xfer(plp->pl_bulkout_ph, br, 0); 1773 1774 if (rval != USB_SUCCESS) { 1775 USB_DPRINTF_L2(DPRINT_OUT_PIPE, plp->pl_lh, 1776 "pl2303_send_data: xfer failed %d", rval); 1777 1778 br->bulk_data = NULL; 1779 usb_free_bulk_req(br); 1780 } 1781 1782 return (rval); 1783 } 1784 1785 1786 /* 1787 * wait until local tx buffer drains. 1788 * 'timeout' is in seconds, zero means wait forever 1789 */ 1790 static int 1791 pl2303_wait_tx_drain(pl2303_state_t *plp, int timeout) 1792 { 1793 clock_t until; 1794 int over = 0; 1795 1796 until = ddi_get_lbolt() + drv_usectohz(1000 * 1000 * timeout); 1797 1798 while (plp->pl_tx_mp && !over) { 1799 if (timeout > 0) { 1800 /* whether timedout or signal pending */ 1801 over = (cv_timedwait_sig(&plp->pl_tx_cv, 1802 &plp->pl_mutex, until) <= 0); 1803 } else { 1804 /* whether a signal is pending */ 1805 over = (cv_wait_sig(&plp->pl_tx_cv, 1806 &plp->pl_mutex) == 0); 1807 } 1808 } 1809 1810 return ((plp->pl_tx_mp == NULL) ? USB_SUCCESS : USB_FAILURE); 1811 } 1812 1813 1814 /* 1815 * device operations 1816 * ----------------- 1817 * 1818 * 1819 * initialize hardware serial port 1820 */ 1821 static int 1822 pl2303_open_hw_port(pl2303_state_t *plp) 1823 { 1824 int rval = USB_SUCCESS; 1825 1826 /* 1827 * initialize three Device Configuration Registers (DCR): 1828 * DCR0, DCR1, and DCR2 1829 */ 1830 1831 switch (plp->pl_chiptype) { 1832 case (pl2303_H): 1833 /* Set DCR0 */ 1834 if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR0, 1835 DCR0_INIT_H)) != USB_SUCCESS) { 1836 1837 return (rval); 1838 } 1839 1840 /* Set DCR1 */ 1841 if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR1, 1842 DCR1_INIT_H)) != USB_SUCCESS) { 1843 1844 return (rval); 1845 } 1846 1847 /* Set DCR2 */ 1848 if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR2, 1849 DCR2_INIT_H)) != USB_SUCCESS) { 1850 1851 return (rval); 1852 } 1853 1854 break; 1855 case (pl2303_X): 1856 case (pl2303_HX_CHIP_D): 1857 1858 /* Set DCR0 */ 1859 if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR0, 1860 DCR0_INIT)) != USB_SUCCESS) { 1861 1862 return (rval); 1863 } 1864 1865 /* Set DCR1 */ 1866 if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR1, 1867 DCR1_INIT_X)) != USB_SUCCESS) { 1868 1869 return (rval); 1870 } 1871 1872 /* Set DCR2 */ 1873 if ((rval = pl2303_cmd_vendor_write0(plp, SET_DCR2, 1874 DCR2_INIT_X)) != USB_SUCCESS) { 1875 1876 return (rval); 1877 } 1878 1879 /* reset Downstream data pipes */ 1880 if ((rval = pl2303_cmd_vendor_write0(plp, 1881 RESET_DOWNSTREAM_DATA_PIPE, 0)) != USB_SUCCESS) { 1882 1883 return (rval); 1884 } 1885 1886 /* reset Upstream data pipes */ 1887 if ((rval = pl2303_cmd_vendor_write0(plp, 1888 RESET_UPSTREAM_DATA_PIPE, 0)) != USB_SUCCESS) { 1889 1890 return (rval); 1891 } 1892 1893 break; 1894 case (pl2303_UNKNOWN): 1895 default: 1896 USB_DPRINTF_L2(DPRINT_OPEN, plp->pl_lh, 1897 "pl2303_open_hw_port: unknown chiptype"); 1898 1899 rval = USB_FAILURE; 1900 } 1901 1902 return (rval); 1903 } 1904 1905 1906 /* 1907 * vendor-specific commands 1908 * ------------------------ 1909 * 1910 * 1911 * Get_Line_Coding Request 1912 */ 1913 static int 1914 pl2303_cmd_get_line(pl2303_state_t *plp, mblk_t **data) 1915 { 1916 usb_ctrl_setup_t setup = { PL2303_GET_LINE_CODING_REQUEST_TYPE, 1917 PL2303_GET_LINE_CODING_REQUEST, 0, 0, 1918 PL2303_GET_LINE_CODING_LENGTH, 0 }; 1919 usb_cb_flags_t cb_flags; 1920 usb_cr_t cr; 1921 int rval; 1922 1923 *data = NULL; 1924 1925 rval = usb_pipe_ctrl_xfer_wait(plp->pl_def_ph, &setup, data, 1926 &cr, &cb_flags, 0); 1927 1928 if ((rval == USB_SUCCESS) && (*data != NULL)) { 1929 USB_DPRINTF_L4(DPRINT_DEF_PIPE, plp->pl_lh, 1930 "pl2303_cmd_get_line: %x %x %x %x %x %x %x", 1931 (*data)->b_rptr[0], (*data)->b_rptr[1], (*data)->b_rptr[2], 1932 (*data)->b_rptr[3], (*data)->b_rptr[4], (*data)->b_rptr[5], 1933 (*data)->b_rptr[6]); 1934 } else { 1935 USB_DPRINTF_L2(DPRINT_DEF_PIPE, plp->pl_lh, 1936 "pl2303_cmd_get_line: failed %d %d %x", 1937 rval, cr, cb_flags); 1938 1939 if (*data != NULL) { 1940 freeb(*data); 1941 } 1942 } 1943 1944 return (rval); 1945 } 1946 1947 1948 /* 1949 * Set_Line_Coding Request 1950 */ 1951 static int 1952 pl2303_cmd_set_line(pl2303_state_t *plp, mblk_t *data) 1953 { 1954 usb_ctrl_setup_t setup = { PL2303_SET_LINE_CODING_REQUEST_TYPE, 1955 PL2303_SET_LINE_CODING_REQUEST, 0, 0, 1956 PL2303_SET_LINE_CODING_LENGTH, 0 }; 1957 usb_cb_flags_t cb_flags; 1958 usb_cr_t cr; 1959 int rval; 1960 1961 USB_DPRINTF_L4(DPRINT_DEF_PIPE, plp->pl_lh, 1962 "pl2303_cmd_set_line: %x %x %x %x %x %x %x", 1963 data->b_rptr[0], data->b_rptr[1], data->b_rptr[2], 1964 data->b_rptr[3], data->b_rptr[4], data->b_rptr[5], data->b_rptr[6]); 1965 1966 rval = usb_pipe_ctrl_xfer_wait(plp->pl_def_ph, &setup, &data, 1967 &cr, &cb_flags, 0); 1968 1969 if (rval != USB_SUCCESS) { 1970 USB_DPRINTF_L2(DPRINT_DEF_PIPE, plp->pl_lh, 1971 "pl2303_cmd_set_line: failed %d %d %x", 1972 rval, cr, cb_flags); 1973 } 1974 1975 return (rval); 1976 } 1977 1978 1979 /* 1980 * Set_Control_Line_State Request to RTS and DTR 1981 */ 1982 static int 1983 pl2303_cmd_set_ctl(pl2303_state_t *plp, uint8_t val) 1984 { 1985 usb_ctrl_setup_t setup = { PL2303_SET_CONTROL_REQUEST_TYPE, 1986 PL2303_SET_CONTROL_REQUEST, 0, 0, 1987 PL2303_SET_CONTROL_LENGTH, 0 }; 1988 usb_cb_flags_t cb_flags; 1989 usb_cr_t cr; 1990 int rval; 1991 1992 setup.wValue = val; 1993 1994 rval = usb_pipe_ctrl_xfer_wait(plp->pl_def_ph, &setup, NULL, 1995 &cr, &cb_flags, 0); 1996 1997 if (rval != USB_SUCCESS) { 1998 USB_DPRINTF_L2(DPRINT_DEF_PIPE, plp->pl_lh, 1999 "pl2303_cmd_set_ctl: failed %d %d %x", 2000 rval, cr, cb_flags); 2001 } 2002 2003 return (rval); 2004 } 2005 2006 2007 /* 2008 * Vendor_Specific_Write Request 2009 * wLength: 0 2010 */ 2011 static int 2012 pl2303_cmd_vendor_write0(pl2303_state_t *plp, uint16_t value, int16_t index) 2013 { 2014 usb_ctrl_setup_t setup = { PL2303_VENDOR_WRITE_REQUEST_TYPE, 2015 PL2303_VENDOR_WRITE_REQUEST, 0, 0, 2016 PL2303_VENDOR_WRITE_LENGTH, 0 }; 2017 usb_cb_flags_t cb_flags; 2018 usb_cr_t cr; 2019 int rval; 2020 2021 setup.wValue = value; 2022 setup.wIndex = index; 2023 2024 rval = usb_pipe_ctrl_xfer_wait(plp->pl_def_ph, &setup, NULL, 2025 &cr, &cb_flags, 0); 2026 2027 if (rval != USB_SUCCESS) { 2028 USB_DPRINTF_L2(DPRINT_DEF_PIPE, plp->pl_lh, 2029 "pl2303_cmd_vendor_write0: %x %x failed %d %d %x", 2030 value, index, rval, cr, cb_flags); 2031 } 2032 2033 return (rval); 2034 } 2035 2036 2037 /* 2038 * For Hardware flow control 2039 */ 2040 static int 2041 pl2303_cmd_set_rtscts(pl2303_state_t *plp) 2042 { 2043 /* Set DCR0 */ 2044 switch (plp->pl_chiptype) { 2045 case pl2303_H: 2046 2047 return (pl2303_cmd_vendor_write0(plp, SET_DCR0, DCR0_INIT_H)); 2048 case pl2303_X: 2049 case pl2303_HX_CHIP_D: 2050 2051 return (pl2303_cmd_vendor_write0(plp, SET_DCR0, DCR0_INIT_X)); 2052 case pl2303_UNKNOWN: 2053 default: 2054 2055 return (USB_FAILURE); 2056 } 2057 } 2058 2059 2060 /* 2061 * Set TxD BREAK_ON or BREAK_OFF 2062 */ 2063 static int 2064 pl2303_cmd_break(pl2303_state_t *plp, int ctl) 2065 { 2066 usb_ctrl_setup_t setup = { PL2303_BREAK_REQUEST_TYPE, 2067 PL2303_BREAK_REQUEST, 0, 0, 2068 PL2303_BREAK_LENGTH, 0 }; 2069 usb_cb_flags_t cb_flags; 2070 usb_cr_t cr; 2071 int rval; 2072 2073 setup.wValue = (ctl == DS_ON) ? PL2303_BREAK_ON : PL2303_BREAK_OFF; 2074 2075 rval = usb_pipe_ctrl_xfer_wait(plp->pl_def_ph, &setup, NULL, 2076 &cr, &cb_flags, 0); 2077 2078 if (rval != USB_SUCCESS) { 2079 USB_DPRINTF_L2(DPRINT_DEF_PIPE, plp->pl_lh, 2080 "pl2303_cmd_break: failed rval=%d,cr=%d,cb_flags=0x%x", 2081 rval, cr, cb_flags); 2082 } 2083 2084 return (rval); 2085 } 2086 2087 2088 /* 2089 * for set_mod_ctl 2090 */ 2091 static void 2092 pl2303_mctl2reg(int mask, int val, uint8_t *line_ctl) 2093 { 2094 if (mask & TIOCM_RTS) { 2095 if (val & TIOCM_RTS) { 2096 *line_ctl |= PL2303_CONTROL_RTS; 2097 } else { 2098 *line_ctl &= ~PL2303_CONTROL_RTS; 2099 } 2100 } 2101 if (mask & TIOCM_DTR) { 2102 if (val & TIOCM_DTR) { 2103 *line_ctl |= PL2303_CONTROL_DTR; 2104 } else { 2105 *line_ctl &= ~PL2303_CONTROL_DTR; 2106 } 2107 } 2108 } 2109 2110 2111 /* 2112 * for get_mod_ctl 2113 */ 2114 static int 2115 pl2303_reg2mctl(uint8_t line_ctl) 2116 { 2117 int val = 0; 2118 2119 if (line_ctl & PL2303_CONTROL_RTS) { 2120 val |= TIOCM_RTS; 2121 } 2122 if (line_ctl & PL2303_CONTROL_DTR) { 2123 val |= TIOCM_DTR; 2124 } 2125 2126 return (val); 2127 } 2128 2129 2130 /* 2131 * misc routines 2132 * ------------- 2133 * 2134 */ 2135 2136 /* 2137 * link a message block to tail of message 2138 * account for the case when message is null 2139 */ 2140 static void 2141 pl2303_put_tail(mblk_t **mpp, mblk_t *bp) 2142 { 2143 if (*mpp) { 2144 linkb(*mpp, bp); 2145 } else { 2146 *mpp = bp; 2147 } 2148 } 2149 2150 2151 /* 2152 * put a message block at the head of the message 2153 * account for the case when message is null 2154 */ 2155 static void 2156 pl2303_put_head(mblk_t **mpp, mblk_t *bp) 2157 { 2158 if (*mpp) { 2159 linkb(bp, *mpp); 2160 } 2161 *mpp = bp; 2162 } 2163 2164 /*ARGSUSED*/ 2165 static usb_pipe_handle_t 2166 pl2303_out_pipe(ds_hdl_t hdl, uint_t port_num) 2167 { 2168 pl2303_state_t *plp = (pl2303_state_t *)hdl; 2169 2170 return (plp->pl_bulkout_ph); 2171 } 2172 2173 /*ARGSUSED*/ 2174 static usb_pipe_handle_t 2175 pl2303_in_pipe(ds_hdl_t hdl, uint_t port_num) 2176 { 2177 pl2303_state_t *plp = (pl2303_state_t *)hdl; 2178 2179 return (plp->pl_bulkin_ph); 2180 } 2181