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