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