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 /* 23 * Copyright 2007 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 * DSD code for keyspan usb2serial adapters 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 49 #include <sys/usb/clients/usbser/usbser_dsdi.h> 50 #include <sys/usb/clients/usbser/usbser_keyspan/keyspan_var.h> 51 #include <sys/usb/clients/usbser/usbser_keyspan/keyspan_pipe.h> 52 53 #include <sys/usb/clients/usbser/usbser_keyspan/usa90msg.h> 54 #include <sys/usb/clients/usbser/usbser_keyspan/usa49msg.h> 55 56 /* 57 * DSD operations which are filled in ds_ops structure. 58 */ 59 static int keyspan_attach(ds_attach_info_t *); 60 static void keyspan_detach(ds_hdl_t); 61 static int keyspan_register_cb(ds_hdl_t, uint_t, ds_cb_t *); 62 static void keyspan_unregister_cb(ds_hdl_t, uint_t); 63 static int keyspan_open_port(ds_hdl_t, uint_t); 64 static int keyspan_close_port(ds_hdl_t, uint_t); 65 66 /* power management */ 67 static int keyspan_usb_power(ds_hdl_t, int, int, int *); 68 static int keyspan_suspend(ds_hdl_t); 69 static int keyspan_resume(ds_hdl_t); 70 71 /* hotplug */ 72 static int keyspan_disconnect(ds_hdl_t); 73 static int keyspan_reconnect(ds_hdl_t); 74 75 /* standard UART operations */ 76 static int keyspan_set_port_params(ds_hdl_t, uint_t, ds_port_params_t *); 77 static int keyspan_set_modem_ctl(ds_hdl_t, uint_t, int, int); 78 static int keyspan_get_modem_ctl(ds_hdl_t, uint_t, int, int *); 79 static int keyspan_break_ctl(ds_hdl_t, uint_t, int); 80 static int keyspan_loopback(ds_hdl_t, uint_t, int); 81 82 /* data xfer */ 83 static int keyspan_tx(ds_hdl_t, uint_t, mblk_t *); 84 static mblk_t *keyspan_rx(ds_hdl_t, uint_t); 85 static void keyspan_stop(ds_hdl_t, uint_t, int); 86 static void keyspan_start(ds_hdl_t, uint_t, int); 87 static int keyspan_fifo_flush(ds_hdl_t, uint_t, int); 88 static int keyspan_fifo_drain(ds_hdl_t, uint_t, int); 89 90 /* 91 * Sub-routines 92 */ 93 94 /* configuration routines */ 95 static void keyspan_free_soft_state(keyspan_state_t *); 96 static void keyspan_init_sync_objs(keyspan_state_t *); 97 static void keyspan_fini_sync_objs(keyspan_state_t *); 98 static int keyspan_usb_register(keyspan_state_t *); 99 static void keyspan_usb_unregister(keyspan_state_t *); 100 static int keyspan_attach_dev(keyspan_state_t *); 101 static void keyspan_attach_ports(keyspan_state_t *); 102 static void keyspan_detach_ports(keyspan_state_t *); 103 static void keyspan_init_port_params(keyspan_state_t *); 104 static void keyspan_free_descr_tree(keyspan_state_t *); 105 static int keyspan_register_events(keyspan_state_t *); 106 static void keyspan_unregister_events(keyspan_state_t *); 107 static void keyspan_set_dev_state_online(keyspan_state_t *); 108 109 /* hotplug */ 110 static int keyspan_restore_device_state(keyspan_state_t *); 111 static int keyspan_restore_ports_state(keyspan_state_t *); 112 113 /* power management */ 114 static int keyspan_create_pm_components(keyspan_state_t *); 115 static void keyspan_destroy_pm_components(keyspan_state_t *); 116 static int keyspan_pm_set_busy(keyspan_state_t *); 117 static void keyspan_pm_set_idle(keyspan_state_t *); 118 static int keyspan_pwrlvl0(keyspan_state_t *); 119 static int keyspan_pwrlvl1(keyspan_state_t *); 120 static int keyspan_pwrlvl2(keyspan_state_t *); 121 static int keyspan_pwrlvl3(keyspan_state_t *); 122 123 /* pipe operations */ 124 static int keyspan_attach_pipes(keyspan_state_t *); 125 static void keyspan_detach_pipes(keyspan_state_t *); 126 static void keyspan_disconnect_pipes(keyspan_state_t *); 127 static int keyspan_reconnect_pipes(keyspan_state_t *); 128 129 /* data transfer routines */ 130 static int keyspan_wait_tx_drain(keyspan_port_t *, int); 131 132 /* misc */ 133 static void keyspan_default_port_params(keyspan_port_t *); 134 static void keyspan_build_cmd_msg(keyspan_port_t *, ds_port_params_t *); 135 static void keyspan_save_port_params(keyspan_port_t *); 136 137 /* 138 * Model specific functions. 139 */ 140 141 /* usa19hs specific functions */ 142 static void keyspan_build_cmd_msg_usa19hs(keyspan_port_t *, 143 ds_port_params_t *); 144 static void keyspan_default_port_params_usa19hs(keyspan_port_t *); 145 static void keyspan_save_port_params_usa19hs(keyspan_port_t *); 146 147 148 /* usa49 specific functions */ 149 static void keyspan_build_cmd_msg_usa49(keyspan_port_t *, 150 ds_port_params_t *); 151 static void keyspan_default_port_params_usa49(keyspan_port_t *); 152 static void keyspan_save_port_params_usa49(keyspan_port_t *); 153 154 155 /* 156 * DSD ops structure 157 */ 158 ds_ops_t ds_ops = { 159 DS_OPS_VERSION, 160 keyspan_attach, 161 keyspan_detach, 162 keyspan_register_cb, 163 keyspan_unregister_cb, 164 keyspan_open_port, 165 keyspan_close_port, 166 keyspan_usb_power, 167 keyspan_suspend, 168 keyspan_resume, 169 keyspan_disconnect, 170 keyspan_reconnect, 171 keyspan_set_port_params, 172 keyspan_set_modem_ctl, 173 keyspan_get_modem_ctl, 174 keyspan_break_ctl, 175 keyspan_loopback, 176 keyspan_tx, 177 keyspan_rx, 178 keyspan_stop, 179 keyspan_start, 180 keyspan_fifo_flush, 181 keyspan_fifo_drain 182 }; 183 184 /* 185 * For USA19HS baud speed, precalculated using the following algorithm: 186 * 187 * speed = (uint16_t)(14769231L / baud); 188 */ 189 static uint16_t keyspan_speedtab_usa19hs[] = { 190 0x0, /* B0 */ 191 0x481d, /* B50 */ 192 0x3013, /* B75 */ 193 0x20c7, /* B110 */ 194 0x1ae8, /* B134 */ 195 0x1809, /* B150 */ 196 0x1207, /* B200 */ 197 0xc04, /* B300 */ 198 0x602, /* B600 */ 199 0x301, /* B1200 */ 200 0x200, /* B1800 */ 201 0x180, /* B2400 */ 202 0xc0, /* B4800 */ 203 0x60, /* B9600 */ 204 0x30, /* B19200 */ 205 0x18, /* B38400 */ 206 0x10, /* B57600 */ 207 0xc, /* B76800 */ 208 0x8, /* B115200 */ 209 0x6, /* B153600 */ 210 0x4, /* B230400 */ 211 }; 212 213 /* 214 * For USA49WLC baud speed, precalculated. 215 */ 216 static uint16_t keyspan_speedtab_usa49[] = { 217 0x0, /* B0 */ 218 0x7530, /* B50 */ 219 0x4e20, /* B75 */ 220 0x3544, /* B110 */ 221 0x2bba, /* B134 */ 222 0x2710, /* B150 */ 223 0x1d4c, /* B200 */ 224 0x1388, /* B300 */ 225 0x9c4, /* B600 */ 226 0x4e2, /* B1200 */ 227 0x25e, /* B1800 */ 228 0x271, /* B2400 */ 229 0xfa, /* B4800 */ 230 0x7d, /* B9600 */ 231 0x19, /* B19200 */ 232 0x27, /* B38400 */ 233 0x1a, /* B57600 */ 234 0xd, /* B76800 */ 235 0xd, /* B115200 */ 236 0x6, /* B153600 */ 237 0x4, /* B230400 */ 238 }; 239 240 /* 241 * For USA49WLC prescaler, precalculated. 242 */ 243 static uint8_t keyspan_prescaler_49wlc[] = { 244 0x0, /* B0 */ 245 0x8, /* B50 */ 246 0x8, /* B75 */ 247 0x8, /* B110 */ 248 0x8, /* B134 */ 249 0x8, /* B150 */ 250 0x8, /* B200 */ 251 0x8, /* B300 */ 252 0x8, /* B600 */ 253 0x8, /* B1200 */ 254 0xb, /* B1800 */ 255 0x8, /* B2400 */ 256 0xa, /* B4800 */ 257 0xa, /* B9600 */ 258 0x19, /* B19200 */ 259 0x8, /* B38400 */ 260 0x8, /* B57600 */ 261 0xc, /* B76800 */ 262 0x8, /* B115200 */ 263 0xd, /* B153600 */ 264 0xd, /* B230400 */ 265 }; 266 267 268 /* convert baud code into baud rate */ 269 static int keyspan_speed2baud[] = { 270 0, /* B0 */ 271 50, /* B50 */ 272 75, /* B75 */ 273 110, /* B110 */ 274 134, /* B134 */ 275 150, /* B150 */ 276 200, /* B200 */ 277 300, /* B300 */ 278 600, /* B600 */ 279 1200, /* B1200 */ 280 1800, /* B1800 */ 281 2400, /* B2400 */ 282 4800, /* B4800 */ 283 9600, /* B9600 */ 284 19200, /* B19200 */ 285 38400, /* B38400 */ 286 57600, /* B57600 */ 287 76800, /* B76800 */ 288 115200, /* B115200 */ 289 153600, /* B153600 */ 290 230400, /* B230400 */ 291 }; 292 293 294 /* debug support */ 295 static uint_t keyspan_errlevel = USB_LOG_L4; 296 static uint_t keyspan_errmask = DPRINT_MASK_ALL; 297 static uint_t keyspan_instance_debug = (uint_t)-1; 298 299 static int 300 keyspan_attach(ds_attach_info_t *aip) 301 { 302 keyspan_state_t *ksp; 303 int rval = USB_SUCCESS; 304 305 ksp = (keyspan_state_t *)kmem_zalloc(sizeof (keyspan_state_t), 306 KM_SLEEP); 307 ksp->ks_dip = aip->ai_dip; 308 ksp->ks_usb_events = aip->ai_usb_events; 309 *aip->ai_hdl = (ds_hdl_t)ksp; 310 311 if (keyspan_usb_register(ksp) != USB_SUCCESS) { 312 313 goto fail_register; 314 } 315 316 /* init mutex and semaphore */ 317 keyspan_init_sync_objs(ksp); 318 319 /* get device specific parameters */ 320 if (keyspan_attach_dev(ksp) != USB_SUCCESS) { 321 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, "fail attach dev "); 322 323 goto fail_attach_dev; 324 } 325 326 keyspan_attach_ports(ksp); 327 328 switch (ksp->ks_dev_spec.id_product) { 329 case KEYSPAN_USA19HS_PID: 330 case KEYSPAN_USA49WLC_PID: 331 rval = keyspan_init_pipes(ksp); 332 333 break; 334 335 case KEYSPAN_USA49WG_PID: 336 rval = keyspan_init_pipes_usa49wg(ksp); 337 338 break; 339 340 default: 341 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, "keyspan_attach:" 342 "the device's product id can't be recognized"); 343 344 return (USB_FAILURE); 345 } 346 347 if (rval != USB_SUCCESS) { 348 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 349 "keyspan_init_pipes: failed."); 350 351 goto fail_init_pipes; 352 } 353 354 keyspan_init_port_params(ksp); 355 keyspan_free_descr_tree(ksp); 356 keyspan_set_dev_state_online(ksp); 357 358 if (keyspan_create_pm_components(ksp) != USB_SUCCESS) { 359 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 360 "keyspan_create_pm_components: failed."); 361 362 goto fail_pm; 363 } 364 365 if (keyspan_register_events(ksp) != USB_SUCCESS) { 366 367 goto fail_events; 368 } 369 370 /* open the global pipes */ 371 if (keyspan_attach_pipes(ksp) != USB_SUCCESS) { 372 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 373 "keyspan_attach_pipes: failed."); 374 375 goto fail_attach_pipes; 376 } 377 378 *aip->ai_port_cnt = ksp->ks_dev_spec.port_cnt; 379 380 return (USB_SUCCESS); 381 382 fail_attach_pipes: 383 keyspan_unregister_events(ksp); 384 fail_events: 385 keyspan_destroy_pm_components(ksp); 386 fail_pm: 387 keyspan_fini_pipes(ksp); 388 fail_init_pipes: 389 keyspan_detach_ports(ksp); 390 fail_attach_dev: 391 keyspan_fini_sync_objs(ksp); 392 keyspan_usb_unregister(ksp); 393 fail_register: 394 keyspan_free_soft_state(ksp); 395 396 return (USB_FAILURE); 397 } 398 399 400 /* 401 * ds_detach 402 */ 403 static void 404 keyspan_detach(ds_hdl_t hdl) 405 { 406 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 407 408 keyspan_detach_pipes(ksp); 409 keyspan_unregister_events(ksp); 410 keyspan_destroy_pm_components(ksp); 411 keyspan_fini_pipes(ksp); 412 keyspan_detach_ports(ksp); 413 keyspan_fini_sync_objs(ksp); 414 keyspan_usb_unregister(ksp); 415 keyspan_free_soft_state(ksp); 416 } 417 418 /* 419 * ds_register_cb 420 */ 421 static int 422 keyspan_register_cb(ds_hdl_t hdl, uint_t port_num, ds_cb_t *cb) 423 { 424 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 425 keyspan_port_t *kp; 426 427 if (port_num >= ksp->ks_dev_spec.port_cnt) { 428 429 return (USB_FAILURE); 430 } 431 kp = &ksp->ks_ports[port_num]; 432 kp->kp_cb = *cb; 433 434 return (USB_SUCCESS); 435 } 436 437 /* 438 * ds_unregister_cb 439 */ 440 static void 441 keyspan_unregister_cb(ds_hdl_t hdl, uint_t port_num) 442 { 443 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 444 keyspan_port_t *kp; 445 446 if (port_num < ksp->ks_dev_spec.port_cnt) { 447 kp = &ksp->ks_ports[port_num]; 448 bzero(&kp->kp_cb, sizeof (kp->kp_cb)); 449 } 450 } 451 452 /* 453 * initialize hardware serial port 454 * 455 * 'open_pipes' specifies whether to open USB pipes or not 456 */ 457 int 458 keyspan_open_hw_port(keyspan_port_t *kp, boolean_t open_pipes) 459 { 460 int rval; 461 keyspan_state_t *ksp = kp->kp_ksp; 462 463 USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh, 464 "keyspan_open_hw_port: [%d]", kp->kp_port_num); 465 466 if (open_pipes) { 467 468 /* open r/w pipes for this port */ 469 if ((rval = keyspan_open_port_pipes(kp)) != USB_SUCCESS) { 470 471 return (rval); 472 } 473 } 474 475 mutex_enter(&kp->kp_mutex); 476 kp->kp_state = KEYSPAN_PORT_OPEN; 477 mutex_exit(&kp->kp_mutex); 478 479 switch (ksp->ks_dev_spec.id_product) { 480 case KEYSPAN_USA19HS_PID: 481 case KEYSPAN_USA49WLC_PID: 482 if ((rval = keyspan_receive_data(&kp->kp_datain_pipe, 483 kp->kp_read_len, kp)) != USB_SUCCESS) { 484 485 goto fail; 486 } 487 488 break; 489 490 case KEYSPAN_USA49WG_PID: 491 mutex_enter(&ksp->ks_mutex); 492 /* open data in pipe the first time, start receiving data */ 493 if ((ksp->ks_datain_open_cnt == 1) && open_pipes) { 494 mutex_exit(&ksp->ks_mutex); 495 if ((rval = keyspan_receive_data(&kp->kp_datain_pipe, 496 kp->kp_read_len, kp)) != USB_SUCCESS) { 497 498 goto fail; 499 } 500 /* the device is reconnected to host, restart receiving data */ 501 } else if ((ksp->ks_reconnect_flag) && (!open_pipes)) { 502 mutex_exit(&ksp->ks_mutex); 503 if ((rval = keyspan_receive_data(&kp->kp_datain_pipe, 504 kp->kp_read_len, kp)) != USB_SUCCESS) { 505 506 goto fail; 507 } 508 mutex_enter(&ksp->ks_mutex); 509 ksp->ks_reconnect_flag = 0; 510 mutex_exit(&ksp->ks_mutex); 511 512 } else { 513 mutex_exit(&ksp->ks_mutex); 514 } 515 516 break; 517 518 default: 519 USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh, "keyspan_open_hw_port:" 520 "the device's product id can't be recognized"); 521 522 return (USB_FAILURE); 523 } 524 525 /* set the default port parameters and send cmd msg to enable port */ 526 mutex_enter(&kp->kp_mutex); 527 keyspan_default_port_params(kp); 528 mutex_exit(&kp->kp_mutex); 529 530 (void) keyspan_send_cmd(kp); 531 532 USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh, 533 "keyspan_open_hw_port: [%d] finished", kp->kp_port_num); 534 535 return (rval); 536 537 fail: 538 539 mutex_enter(&kp->kp_mutex); 540 kp->kp_state = KEYSPAN_PORT_CLOSED; 541 mutex_exit(&kp->kp_mutex); 542 543 if (open_pipes) { 544 545 /* close all ports' data pipes */ 546 keyspan_close_port_pipes(kp); 547 } 548 549 USB_DPRINTF_L2(DPRINT_OPEN, kp->kp_lh, 550 "keyspan_open_hw_port: failed. This port can't be used."); 551 552 return (rval); 553 } 554 555 /* 556 * ds_open_port 557 */ 558 static int 559 keyspan_open_port(ds_hdl_t hdl, uint_t port_num) 560 { 561 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 562 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 563 int rval; 564 565 if (port_num >= ksp->ks_dev_spec.port_cnt) { 566 567 return (USB_FAILURE); 568 } 569 USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh, "keyspan_open_port"); 570 571 mutex_enter(&ksp->ks_mutex); 572 if (ksp->ks_dev_state == USB_DEV_DISCONNECTED) { 573 mutex_exit(&ksp->ks_mutex); 574 575 return (USB_FAILURE); 576 } 577 mutex_exit(&ksp->ks_mutex); 578 579 if (keyspan_pm_set_busy(ksp) != USB_SUCCESS) { 580 581 return (USB_FAILURE); 582 } 583 584 /* 585 * initialize state 586 */ 587 mutex_enter(&kp->kp_mutex); 588 ASSERT(kp->kp_state == KEYSPAN_PORT_CLOSED); 589 ASSERT((kp->kp_rx_mp == NULL) && (kp->kp_tx_mp == NULL)); 590 591 kp->kp_state = KEYSPAN_PORT_OPENING; 592 kp->kp_flags = 0; 593 mutex_exit(&kp->kp_mutex); 594 595 /* 596 * initialize hardware serial port, B_TRUE means open pipes 597 */ 598 sema_p(&ksp->ks_pipes_sema); 599 rval = keyspan_open_hw_port(kp, B_TRUE); 600 if (rval != USB_SUCCESS) { 601 keyspan_pm_set_idle(ksp); 602 } 603 sema_v(&ksp->ks_pipes_sema); 604 605 return (rval); 606 } 607 608 609 /* 610 * close hardware serial port 611 */ 612 void 613 keyspan_close_hw_port(keyspan_port_t *kp) 614 { 615 keyspan_state_t *ksp = kp->kp_ksp; 616 617 ASSERT(!mutex_owned(&kp->kp_mutex)); 618 619 USB_DPRINTF_L4(DPRINT_CLOSE, kp->kp_lh, 620 "keyspan_close_hw_port"); 621 622 /* 623 * The bulk IN/OUT pipes might have got closed due to 624 * a device disconnect event. So its required to check the 625 * pipe handle and proceed if it is not NULL 626 */ 627 628 mutex_enter(&kp->kp_mutex); 629 if ((kp->kp_datain_pipe.pipe_handle == NULL) && 630 (kp->kp_dataout_pipe.pipe_handle == NULL)) { 631 mutex_exit(&kp->kp_mutex); 632 633 return; 634 } 635 636 switch (ksp->ks_dev_spec.id_product) { 637 case KEYSPAN_USA19HS_PID: 638 keyspan_build_cmd_msg_usa19hs(kp, NULL); 639 kp->kp_ctrl_msg.usa19hs.portEnabled = 0; 640 kp->kp_ctrl_msg.usa19hs.rxFlush = 0; 641 kp->kp_ctrl_msg.usa19hs.txFlush = 0; 642 kp->kp_ctrl_msg.usa19hs.returnStatus = 0; 643 kp->kp_ctrl_msg.usa19hs.setRts = 1; 644 kp->kp_ctrl_msg.usa19hs.rts = 0; 645 kp->kp_ctrl_msg.usa19hs.setDtr = 1; 646 kp->kp_ctrl_msg.usa19hs.dtr = 0; 647 kp->kp_ctrl_msg.usa19hs.setTxFlowControl = 1; 648 kp->kp_ctrl_msg.usa19hs.txFlowControl = 0; 649 kp->kp_ctrl_msg.usa19hs.setRxFlowControl = 1; 650 kp->kp_ctrl_msg.usa19hs.rxFlowControl = 0; 651 kp->kp_ctrl_msg.usa19hs.rxForwardingTimeout = 0; 652 kp->kp_ctrl_msg.usa19hs.rxForwardingLength = 0; 653 654 break; 655 656 657 case KEYSPAN_USA49WLC_PID: 658 case KEYSPAN_USA49WG_PID: 659 keyspan_build_cmd_msg_usa49(kp, NULL); 660 kp->kp_ctrl_msg.usa49._txOn = 0; 661 kp->kp_ctrl_msg.usa49._txOff = 1; 662 kp->kp_ctrl_msg.usa49.txFlush = 0; 663 kp->kp_ctrl_msg.usa49.txBreak = 0; 664 kp->kp_ctrl_msg.usa49.rxOn = 0; 665 kp->kp_ctrl_msg.usa49.rxOff = 1; 666 kp->kp_ctrl_msg.usa49.rxFlush = 0; 667 kp->kp_ctrl_msg.usa49.rxForward = 0; 668 kp->kp_ctrl_msg.usa49.returnStatus = 0; 669 kp->kp_ctrl_msg.usa49.resetDataToggle = 0; 670 kp->kp_ctrl_msg.usa49.enablePort = 0; 671 kp->kp_ctrl_msg.usa49.disablePort = 1; 672 673 break; 674 675 default: 676 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 677 "keyspan_close_hw_port:" 678 "the device's product id can't be recognized"); 679 mutex_exit(&kp->kp_mutex); 680 681 return; 682 } 683 684 mutex_exit(&kp->kp_mutex); 685 /* send close port cmd to this port */ 686 if (keyspan_send_cmd(kp) != USB_SUCCESS) { 687 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, 688 "keyspan_close_hw_port: closing hw port, send cmd FAILED"); 689 } 690 691 /* blow away bulkin requests or pipe close will wait until timeout */ 692 switch (ksp->ks_dev_spec.id_product) { 693 case KEYSPAN_USA19HS_PID: 694 case KEYSPAN_USA49WLC_PID: 695 usb_pipe_reset(ksp->ks_dip, 696 kp->kp_datain_pipe.pipe_handle, 697 USB_FLAGS_SLEEP, NULL, NULL); 698 699 break; 700 case KEYSPAN_USA49WG_PID: 701 mutex_enter(&ksp->ks_mutex); 702 /* 703 * if only this port is opened, shared data in pipe 704 * can be reset. 705 */ 706 if (ksp->ks_datain_open_cnt == 1) { 707 mutex_exit(&ksp->ks_mutex); 708 709 usb_pipe_reset(ksp->ks_dip, 710 kp->kp_datain_pipe.pipe_handle, 711 USB_FLAGS_SLEEP, NULL, NULL); 712 } else { 713 mutex_exit(&ksp->ks_mutex); 714 } 715 716 break; 717 default: 718 USB_DPRINTF_L2(DPRINT_CLOSE, kp->kp_lh, 719 "keyspan_close_hw_port: the device's" 720 " product id can't be recognized"); 721 } 722 723 (void) keyspan_close_port_pipes(kp); 724 } 725 726 /* 727 * ds_close_port 728 */ 729 static int 730 keyspan_close_port(ds_hdl_t hdl, uint_t port_num) 731 { 732 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 733 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 734 735 if (port_num >= ksp->ks_dev_spec.port_cnt) { 736 737 return (USB_FAILURE); 738 } 739 USB_DPRINTF_L4(DPRINT_CLOSE, kp->kp_lh, "keyspan_close_port"); 740 741 sema_p(&ksp->ks_pipes_sema); 742 mutex_enter(&kp->kp_mutex); 743 kp->kp_no_more_reads = B_TRUE; 744 745 /* close hardware serial port */ 746 mutex_exit(&kp->kp_mutex); 747 748 keyspan_close_hw_port(kp); 749 mutex_enter(&kp->kp_mutex); 750 751 /* 752 * free resources and finalize state 753 */ 754 if (kp->kp_rx_mp) { 755 freemsg(kp->kp_rx_mp); 756 kp->kp_rx_mp = NULL; 757 } 758 if (kp->kp_tx_mp) { 759 freemsg(kp->kp_tx_mp); 760 kp->kp_tx_mp = NULL; 761 } 762 763 kp->kp_no_more_reads = B_FALSE; 764 kp->kp_state = KEYSPAN_PORT_CLOSED; 765 mutex_exit(&kp->kp_mutex); 766 767 keyspan_pm_set_idle(ksp); 768 769 sema_v(&ksp->ks_pipes_sema); 770 771 return (USB_SUCCESS); 772 } 773 774 /* 775 * power management 776 * 777 * ds_usb_power 778 */ 779 /*ARGSUSED*/ 780 static int 781 keyspan_usb_power(ds_hdl_t hdl, int comp, int level, int *new_state) 782 { 783 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 784 keyspan_pm_t *pm = ksp->ks_pm; 785 int rval; 786 787 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_usb_power"); 788 789 mutex_enter(&ksp->ks_mutex); 790 791 /* 792 * check if we are transitioning to a legal power level 793 */ 794 if (USB_DEV_PWRSTATE_OK(pm->pm_pwr_states, level)) { 795 USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh, "keyspan_usb_power:" 796 "illegal power level %d, pwr_states=%x", 797 level, pm->pm_pwr_states); 798 mutex_exit(&ksp->ks_mutex); 799 800 return (USB_FAILURE); 801 } 802 803 /* 804 * if we are about to raise power and asked to lower power, fail 805 */ 806 if (pm->pm_raise_power && (level < (int)pm->pm_cur_power)) { 807 mutex_exit(&ksp->ks_mutex); 808 809 return (USB_FAILURE); 810 } 811 812 switch (level) { 813 case USB_DEV_OS_PWR_OFF: 814 rval = keyspan_pwrlvl0(ksp); 815 816 break; 817 case USB_DEV_OS_PWR_1: 818 rval = keyspan_pwrlvl1(ksp); 819 820 break; 821 case USB_DEV_OS_PWR_2: 822 rval = keyspan_pwrlvl2(ksp); 823 824 break; 825 case USB_DEV_OS_FULL_PWR: 826 rval = keyspan_pwrlvl3(ksp); 827 /* 828 * If usbser dev_state is DISCONNECTED or SUSPENDED, it shows 829 * that the usb serial device is disconnected/suspended while it 830 * is under power down state, now the device is powered up 831 * before it is reconnected/resumed. xxx_pwrlvl3() will set dev 832 * state to ONLINE, we need to set the dev state back to 833 * DISCONNECTED/SUSPENDED. 834 */ 835 if ((rval == USB_SUCCESS) && 836 ((*new_state == USB_DEV_DISCONNECTED) || 837 (*new_state == USB_DEV_SUSPENDED))) { 838 ksp->ks_dev_state = *new_state; 839 } 840 841 break; 842 default: 843 ASSERT(0); /* cannot happen */ 844 } 845 846 *new_state = ksp->ks_dev_state; 847 mutex_exit(&ksp->ks_mutex); 848 849 return (rval); 850 } 851 852 853 /* 854 * ds_suspend 855 */ 856 static int 857 keyspan_suspend(ds_hdl_t hdl) 858 { 859 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 860 int state = USB_DEV_SUSPENDED; 861 862 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_suspend"); 863 864 /* 865 * If the device is suspended while it is under PWRED_DOWN state, we 866 * need to keep the PWRED_DOWN state so that it could be powered up 867 * later. In the mean while, usbser dev state will be changed to 868 * SUSPENDED state. 869 */ 870 mutex_enter(&ksp->ks_mutex); 871 if (ksp->ks_dev_state != USB_DEV_PWRED_DOWN) { 872 ksp->ks_dev_state = USB_DEV_SUSPENDED; 873 } 874 mutex_exit(&ksp->ks_mutex); 875 876 keyspan_disconnect_pipes(ksp); 877 878 return (state); 879 } 880 881 882 /* 883 * ds_resume 884 */ 885 static int 886 keyspan_resume(ds_hdl_t hdl) 887 { 888 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 889 int current_state; 890 int rval; 891 892 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_resume"); 893 894 mutex_enter(&ksp->ks_mutex); 895 current_state = ksp->ks_dev_state; 896 mutex_exit(&ksp->ks_mutex); 897 898 if (current_state != USB_DEV_ONLINE) { 899 rval = keyspan_restore_device_state(ksp); 900 } else { 901 rval = USB_SUCCESS; 902 } 903 904 return (rval); 905 } 906 907 908 /* 909 * ds_disconnect 910 */ 911 static int 912 keyspan_disconnect(ds_hdl_t hdl) 913 { 914 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 915 int state = USB_DEV_DISCONNECTED; 916 917 USB_DPRINTF_L4(DPRINT_HOTPLUG, ksp->ks_lh, "keyspan_disconnect"); 918 919 /* 920 * If the device is disconnected while it is under PWRED_DOWN state, we 921 * need to keep the PWRED_DOWN state so that it could be powered up 922 * later. In the mean while, usbser dev state will be changed to 923 * DISCONNECTED state. 924 */ 925 mutex_enter(&ksp->ks_mutex); 926 if (ksp->ks_dev_state != USB_DEV_PWRED_DOWN) { 927 ksp->ks_dev_state = USB_DEV_DISCONNECTED; 928 } 929 mutex_exit(&ksp->ks_mutex); 930 931 keyspan_disconnect_pipes(ksp); 932 933 return (state); 934 } 935 936 937 /* 938 * ds_reconnect 939 */ 940 static int 941 keyspan_reconnect(ds_hdl_t hdl) 942 { 943 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 944 945 USB_DPRINTF_L4(DPRINT_HOTPLUG, ksp->ks_lh, "keyspan_reconnect"); 946 947 return (keyspan_restore_device_state(ksp)); 948 } 949 950 /* 951 * ds_set_port_params 952 */ 953 static int 954 keyspan_set_port_params(ds_hdl_t hdl, uint_t port_num, ds_port_params_t *tp) 955 { 956 int cnt = tp->tp_cnt; 957 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 958 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 959 960 ASSERT(port_num < ksp->ks_dev_spec.port_cnt); 961 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, 962 "keyspan_set_port_params: port: %d params", cnt); 963 964 if (cnt <= 0) { 965 966 return (USB_SUCCESS); 967 } 968 969 mutex_enter(&kp->kp_mutex); 970 ASSERT((kp->kp_state == KEYSPAN_PORT_OPENING) || 971 (kp->kp_state == KEYSPAN_PORT_OPEN)); 972 keyspan_build_cmd_msg(kp, tp); 973 mutex_exit(&kp->kp_mutex); 974 975 if (keyspan_send_cmd(kp) != USB_SUCCESS) { 976 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, 977 "keyspan_send_cmd() FAILED"); 978 979 return (USB_FAILURE); 980 } 981 982 return (USB_SUCCESS); 983 } 984 985 986 /* 987 * ds_set_modem_ctl 988 */ 989 static int 990 keyspan_set_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int val) 991 { 992 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 993 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 994 995 ASSERT(port_num < ksp->ks_dev_spec.port_cnt); 996 997 mutex_enter(&kp->kp_mutex); 998 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_set_modem_ctl: " 999 "mask=%x, val=%x", mask, val); 1000 1001 keyspan_build_cmd_msg(kp, NULL); 1002 1003 switch (ksp->ks_dev_spec.id_product) { 1004 case KEYSPAN_USA19HS_PID: 1005 if (mask & TIOCM_RTS) { 1006 1007 kp->kp_ctrl_msg.usa19hs.setRts = 0x01; 1008 1009 if (val & TIOCM_RTS) { 1010 kp->kp_ctrl_msg.usa19hs.rts = 0x1; 1011 } else { 1012 kp->kp_ctrl_msg.usa19hs.rts = 0x0; 1013 } 1014 1015 } else { 1016 kp->kp_ctrl_msg.usa19hs.setRts = 0x0; 1017 } 1018 1019 if (mask & TIOCM_DTR) { 1020 kp->kp_ctrl_msg.usa19hs.setDtr = 0x01; 1021 1022 if (val & TIOCM_DTR) { 1023 kp->kp_ctrl_msg.usa19hs.dtr = 0x1; 1024 } else { 1025 kp->kp_ctrl_msg.usa19hs.dtr = 0x0; 1026 } 1027 1028 } else { 1029 kp->kp_ctrl_msg.usa19hs.setDtr = 0x0; 1030 } 1031 1032 break; 1033 1034 1035 case KEYSPAN_USA49WLC_PID: 1036 case KEYSPAN_USA49WG_PID: 1037 if (mask & TIOCM_RTS) { 1038 1039 kp->kp_ctrl_msg.usa49.setRts = 0x1; 1040 1041 if (val & TIOCM_RTS) { 1042 kp->kp_ctrl_msg.usa49.rts = 0x1; 1043 } else { 1044 kp->kp_ctrl_msg.usa49.rts = 0x0; 1045 } 1046 1047 } else { 1048 kp->kp_ctrl_msg.usa49.setRts = 0x0; 1049 } 1050 1051 if (mask & TIOCM_DTR) { 1052 kp->kp_ctrl_msg.usa49.setDtr = 0x1; 1053 1054 if (val & TIOCM_DTR) { 1055 kp->kp_ctrl_msg.usa49.dtr = 0x1; 1056 } else { 1057 kp->kp_ctrl_msg.usa49.dtr = 0x0; 1058 } 1059 1060 } else { 1061 kp->kp_ctrl_msg.usa49.setDtr = 0x0; 1062 } 1063 1064 break; 1065 1066 default: 1067 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, 1068 "keyspan_get_modem_ctl:" 1069 "the device's product id can't be recognized"); 1070 mutex_exit(&kp->kp_mutex); 1071 1072 return (USB_FAILURE); 1073 } 1074 1075 mutex_exit(&kp->kp_mutex); 1076 1077 if (keyspan_send_cmd(kp) != USB_SUCCESS) { 1078 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, 1079 "keyspan_send_cmd() FAILED"); 1080 1081 return (USB_FAILURE); 1082 } 1083 1084 return (USB_SUCCESS); 1085 } 1086 1087 /* 1088 * ds_get_modem_ctl 1089 */ 1090 static int 1091 keyspan_get_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int *valp) 1092 { 1093 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 1094 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 1095 int val = 0; 1096 1097 ASSERT(port_num < ksp->ks_dev_spec.port_cnt); 1098 1099 mutex_enter(&kp->kp_mutex); 1100 1101 /* 1102 * rts and dtr are not in status_msg, but we can get it from 1103 * status_flag since it represents what we set the device last time. 1104 */ 1105 if (kp->kp_status_flag & KEYSPAN_PORT_RTS) { 1106 val |= TIOCM_RTS; 1107 } 1108 if (kp->kp_status_flag & KEYSPAN_PORT_DTR) { 1109 val |= TIOCM_DTR; 1110 } 1111 1112 /* usbser don't deal with TIOCM_RI status */ 1113 switch (ksp->ks_dev_spec.id_product) { 1114 case KEYSPAN_USA19HS_PID: 1115 if (kp->kp_status_msg.usa19hs.dcd) { 1116 val |= TIOCM_CD; 1117 } 1118 if (kp->kp_status_msg.usa19hs.cts) { 1119 val |= TIOCM_CTS; 1120 } 1121 if (kp->kp_status_msg.usa19hs.dsr) { 1122 val |= TIOCM_DSR; 1123 } 1124 break; 1125 1126 1127 case KEYSPAN_USA49WLC_PID: 1128 case KEYSPAN_USA49WG_PID: 1129 if (kp->kp_status_msg.usa49.dcd) { 1130 val |= TIOCM_CD; 1131 } 1132 if (kp->kp_status_msg.usa49.cts) { 1133 val |= TIOCM_CTS; 1134 } 1135 if (kp->kp_status_msg.usa49.dsr) { 1136 val |= TIOCM_DSR; 1137 } 1138 break; 1139 1140 default: 1141 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 1142 "keyspan_get_modem_ctl:" 1143 "the device's product id can't be recognized"); 1144 mutex_exit(&kp->kp_mutex); 1145 1146 return (USB_FAILURE); 1147 } 1148 1149 *valp = val & mask; 1150 1151 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_get_modem_ctl:" 1152 "success. status_flag = %x, val=0%o", 1153 kp->kp_status_flag, *valp); 1154 1155 mutex_exit(&kp->kp_mutex); 1156 1157 return (USB_SUCCESS); 1158 } 1159 1160 1161 /* 1162 * ds_break_ctl 1163 */ 1164 static int 1165 keyspan_break_ctl(ds_hdl_t hdl, uint_t port_num, int ctl) 1166 { 1167 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 1168 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 1169 int is_break; 1170 int rval = USB_SUCCESS; 1171 1172 ASSERT(port_num < ksp->ks_dev_spec.port_cnt); 1173 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, 1174 "keyspan_break_ctl: ctl = %s", (ctl == DS_ON) ? "on" : "off"); 1175 1176 mutex_enter(&kp->kp_mutex); 1177 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN); 1178 ASSERT(ctl == DS_ON || ctl == DS_OFF); 1179 1180 is_break = kp->kp_status_flag & KEYSPAN_PORT_TXBREAK; 1181 1182 if ((ctl == DS_ON) && !is_break) { 1183 1184 keyspan_build_cmd_msg(kp, NULL); 1185 1186 switch (ksp->ks_dev_spec.id_product) { 1187 case KEYSPAN_USA19HS_PID: 1188 kp->kp_ctrl_msg.usa19hs.txBreak = 1; 1189 1190 break; 1191 1192 case KEYSPAN_USA49WLC_PID: 1193 case KEYSPAN_USA49WG_PID: 1194 kp->kp_ctrl_msg.usa49.txBreak = 1; 1195 1196 break; 1197 1198 default: 1199 mutex_exit(&kp->kp_mutex); 1200 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 1201 "keyspan_break_ctl:" 1202 "the device's product id can't be recognized"); 1203 1204 return (USB_FAILURE); 1205 } 1206 1207 mutex_exit(&kp->kp_mutex); 1208 rval = keyspan_send_cmd(kp); 1209 return (rval); 1210 } 1211 1212 if ((ctl == DS_OFF) && is_break) { 1213 keyspan_build_cmd_msg(kp, NULL); 1214 1215 switch (ksp->ks_dev_spec.id_product) { 1216 case KEYSPAN_USA19HS_PID: 1217 kp->kp_ctrl_msg.usa19hs.txBreak = 0; 1218 1219 break; 1220 1221 case KEYSPAN_USA49WLC_PID: 1222 case KEYSPAN_USA49WG_PID: 1223 kp->kp_ctrl_msg.usa49._txOn = 1; 1224 kp->kp_ctrl_msg.usa49.txBreak = 0; 1225 1226 break; 1227 1228 default: 1229 mutex_exit(&kp->kp_mutex); 1230 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 1231 "keyspan_break_ctl:" 1232 "the device's product id can't be recognized"); 1233 1234 return (USB_FAILURE); 1235 } 1236 1237 mutex_exit(&kp->kp_mutex); 1238 rval = keyspan_send_cmd(kp); 1239 if (rval == USB_SUCCESS) { 1240 mutex_enter(&kp->kp_mutex); 1241 1242 /* resume transmit */ 1243 keyspan_tx_start(kp, NULL); 1244 mutex_exit(&kp->kp_mutex); 1245 } 1246 1247 return (rval); 1248 } 1249 1250 mutex_exit(&kp->kp_mutex); 1251 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, 1252 "keyspan_break_ctl: not necessary to set break, is_break = %d", 1253 is_break); 1254 1255 return (rval); 1256 } 1257 1258 1259 /* 1260 * ds_loopback 1261 */ 1262 static int 1263 keyspan_loopback(ds_hdl_t hdl, uint_t port_num, int ctl) 1264 { 1265 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 1266 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 1267 int is_loop; 1268 int rval = USB_SUCCESS; 1269 1270 ASSERT(port_num < ksp->ks_dev_spec.port_cnt); 1271 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, 1272 "keyspan_loopback: %s", (ctl == DS_ON) ? "on" : "off"); 1273 1274 mutex_enter(&kp->kp_mutex); 1275 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN); 1276 ASSERT(ctl == DS_ON || ctl == DS_OFF); 1277 1278 /* check bit indicating internal loopback state */ 1279 is_loop = kp->kp_status_flag & KEYSPAN_PORT_LOOPBACK; 1280 1281 if ((ctl == DS_ON) && !is_loop) { 1282 1283 keyspan_build_cmd_msg(kp, NULL); 1284 switch (ksp->ks_dev_spec.id_product) { 1285 case KEYSPAN_USA19HS_PID: 1286 kp->kp_ctrl_msg.usa19hs.loopbackMode = 0; 1287 1288 break; 1289 1290 case KEYSPAN_USA49WLC_PID: 1291 case KEYSPAN_USA49WG_PID: 1292 kp->kp_ctrl_msg.usa49.loopbackMode = 0; 1293 1294 break; 1295 1296 default: 1297 mutex_exit(&kp->kp_mutex); 1298 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 1299 "keyspan_loopback:" 1300 "the device's product id can't be recognized"); 1301 1302 return (USB_FAILURE); 1303 } 1304 mutex_exit(&kp->kp_mutex); 1305 rval = keyspan_send_cmd(kp); 1306 } else if ((ctl == DS_OFF) && is_loop) { 1307 1308 keyspan_build_cmd_msg(kp, NULL); 1309 switch (ksp->ks_dev_spec.id_product) { 1310 case KEYSPAN_USA19HS_PID: 1311 kp->kp_ctrl_msg.usa19hs.loopbackMode = 1; 1312 1313 break; 1314 1315 case KEYSPAN_USA49WLC_PID: 1316 case KEYSPAN_USA49WG_PID: 1317 kp->kp_ctrl_msg.usa49.loopbackMode = 1; 1318 1319 break; 1320 1321 default: 1322 mutex_exit(&kp->kp_mutex); 1323 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 1324 "keyspan_loopback:" 1325 "the device's product id can't be recognized"); 1326 1327 return (USB_FAILURE); 1328 } 1329 mutex_exit(&kp->kp_mutex); 1330 rval = keyspan_send_cmd(kp); 1331 } else { 1332 mutex_exit(&kp->kp_mutex); 1333 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, 1334 "keyspan_loopback: not necessary to set loopback," 1335 "is_loop = %d", is_loop); 1336 } 1337 1338 return (rval); 1339 } 1340 1341 1342 /* 1343 * ds_tx 1344 */ 1345 static int 1346 keyspan_tx(ds_hdl_t hdl, uint_t port_num, mblk_t *mp) 1347 { 1348 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 1349 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 1350 int xferd; 1351 1352 ASSERT(port_num < ksp->ks_dev_spec.port_cnt); 1353 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_tx"); 1354 1355 /* 1356 * sanity checks 1357 */ 1358 if (mp == NULL) { 1359 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, "keyspan_tx: mp=NULL"); 1360 1361 return (USB_SUCCESS); 1362 } 1363 1364 kp = &ksp->ks_ports[port_num]; 1365 1366 mutex_enter(&kp->kp_mutex); 1367 1368 keyspan_put_tail(&kp->kp_tx_mp, mp); /* add to the chain */ 1369 1370 keyspan_tx_start(kp, &xferd); /* go! */ 1371 1372 mutex_exit(&kp->kp_mutex); 1373 1374 return (USB_SUCCESS); 1375 } 1376 1377 1378 /* 1379 * ds_rx. the real data receiving is in keyspan_open_hw_port 1380 */ 1381 static mblk_t * 1382 keyspan_rx(ds_hdl_t hdl, uint_t port_num) 1383 { 1384 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 1385 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 1386 mblk_t *mp; 1387 1388 ASSERT(port_num < ksp->ks_dev_spec.port_cnt); 1389 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_rx"); 1390 1391 mutex_enter(&kp->kp_mutex); 1392 mp = kp->kp_rx_mp; 1393 kp->kp_rx_mp = NULL; 1394 mutex_exit(&kp->kp_mutex); 1395 1396 return (mp); 1397 } 1398 1399 1400 /* 1401 * ds_stop 1402 */ 1403 static void 1404 keyspan_stop(ds_hdl_t hdl, uint_t port_num, int dir) 1405 { 1406 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 1407 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 1408 1409 ASSERT(port_num < ksp->ks_dev_spec.port_cnt); 1410 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_stop"); 1411 1412 if (dir & DS_TX) { 1413 mutex_enter(&kp->kp_mutex); 1414 kp->kp_flags |= KEYSPAN_PORT_TX_STOPPED; 1415 mutex_exit(&kp->kp_mutex); 1416 } 1417 } 1418 1419 1420 /* 1421 * ds_start 1422 */ 1423 static void 1424 keyspan_start(ds_hdl_t hdl, uint_t port_num, int dir) 1425 { 1426 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 1427 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 1428 1429 ASSERT(port_num < ksp->ks_dev_spec.port_cnt); 1430 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_start"); 1431 1432 if (dir & DS_TX) { 1433 mutex_enter(&kp->kp_mutex); 1434 if (kp->kp_flags & KEYSPAN_PORT_TX_STOPPED) { 1435 kp->kp_flags &= ~KEYSPAN_PORT_TX_STOPPED; 1436 keyspan_tx_start(kp, NULL); 1437 } 1438 mutex_exit(&kp->kp_mutex); 1439 } 1440 } 1441 1442 1443 /* 1444 * ds_fifo_flush 1445 * send flush cmd and wait for completion, then turn off the flush. 1446 */ 1447 static int 1448 keyspan_fifo_flush(ds_hdl_t hdl, uint_t port_num, int dir) 1449 { 1450 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 1451 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 1452 1453 ASSERT(port_num < ksp->ks_dev_spec.port_cnt); 1454 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, 1455 "keyspan_fifo_flush: dir=%x", dir); 1456 1457 mutex_enter(&kp->kp_mutex); 1458 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN); 1459 1460 /* discard the data in DSD buffers */ 1461 if ((dir & DS_TX) && kp->kp_tx_mp) { 1462 freemsg(kp->kp_tx_mp); 1463 kp->kp_tx_mp = NULL; 1464 } 1465 if ((dir & DS_RX) && kp->kp_rx_mp) { 1466 freemsg(kp->kp_rx_mp); 1467 kp->kp_rx_mp = NULL; 1468 } 1469 1470 mutex_exit(&kp->kp_mutex); 1471 1472 return (USB_SUCCESS); 1473 } 1474 1475 /* 1476 * ds_fifo_drain 1477 * 1478 * it is the caller's responsibility to cease submitting new tx data 1479 * while this function executes 1480 */ 1481 static int 1482 keyspan_fifo_drain(ds_hdl_t hdl, uint_t port_num, int timeout) 1483 { 1484 keyspan_state_t *ksp = (keyspan_state_t *)hdl; 1485 keyspan_port_t *kp = &ksp->ks_ports[port_num]; 1486 int rval = USB_SUCCESS; 1487 1488 ASSERT(port_num < ksp->ks_dev_spec.port_cnt); 1489 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, 1490 "keyspan_fifo_drain, timeout = %d", timeout); 1491 1492 mutex_enter(&kp->kp_mutex); 1493 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN); 1494 1495 /* wait until local data drains */ 1496 if (keyspan_wait_tx_drain(kp, 0) != USB_SUCCESS) { 1497 mutex_exit(&kp->kp_mutex); 1498 1499 return (USB_FAILURE); 1500 } 1501 mutex_exit(&kp->kp_mutex); 1502 1503 /* wait until hw fifo drains */ 1504 delay(drv_usectohz(500*1000)); 1505 1506 return (rval); 1507 } 1508 1509 1510 /* 1511 * configuration routines 1512 * ---------------------- 1513 * 1514 */ 1515 1516 /* 1517 * free state structure 1518 */ 1519 static void 1520 keyspan_free_soft_state(keyspan_state_t *ksp) 1521 { 1522 kmem_free(ksp, sizeof (keyspan_state_t)); 1523 } 1524 1525 1526 /* 1527 * register/unregister USBA client 1528 */ 1529 static int 1530 keyspan_usb_register(keyspan_state_t *ksp) 1531 { 1532 int rval; 1533 1534 rval = usb_client_attach(ksp->ks_dip, USBDRV_VERSION, 0); 1535 if (rval == USB_SUCCESS) { 1536 rval = usb_get_dev_data(ksp->ks_dip, &ksp->ks_dev_data, 1537 USB_PARSE_LVL_IF, 0); 1538 if (rval == USB_SUCCESS) { 1539 ksp->ks_lh = 1540 usb_alloc_log_hdl(ksp->ks_dip, "keyspan[*].", 1541 &keyspan_errlevel, &keyspan_errmask, 1542 &keyspan_instance_debug, 0); 1543 1544 ksp->ks_def_pipe.pipe_handle = 1545 ksp->ks_dev_data->dev_default_ph; 1546 ksp->ks_def_pipe.pipe_ksp = ksp; 1547 ksp->ks_def_pipe.pipe_lh = ksp->ks_lh; 1548 } 1549 } 1550 1551 return (rval); 1552 } 1553 1554 1555 static void 1556 keyspan_usb_unregister(keyspan_state_t *ksp) 1557 { 1558 usb_free_log_hdl(ksp->ks_lh); 1559 ksp->ks_lh = NULL; 1560 usb_client_detach(ksp->ks_dip, ksp->ks_dev_data); 1561 ksp->ks_def_pipe.pipe_handle = NULL; 1562 ksp->ks_dev_data = NULL; 1563 } 1564 1565 1566 /* 1567 * init/fini soft state during attach 1568 */ 1569 static void 1570 keyspan_init_sync_objs(keyspan_state_t *ksp) 1571 { 1572 mutex_init(&ksp->ks_mutex, NULL, MUTEX_DRIVER, 1573 ksp->ks_dev_data->dev_iblock_cookie); 1574 sema_init(&ksp->ks_pipes_sema, 1, NULL, SEMA_DRIVER, NULL); 1575 } 1576 1577 1578 static void 1579 keyspan_fini_sync_objs(keyspan_state_t *ksp) 1580 { 1581 mutex_destroy(&ksp->ks_mutex); 1582 sema_destroy(&ksp->ks_pipes_sema); 1583 } 1584 1585 1586 /* 1587 * device specific attributes 1588 */ 1589 static int 1590 keyspan_attach_dev(keyspan_state_t *ksp) 1591 { 1592 1593 mutex_enter(&ksp->ks_mutex); 1594 switch (ksp->ks_dev_data->dev_descr->idProduct) { 1595 case KEYSPAN_USA19HS_PID: 1596 ksp->ks_dev_spec.id_product = KEYSPAN_USA19HS_PID; 1597 ksp->ks_dev_spec.port_cnt = 1; 1598 ksp->ks_dev_spec.ctrl_ep_addr = 0x02; 1599 ksp->ks_dev_spec.stat_ep_addr = 0x82; 1600 ksp->ks_dev_spec.dataout_ep_addr[0] = 0x01; 1601 ksp->ks_dev_spec.datain_ep_addr[0] = 0x81; 1602 1603 break; 1604 1605 case KEYSPAN_USA49WLC_PID: 1606 ksp->ks_dev_spec.id_product = KEYSPAN_USA49WLC_PID; 1607 ksp->ks_dev_spec.port_cnt = 4; 1608 ksp->ks_dev_spec.ctrl_ep_addr = 0x07; 1609 ksp->ks_dev_spec.stat_ep_addr = 0x87; 1610 ksp->ks_dev_spec.dataout_ep_addr[0] = 0x01; 1611 ksp->ks_dev_spec.dataout_ep_addr[1] = 0x02; 1612 ksp->ks_dev_spec.dataout_ep_addr[2] = 0x03; 1613 ksp->ks_dev_spec.dataout_ep_addr[3] = 0x04; 1614 ksp->ks_dev_spec.datain_ep_addr[0] = 0x81; 1615 ksp->ks_dev_spec.datain_ep_addr[1] = 0x82; 1616 ksp->ks_dev_spec.datain_ep_addr[2] = 0x83; 1617 ksp->ks_dev_spec.datain_ep_addr[3] = 0x84; 1618 1619 break; 1620 1621 case KEYSPAN_USA49WG_PID: 1622 ksp->ks_dev_spec.id_product = KEYSPAN_USA49WG_PID; 1623 ksp->ks_dev_spec.port_cnt = 4; 1624 ksp->ks_dev_spec.stat_ep_addr = 0x81; 1625 ksp->ks_dev_spec.dataout_ep_addr[0] = 0x01; 1626 ksp->ks_dev_spec.dataout_ep_addr[1] = 0x02; 1627 ksp->ks_dev_spec.dataout_ep_addr[2] = 0x04; 1628 ksp->ks_dev_spec.dataout_ep_addr[3] = 0x06; 1629 ksp->ks_dev_spec.datain_ep_addr[0] = 0x88; 1630 ksp->ks_dev_spec.datain_ep_addr[1] = 0x88; 1631 ksp->ks_dev_spec.datain_ep_addr[2] = 0x88; 1632 ksp->ks_dev_spec.datain_ep_addr[3] = 0x88; 1633 1634 break; 1635 1636 default: 1637 mutex_exit(&ksp->ks_mutex); 1638 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 1639 "keyspan_attach_dev:" 1640 "the device's product id can't be recognized"); 1641 1642 return (USB_FAILURE); 1643 } 1644 1645 mutex_exit(&ksp->ks_mutex); 1646 1647 return (USB_SUCCESS); 1648 } 1649 1650 /* 1651 * allocate and initialize per port resources. 1652 */ 1653 static void 1654 keyspan_attach_ports(keyspan_state_t *ksp) 1655 { 1656 int i; 1657 keyspan_port_t *kp; 1658 1659 ksp->ks_ports = kmem_zalloc(ksp->ks_dev_spec.port_cnt * 1660 sizeof (keyspan_port_t), KM_SLEEP); 1661 1662 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) { 1663 kp = &ksp->ks_ports[i]; 1664 kp->kp_port_num = i; 1665 kp->kp_ksp = ksp; 1666 1667 (void) sprintf(kp->kp_lh_name, "keyspan[%d].", i); 1668 kp->kp_lh = usb_alloc_log_hdl(ksp->ks_dip, kp->kp_lh_name, 1669 &keyspan_errlevel, &keyspan_errmask, 1670 &keyspan_instance_debug, 0); 1671 1672 kp->kp_state = KEYSPAN_PORT_CLOSED; 1673 mutex_init(&kp->kp_mutex, NULL, MUTEX_DRIVER, 1674 ksp->ks_dev_data->dev_iblock_cookie); 1675 cv_init(&kp->kp_tx_cv, NULL, CV_DRIVER, NULL); 1676 } 1677 } 1678 1679 1680 /* 1681 * free per port resources 1682 */ 1683 static void 1684 keyspan_detach_ports(keyspan_state_t *ksp) 1685 { 1686 int i; 1687 keyspan_port_t *kp; 1688 1689 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) { 1690 kp = &ksp->ks_ports[i]; 1691 if (kp->kp_state != KEYSPAN_PORT_NOT_INIT) { 1692 ASSERT(kp->kp_state == KEYSPAN_PORT_CLOSED); 1693 1694 mutex_destroy(&kp->kp_mutex); 1695 cv_destroy(&kp->kp_tx_cv); 1696 usb_free_log_hdl(kp->kp_lh); 1697 } 1698 } 1699 kmem_free(ksp->ks_ports, 1700 ksp->ks_dev_spec.port_cnt * sizeof (keyspan_port_t)); 1701 } 1702 1703 static void 1704 keyspan_init_port_params(keyspan_state_t *ksp) 1705 { 1706 int i; 1707 size_t sz; 1708 uint_t read_len; 1709 uint_t write_len; 1710 1711 /* the max data len of every bulk in req. */ 1712 if (usb_pipe_get_max_bulk_transfer_size(ksp->ks_dip, &sz) == 1713 USB_SUCCESS) { 1714 if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) { 1715 read_len = min(sz, KEYSPAN_BULKIN_MAX_LEN_49WG); 1716 } else { 1717 read_len = min(sz, KEYSPAN_BULKIN_MAX_LEN); 1718 } 1719 } else { 1720 if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) { 1721 read_len = KEYSPAN_BULKIN_MAX_LEN_49WG; 1722 } else { 1723 read_len = KEYSPAN_BULKIN_MAX_LEN; 1724 } 1725 } 1726 1727 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) { 1728 ksp->ks_ports[i].kp_read_len = read_len; 1729 /* the max data len of every bulk out req. */ 1730 switch (ksp->ks_dev_spec.id_product) { 1731 case KEYSPAN_USA19HS_PID: 1732 ksp->ks_ports[i].kp_write_len = 1733 KEYSPAN_BULKOUT_MAX_LEN_19HS; 1734 1735 break; 1736 case KEYSPAN_USA49WLC_PID: 1737 ksp->ks_ports[i].kp_write_len = 1738 KEYSPAN_BULKOUT_MAX_LEN_49WLC; 1739 1740 break; 1741 case KEYSPAN_USA49WG_PID: 1742 /* 1743 * USA49WG port0 uses intr out pipe send data while 1744 * other ports use bulk out pipes, so port0's max 1745 * packet length for "bulk out" is different from other 1746 * ports' while the same as USA49WLC. 1747 */ 1748 write_len = ((i == 0) ? KEYSPAN_BULKOUT_MAX_LEN_49WLC : 1749 KEYSPAN_BULKOUT_MAX_LEN_49WG); 1750 ksp->ks_ports[i].kp_write_len = write_len; 1751 1752 break; 1753 default: 1754 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 1755 "keyspan_init_port_params:" 1756 "the device's product id can't be recognized"); 1757 1758 return; 1759 } 1760 } 1761 } 1762 1763 1764 /* 1765 * free descriptor tree 1766 */ 1767 static void 1768 keyspan_free_descr_tree(keyspan_state_t *ksp) 1769 { 1770 usb_free_descr_tree(ksp->ks_dip, ksp->ks_dev_data); 1771 1772 } 1773 1774 1775 /* 1776 * register/unregister USB event callbacks 1777 */ 1778 static int 1779 keyspan_register_events(keyspan_state_t *ksp) 1780 { 1781 return (usb_register_event_cbs(ksp->ks_dip, ksp->ks_usb_events, 0)); 1782 } 1783 1784 1785 static void 1786 keyspan_unregister_events(keyspan_state_t *ksp) 1787 { 1788 usb_unregister_event_cbs(ksp->ks_dip, ksp->ks_usb_events); 1789 } 1790 1791 1792 static void 1793 keyspan_set_dev_state_online(keyspan_state_t *ksp) 1794 { 1795 ksp->ks_dev_state = USB_DEV_ONLINE; 1796 } 1797 1798 /* 1799 * send command to the port and save the params after its completion for 1800 * USA19HS and USA49WLC 1801 */ 1802 int 1803 keyspan_send_cmd_usa49(keyspan_port_t *kp) 1804 { 1805 keyspan_state_t *ksp = kp->kp_ksp; 1806 mblk_t *mp; 1807 int rval = USB_SUCCESS; 1808 int size; 1809 usb_bulk_req_t *br; 1810 1811 ASSERT(!mutex_owned(&kp->kp_mutex)); 1812 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_send_cmd_usa49"); 1813 1814 switch (ksp->ks_dev_spec.id_product) { 1815 case KEYSPAN_USA19HS_PID: 1816 size = sizeof (keyspan_usa19hs_port_ctrl_msg_t); 1817 1818 break; 1819 1820 1821 case KEYSPAN_USA49WLC_PID: 1822 size = sizeof (keyspan_usa49_port_ctrl_msg_t); 1823 1824 break; 1825 1826 default: 1827 USB_DPRINTF_L2(DPRINT_CTLOP, ksp->ks_lh, 1828 "keyspan_send_cmd_usa49:" 1829 "the device's product id can't be recognized"); 1830 return (USB_FAILURE); 1831 } 1832 1833 if ((mp = allocb(size, BPRI_LO)) == NULL) { 1834 1835 return (USB_FAILURE); 1836 } 1837 bcopy(&kp->kp_ctrl_msg, mp->b_rptr, size); 1838 1839 br = usb_alloc_bulk_req(ksp->ks_dip, 0, USB_FLAGS_SLEEP); 1840 br->bulk_len = size; 1841 br->bulk_data = mp; 1842 br->bulk_timeout = KEYSPAN_BULK_TIMEOUT; 1843 br->bulk_client_private = (void *)kp; 1844 br->bulk_attributes = USB_ATTRS_AUTOCLEARING; 1845 1846 rval = usb_pipe_bulk_xfer(ksp->ks_ctrlout_pipe.pipe_handle, br, 1847 USB_FLAGS_SLEEP); 1848 if (rval == USB_SUCCESS) { 1849 mutex_enter(&kp->kp_mutex); 1850 keyspan_save_port_params(kp); 1851 mutex_exit(&kp->kp_mutex); 1852 } else { 1853 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, "keyspan_send_cmd_usa49" 1854 ": failure, rval=%d", rval); 1855 } 1856 1857 usb_free_bulk_req(br); 1858 1859 return (rval); 1860 } 1861 1862 /* 1863 * send command to the port and save the params after its completion for 1864 * USA_49WG only 1865 */ 1866 int 1867 keyspan_send_cmd_usa49wg(keyspan_port_t *kp) 1868 { 1869 keyspan_state_t *ksp = kp->kp_ksp; 1870 mblk_t *mp; 1871 int rval = USB_SUCCESS; 1872 int size = sizeof (keyspan_usa49_port_ctrl_msg_t); 1873 usb_cb_flags_t cb_flags; 1874 usb_cr_t cr; 1875 usb_ctrl_setup_t setup; 1876 1877 ASSERT(!mutex_owned(&kp->kp_mutex)); 1878 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_send_cmd_usa49wg"); 1879 1880 if ((mp = allocb(size, BPRI_LO)) == NULL) { 1881 1882 return (USB_FAILURE); 1883 } 1884 bcopy(&kp->kp_ctrl_msg, mp->b_rptr, size); 1885 1886 setup.bmRequestType = USB_DEV_REQ_TYPE_VENDOR; 1887 setup.bRequest = KEYSPAN_SET_CONTROL_REQUEST; 1888 setup.wValue = 0; 1889 setup.wIndex = 0; 1890 setup.wLength = size; 1891 setup.attrs = 0; 1892 1893 rval = usb_pipe_ctrl_xfer_wait(ksp->ks_def_pipe.pipe_handle, &setup, 1894 &mp, &cr, &cb_flags, 0); 1895 1896 if (rval == USB_SUCCESS) { 1897 mutex_enter(&kp->kp_mutex); 1898 keyspan_save_port_params(kp); 1899 mutex_exit(&kp->kp_mutex); 1900 } else { 1901 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, 1902 "keyspan_send_cmd_usa49wg: failure, rval=%d", rval); 1903 } 1904 if (mp) { 1905 freemsg(mp); 1906 } 1907 1908 return (rval); 1909 } 1910 1911 /* 1912 * send command to the port and save the params after its completion 1913 */ 1914 int 1915 keyspan_send_cmd(keyspan_port_t *kp) 1916 { 1917 keyspan_state_t *ksp = kp->kp_ksp; 1918 int rval = USB_FAILURE; 1919 1920 switch (ksp->ks_dev_spec.id_product) { 1921 case KEYSPAN_USA19HS_PID: 1922 case KEYSPAN_USA49WLC_PID: 1923 rval = keyspan_send_cmd_usa49(kp); 1924 1925 break; 1926 case KEYSPAN_USA49WG_PID: 1927 rval = keyspan_send_cmd_usa49wg(kp); 1928 1929 break; 1930 default: 1931 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, 1932 "keyspan_send_cmd: " 1933 "the device's product id can't be recognized"); 1934 } 1935 1936 if (rval != USB_SUCCESS) { 1937 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, 1938 "keyspan_send_cmd() FAILED"); 1939 1940 return (rval); 1941 } 1942 1943 return (USB_SUCCESS); 1944 1945 } 1946 1947 /* 1948 * hotplug 1949 * ------- 1950 * 1951 * restore device state after CPR resume or reconnect 1952 */ 1953 static int 1954 keyspan_restore_device_state(keyspan_state_t *ksp) 1955 { 1956 int state; 1957 1958 mutex_enter(&ksp->ks_mutex); 1959 state = ksp->ks_dev_state; 1960 mutex_exit(&ksp->ks_mutex); 1961 1962 if ((state != USB_DEV_DISCONNECTED) && (state != USB_DEV_SUSPENDED)) { 1963 1964 return (state); 1965 } 1966 1967 if (usb_check_same_device(ksp->ks_dip, ksp->ks_lh, USB_LOG_L0, 1968 DPRINT_MASK_ALL, USB_CHK_ALL, NULL) != USB_SUCCESS) { 1969 mutex_enter(&ksp->ks_mutex); 1970 state = ksp->ks_dev_state = USB_DEV_DISCONNECTED; 1971 mutex_exit(&ksp->ks_mutex); 1972 1973 return (state); 1974 } 1975 1976 if (state == USB_DEV_DISCONNECTED) { 1977 USB_DPRINTF_L0(DPRINT_HOTPLUG, ksp->ks_lh, 1978 "device has been reconnected but data may have been lost"); 1979 } 1980 1981 if (keyspan_reconnect_pipes(ksp) != USB_SUCCESS) { 1982 1983 return (state); 1984 } 1985 1986 /* 1987 * init device state 1988 */ 1989 mutex_enter(&ksp->ks_mutex); 1990 state = ksp->ks_dev_state = USB_DEV_ONLINE; 1991 ksp->ks_reconnect_flag = 1; 1992 mutex_exit(&ksp->ks_mutex); 1993 1994 /* 1995 * now restore each open port 1996 */ 1997 (void) keyspan_restore_ports_state(ksp); 1998 1999 return (state); 2000 } 2001 2002 /* 2003 * restore ports state after CPR resume or reconnect 2004 */ 2005 static int 2006 keyspan_restore_ports_state(keyspan_state_t *ksp) 2007 { 2008 keyspan_port_t *kp; 2009 int rval = USB_SUCCESS; 2010 int err; 2011 int i; 2012 2013 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) { 2014 kp = &ksp->ks_ports[i]; 2015 /* 2016 * only care about open ports 2017 */ 2018 mutex_enter(&kp->kp_mutex); 2019 if (kp->kp_state != KEYSPAN_PORT_OPEN) { 2020 mutex_exit(&kp->kp_mutex); 2021 continue; 2022 } 2023 mutex_exit(&kp->kp_mutex); 2024 2025 sema_p(&ksp->ks_pipes_sema); 2026 /* open hardware serial port */ 2027 err = keyspan_open_hw_port(kp, B_FALSE); 2028 sema_v(&ksp->ks_pipes_sema); 2029 if (err != USB_SUCCESS) { 2030 USB_DPRINTF_L2(DPRINT_HOTPLUG, kp->kp_lh, 2031 "keyspan_restore_ports_state: failed"); 2032 rval = err; 2033 } 2034 } 2035 2036 return (rval); 2037 } 2038 2039 2040 /* 2041 * power management 2042 * ---------------- 2043 * 2044 * 2045 * create PM components 2046 */ 2047 static int 2048 keyspan_create_pm_components(keyspan_state_t *ksp) 2049 { 2050 dev_info_t *dip = ksp->ks_dip; 2051 keyspan_pm_t *pm; 2052 uint_t pwr_states; 2053 2054 pm = ksp->ks_pm = kmem_zalloc(sizeof (keyspan_pm_t), KM_SLEEP); 2055 pm->pm_cur_power = USB_DEV_OS_FULL_PWR; 2056 2057 if (usb_create_pm_components(dip, &pwr_states) != USB_SUCCESS) { 2058 USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh, 2059 "keyspan_create_pm_components: failed"); 2060 2061 return (USB_SUCCESS); 2062 } 2063 2064 pm->pm_wakeup_enabled = (usb_handle_remote_wakeup(dip, 2065 USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS); 2066 pm->pm_pwr_states = (uint8_t)pwr_states; 2067 2068 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 2069 2070 return (USB_SUCCESS); 2071 } 2072 2073 2074 /* 2075 * destroy PM components 2076 */ 2077 static void 2078 keyspan_destroy_pm_components(keyspan_state_t *ksp) 2079 { 2080 keyspan_pm_t *pm = ksp->ks_pm; 2081 dev_info_t *dip = ksp->ks_dip; 2082 int rval; 2083 2084 if (ksp->ks_dev_state != USB_DEV_DISCONNECTED) { 2085 if (pm->pm_wakeup_enabled) { 2086 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 2087 2088 rval = usb_handle_remote_wakeup(dip, 2089 USB_REMOTE_WAKEUP_DISABLE); 2090 if (rval != USB_SUCCESS) { 2091 USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh, 2092 "keyspan_destroy_pm_components: disable " 2093 "remote wakeup failed, rval=%d", rval); 2094 } 2095 } 2096 2097 (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF); 2098 } 2099 kmem_free(pm, sizeof (keyspan_pm_t)); 2100 ksp->ks_pm = NULL; 2101 } 2102 2103 2104 /* 2105 * mark device busy and raise power 2106 */ 2107 static int 2108 keyspan_pm_set_busy(keyspan_state_t *ksp) 2109 { 2110 keyspan_pm_t *pm = ksp->ks_pm; 2111 dev_info_t *dip = ksp->ks_dip; 2112 2113 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_busy"); 2114 2115 mutex_enter(&ksp->ks_mutex); 2116 /* if already marked busy, just increment the counter */ 2117 if (pm->pm_busy_cnt++ > 0) { 2118 USB_DPRINTF_L3(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_busy:" 2119 "already busy, busy_cnt = %d", pm->pm_busy_cnt); 2120 mutex_exit(&ksp->ks_mutex); 2121 2122 return (USB_SUCCESS); 2123 } 2124 2125 (void) pm_busy_component(dip, 0); 2126 2127 if (pm->pm_cur_power == USB_DEV_OS_FULL_PWR) { 2128 mutex_exit(&ksp->ks_mutex); 2129 2130 return (USB_SUCCESS); 2131 } 2132 2133 /* need to raise power */ 2134 pm->pm_raise_power = B_TRUE; 2135 mutex_exit(&ksp->ks_mutex); 2136 2137 USB_DPRINTF_L3(DPRINT_PM, ksp->ks_lh, 2138 "keyspan_pm_set_busy: raise power"); 2139 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 2140 2141 mutex_enter(&ksp->ks_mutex); 2142 pm->pm_raise_power = B_FALSE; 2143 mutex_exit(&ksp->ks_mutex); 2144 2145 return (USB_SUCCESS); 2146 } 2147 2148 2149 /* 2150 * mark device idle 2151 */ 2152 static void 2153 keyspan_pm_set_idle(keyspan_state_t *ksp) 2154 { 2155 keyspan_pm_t *pm = ksp->ks_pm; 2156 dev_info_t *dip = ksp->ks_dip; 2157 2158 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_idle"); 2159 2160 /* 2161 * if more ports use the device, do not mark as yet 2162 */ 2163 mutex_enter(&ksp->ks_mutex); 2164 if (--pm->pm_busy_cnt > 0) { 2165 mutex_exit(&ksp->ks_mutex); 2166 2167 return; 2168 } 2169 2170 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_idle: set idle"); 2171 (void) pm_idle_component(dip, 0); 2172 2173 mutex_exit(&ksp->ks_mutex); 2174 } 2175 2176 2177 /* 2178 * Functions to handle power transition for OS levels 0 -> 3 2179 */ 2180 static int 2181 keyspan_pwrlvl0(keyspan_state_t *ksp) 2182 { 2183 int rval; 2184 keyspan_pipe_t *statin = &ksp->ks_statin_pipe; 2185 2186 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl0"); 2187 2188 switch (ksp->ks_dev_state) { 2189 case USB_DEV_ONLINE: 2190 /* issue USB D3 command to the device */ 2191 rval = usb_set_device_pwrlvl3(ksp->ks_dip); 2192 ASSERT(rval == USB_SUCCESS); 2193 2194 if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) { 2195 mutex_exit(&ksp->ks_mutex); 2196 usb_pipe_stop_intr_polling(statin->pipe_handle, 2197 USB_FLAGS_SLEEP); 2198 mutex_enter(&ksp->ks_mutex); 2199 2200 mutex_enter(&statin->pipe_mutex); 2201 statin->pipe_state = KEYSPAN_PIPE_CLOSED; 2202 mutex_exit(&statin->pipe_mutex); 2203 } 2204 ksp->ks_dev_state = USB_DEV_PWRED_DOWN; 2205 ksp->ks_pm->pm_cur_power = USB_DEV_OS_PWR_OFF; 2206 2207 /* FALLTHRU */ 2208 case USB_DEV_DISCONNECTED: 2209 case USB_DEV_SUSPENDED: 2210 /* allow a disconnect/cpr'ed device to go to lower power */ 2211 2212 return (USB_SUCCESS); 2213 case USB_DEV_PWRED_DOWN: 2214 default: 2215 USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh, 2216 "keyspan_pwrlvl0: illegal device state"); 2217 2218 return (USB_FAILURE); 2219 } 2220 } 2221 2222 2223 static int 2224 keyspan_pwrlvl1(keyspan_state_t *ksp) 2225 { 2226 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl1"); 2227 2228 /* issue USB D2 command to the device */ 2229 (void) usb_set_device_pwrlvl2(ksp->ks_dip); 2230 2231 return (USB_FAILURE); 2232 } 2233 2234 2235 static int 2236 keyspan_pwrlvl2(keyspan_state_t *ksp) 2237 { 2238 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl2"); 2239 2240 /* issue USB D1 command to the device */ 2241 (void) usb_set_device_pwrlvl1(ksp->ks_dip); 2242 2243 return (USB_FAILURE); 2244 } 2245 2246 2247 static int 2248 keyspan_pwrlvl3(keyspan_state_t *ksp) 2249 { 2250 int rval; 2251 2252 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl3"); 2253 2254 switch (ksp->ks_dev_state) { 2255 case USB_DEV_PWRED_DOWN: 2256 /* Issue USB D0 command to the device here */ 2257 rval = usb_set_device_pwrlvl0(ksp->ks_dip); 2258 ASSERT(rval == USB_SUCCESS); 2259 2260 if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) { 2261 mutex_exit(&ksp->ks_mutex); 2262 keyspan_pipe_start_polling(&ksp->ks_statin_pipe); 2263 mutex_enter(&ksp->ks_mutex); 2264 } 2265 2266 ksp->ks_dev_state = USB_DEV_ONLINE; 2267 ksp->ks_pm->pm_cur_power = USB_DEV_OS_FULL_PWR; 2268 2269 /* FALLTHRU */ 2270 case USB_DEV_ONLINE: 2271 /* we are already in full power */ 2272 2273 /* FALLTHRU */ 2274 case USB_DEV_DISCONNECTED: 2275 case USB_DEV_SUSPENDED: 2276 2277 return (USB_SUCCESS); 2278 default: 2279 USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh, 2280 "keyspan_pwrlvl3: illegal device state"); 2281 2282 return (USB_FAILURE); 2283 } 2284 } 2285 2286 2287 /* 2288 * pipe operations 2289 * --------------- 2290 * 2291 * XXX keyspan seem to malfunction after the pipes are closed 2292 * and reopened again (does not respond to OPEN_PORT command). 2293 * so we open them once in attach 2294 */ 2295 static int 2296 keyspan_attach_pipes(keyspan_state_t *ksp) 2297 { 2298 return (keyspan_open_dev_pipes(ksp)); 2299 } 2300 2301 void 2302 keyspan_detach_pipes(keyspan_state_t *ksp) 2303 { 2304 2305 /* 2306 * Blow away status bulk in requests or 2307 * pipe close will wait until timeout. 2308 */ 2309 if (ksp->ks_statin_pipe.pipe_handle) { 2310 usb_pipe_stop_intr_polling(ksp->ks_statin_pipe.pipe_handle, 2311 USB_FLAGS_SLEEP); 2312 } 2313 2314 /* Close the globle pipes */ 2315 keyspan_close_dev_pipes(ksp); 2316 } 2317 2318 2319 /* 2320 * during device disconnect/suspend, close pipes if they are open. 2321 */ 2322 static void 2323 keyspan_disconnect_pipes(keyspan_state_t *ksp) 2324 { 2325 sema_p(&ksp->ks_pipes_sema); 2326 keyspan_close_pipes(ksp); 2327 sema_v(&ksp->ks_pipes_sema); 2328 } 2329 2330 2331 /* 2332 * during device reconnect/resume, reopen pipes if they were open. 2333 */ 2334 static int 2335 keyspan_reconnect_pipes(keyspan_state_t *ksp) 2336 { 2337 int rval = USB_SUCCESS; 2338 2339 sema_p(&ksp->ks_pipes_sema); 2340 rval = keyspan_reopen_pipes(ksp); 2341 sema_v(&ksp->ks_pipes_sema); 2342 2343 return (rval); 2344 } 2345 2346 /* 2347 * data transfer routines 2348 * ---------------------- 2349 * 2350 * 2351 * start data transmit 2352 */ 2353 void 2354 keyspan_tx_start(keyspan_port_t *kp, int *xferd) 2355 { 2356 keyspan_state_t *ksp = kp->kp_ksp; 2357 int len; /* # of bytes we can transmit */ 2358 mblk_t *data; /* data to be transmitted */ 2359 int data_len = 0; /* # of bytes in 'data' */ 2360 int tran_len; 2361 int rval; 2362 int status_len = 0; 2363 2364 ASSERT(!mutex_owned(&ksp->ks_mutex)); 2365 ASSERT(mutex_owned(&kp->kp_mutex)); 2366 ASSERT(kp->kp_state != KEYSPAN_PORT_CLOSED); 2367 2368 USB_DPRINTF_L4(DPRINT_OUT_PIPE, kp->kp_lh, "keyspan_tx_start"); 2369 2370 if (xferd) { 2371 *xferd = 0; 2372 } 2373 if ((kp->kp_flags & KEYSPAN_PORT_TX_STOPPED) || 2374 (kp->kp_tx_mp == NULL)) { 2375 2376 return; 2377 } 2378 2379 len = min(msgdsize(kp->kp_tx_mp), kp->kp_write_len); 2380 USB_DPRINTF_L4(DPRINT_OUT_PIPE, kp->kp_lh, "keyspan_tx_start:" 2381 "len = %d, tx_mp_len = %d", len, (int)msgdsize(kp->kp_tx_mp)); 2382 2383 mutex_exit(&kp->kp_mutex); 2384 2385 /* 2386 * Some keyspan adapters, such as usa49wlc, 2387 * need use the first byte as flag. 2388 */ 2389 switch (ksp->ks_dev_spec.id_product) { 2390 case KEYSPAN_USA19HS_PID: 2391 2392 if ((data = allocb(len, BPRI_LO)) == NULL) { 2393 mutex_enter(&kp->kp_mutex); 2394 2395 return; 2396 } 2397 mutex_enter(&kp->kp_mutex); 2398 2399 /* copy at most 'len' bytes from mblk chain for transmission */ 2400 data_len = keyspan_tx_copy_data(kp, data, len); 2401 if (data_len <= 0) { 2402 USB_DPRINTF_L3(DPRINT_OUT_PIPE, kp->kp_lh, 2403 "keyspan_tx_start:keyspan_tx_copy_data copied" 2404 " zero bytes"); 2405 } 2406 2407 break; 2408 2409 case KEYSPAN_USA49WLC_PID: 2410 case KEYSPAN_USA49WG_PID: 2411 status_len = len / 64 + 1; 2412 if ((data = allocb(len + status_len, BPRI_LO)) == NULL) { 2413 mutex_enter(&kp->kp_mutex); 2414 2415 return; 2416 } 2417 mutex_enter(&kp->kp_mutex); 2418 /* 2419 * the data format is [status byte][63 data bytes][...][status] 2420 * byte][up to 63 bytes] according to keyspan spec 2421 */ 2422 while (data_len < len) { 2423 /* Add status byte per 63 data bytes */ 2424 *(data->b_wptr++) = 0; 2425 /* copy at most 63 bytes from mblk chain for trans */ 2426 tran_len = keyspan_tx_copy_data(kp, data, 63); 2427 if (tran_len <= 0) { 2428 USB_DPRINTF_L3(DPRINT_OUT_PIPE, kp->kp_lh, 2429 "keyspan_tx_start:keyspan_tx_copy_data" 2430 " copied zero bytes"); 2431 2432 break; 2433 } 2434 data_len += tran_len; 2435 } 2436 2437 break; 2438 default: 2439 2440 mutex_enter(&kp->kp_mutex); 2441 USB_DPRINTF_L2(DPRINT_OUT_PIPE, ksp->ks_lh, "keyspan_tx_start:" 2442 "the device's product id can't be recognized"); 2443 2444 return; 2445 } 2446 2447 mutex_exit(&kp->kp_mutex); 2448 2449 /* 2450 * For USA-49WG, the port0 uses intr out pipe as data out pipe, while 2451 * other ports use bulk out pipe. 2452 */ 2453 2454 if ((kp->kp_port_num == 0) && 2455 (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID)) { 2456 rval = keyspan_send_data_port0(&kp->kp_dataout_pipe, &data, kp); 2457 } else { 2458 rval = keyspan_send_data(&kp->kp_dataout_pipe, &data, kp); 2459 } 2460 mutex_enter(&kp->kp_mutex); 2461 2462 /* 2463 * if send failed, put data back 2464 */ 2465 if (rval != USB_SUCCESS) { 2466 ASSERT(data); 2467 keyspan_put_head(&kp->kp_tx_mp, data, kp); 2468 } else if (xferd) { 2469 *xferd = data_len; 2470 } 2471 2472 USB_DPRINTF_L4(DPRINT_OUT_PIPE, kp->kp_lh, "keyspan_tx_start[%d]: over" 2473 "(%d) rval=%d", kp->kp_port_num, data_len, rval); 2474 2475 } 2476 2477 2478 /* 2479 * copy no more than 'len' bytes from mblk chain to transmit mblk 'data'. 2480 * return number of bytes copied 2481 */ 2482 int 2483 keyspan_tx_copy_data(keyspan_port_t *kp, mblk_t *data, int len) 2484 { 2485 mblk_t *mp; /* current msgblk */ 2486 int copylen; /* # of bytes to copy from 'mp' to 'data' */ 2487 int data_len = 0; 2488 2489 ASSERT(mutex_owned(&kp->kp_mutex)); 2490 2491 if (msgdsize(kp->kp_tx_mp) == 0) { 2492 data->b_wptr = data->b_rptr; 2493 freeb(kp->kp_tx_mp); 2494 kp->kp_tx_mp = NULL; 2495 2496 return (data_len); 2497 } 2498 2499 while ((data_len < len) && kp->kp_tx_mp) { 2500 mp = kp->kp_tx_mp; 2501 copylen = min(MBLKL(mp), len - data_len); 2502 bcopy(mp->b_rptr, data->b_wptr, copylen); 2503 2504 mp->b_rptr += copylen; 2505 data->b_wptr += copylen; 2506 data_len += copylen; 2507 2508 if (MBLKL(mp) <= 0) { 2509 kp->kp_tx_mp = unlinkb(mp); 2510 freeb(mp); 2511 } else { 2512 ASSERT(data_len == len); 2513 } 2514 } 2515 USB_DPRINTF_L3(DPRINT_OUT_DATA, kp->kp_lh, "keyspan_tx_copy_data:" 2516 "copied data_len = %d", data_len); 2517 2518 return (data_len); 2519 } 2520 2521 2522 /* 2523 * wait until local tx buffer drains. 2524 * 'timeout' is in seconds, zero means wait forever 2525 */ 2526 static int 2527 keyspan_wait_tx_drain(keyspan_port_t *kp, int timeout) 2528 { 2529 clock_t until; 2530 int over = 0; 2531 2532 USB_DPRINTF_L4(DPRINT_OUT_DATA, kp->kp_lh, "keyspan_wait_tx_drain:" 2533 "timeout = %d", timeout); 2534 until = ddi_get_lbolt() + drv_usectohz(1000000 * timeout); 2535 2536 while (kp->kp_tx_mp && !over) { 2537 if (timeout > 0) { 2538 over = (cv_timedwait_sig(&kp->kp_tx_cv, 2539 &kp->kp_mutex, until) <= 0); 2540 } else { 2541 over = (cv_wait_sig(&kp->kp_tx_cv, &kp->kp_mutex) == 0); 2542 } 2543 } 2544 2545 return ((kp->kp_tx_mp == NULL) ? USB_SUCCESS : USB_FAILURE); 2546 } 2547 2548 /* 2549 * returns 0 if device is not online, != 0 otherwise 2550 */ 2551 int 2552 keyspan_dev_is_online(keyspan_state_t *ksp) 2553 { 2554 int rval; 2555 2556 mutex_enter(&ksp->ks_mutex); 2557 rval = (ksp->ks_dev_state == USB_DEV_ONLINE); 2558 mutex_exit(&ksp->ks_mutex); 2559 2560 return (rval); 2561 } 2562 2563 /* 2564 * link a message block to tail of message 2565 * account for the case when message is null 2566 */ 2567 void 2568 keyspan_put_tail(mblk_t **mpp, mblk_t *bp) 2569 { 2570 if (*mpp) { 2571 linkb(*mpp, bp); 2572 } else { 2573 *mpp = bp; 2574 } 2575 } 2576 2577 /* 2578 * put a message block at the head of the message 2579 * account for the case when message is null 2580 */ 2581 void 2582 keyspan_put_head(mblk_t **mpp, mblk_t *bp, keyspan_port_t *kp) 2583 { 2584 switch (kp->kp_ksp->ks_dev_spec.id_product) { 2585 case KEYSPAN_USA19HS_PID: 2586 if (*mpp) { 2587 linkb(bp, *mpp); 2588 } 2589 *mpp = bp; 2590 2591 break; 2592 2593 2594 case KEYSPAN_USA49WLC_PID: 2595 case KEYSPAN_USA49WG_PID: 2596 2597 /* get rid of the first byte of the msg data which is a flag */ 2598 if (*mpp) { 2599 linkb(bp, *mpp); 2600 } 2601 bp->b_rptr = bp->b_datap->db_base + 1; 2602 *mpp = bp; 2603 2604 break; 2605 2606 default: 2607 USB_DPRINTF_L2(DPRINT_OUT_DATA, kp->kp_lh, "keyspan_put_head:" 2608 "the device's product id can't be recognized"); 2609 2610 return; 2611 } 2612 2613 } 2614 2615 /* 2616 * Set the port parameters to default values 2617 */ 2618 static void 2619 keyspan_default_port_params(keyspan_port_t *kp) 2620 { 2621 keyspan_state_t *ksp = kp->kp_ksp; 2622 2623 ASSERT(mutex_owned(&kp->kp_mutex)); 2624 2625 switch (ksp->ks_dev_spec.id_product) { 2626 case KEYSPAN_USA19HS_PID: 2627 keyspan_default_port_params_usa19hs(kp); 2628 2629 break; 2630 2631 2632 case KEYSPAN_USA49WLC_PID: 2633 case KEYSPAN_USA49WG_PID: 2634 keyspan_default_port_params_usa49(kp); 2635 2636 break; 2637 2638 default: 2639 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 2640 "keyspan_default_port_params:" 2641 "the device's product id can't be recognized"); 2642 } 2643 2644 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2645 "keyspan_default_port_params: setted."); 2646 } 2647 2648 /* 2649 * Build the command message according to the params from usbser. 2650 * The message will then be sent to deivce by keyspan_send_cmd. 2651 */ 2652 static void 2653 keyspan_build_cmd_msg(keyspan_port_t *kp, ds_port_params_t *tp) 2654 { 2655 keyspan_state_t *ksp = kp->kp_ksp; 2656 2657 switch (ksp->ks_dev_spec.id_product) { 2658 case KEYSPAN_USA19HS_PID: 2659 keyspan_build_cmd_msg_usa19hs(kp, tp); 2660 2661 break; 2662 2663 2664 case KEYSPAN_USA49WLC_PID: 2665 case KEYSPAN_USA49WG_PID: 2666 keyspan_build_cmd_msg_usa49(kp, tp); 2667 2668 break; 2669 2670 default: 2671 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 2672 "keyspan_build_cmd_msg:" 2673 "the device's product id can't be recognized"); 2674 } 2675 } 2676 2677 /* save the port params after send cmd successfully */ 2678 static void 2679 keyspan_save_port_params(keyspan_port_t *kp) 2680 { 2681 keyspan_state_t *ksp = kp->kp_ksp; 2682 2683 ASSERT(mutex_owned(&kp->kp_mutex)); 2684 2685 switch (ksp->ks_dev_spec.id_product) { 2686 case KEYSPAN_USA19HS_PID: 2687 keyspan_save_port_params_usa19hs(kp); 2688 2689 break; 2690 2691 2692 case KEYSPAN_USA49WLC_PID: 2693 case KEYSPAN_USA49WG_PID: 2694 keyspan_save_port_params_usa49(kp); 2695 2696 break; 2697 2698 default: 2699 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 2700 "keyspan_save_port_params:" 2701 "the device's product id can't be recognized"); 2702 } 2703 2704 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2705 "keyspan_save_port_params: baud = %x, lcr = %x," 2706 "status_flag = %x", kp->kp_baud, kp->kp_lcr, kp->kp_status_flag); 2707 2708 } 2709 2710 /* save the port params after send cmd successfully */ 2711 static void 2712 keyspan_save_port_params_usa19hs(keyspan_port_t *kp) 2713 { 2714 keyspan_usa19hs_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa19hs); 2715 2716 ASSERT(mutex_owned(&kp->kp_mutex)); 2717 2718 if (ctrl_msg->setClocking) { 2719 kp->kp_baud = ctrl_msg->baudHi; 2720 kp->kp_baud = (kp->kp_baud << 8); 2721 kp->kp_baud |= ctrl_msg->baudLo; 2722 } 2723 if (ctrl_msg->setLcr) { 2724 kp->kp_lcr = ctrl_msg->lcr; 2725 } 2726 if (ctrl_msg->setRts) { 2727 if (ctrl_msg->rts) { 2728 kp->kp_status_flag |= KEYSPAN_PORT_RTS; 2729 } else { 2730 kp->kp_status_flag &= ~KEYSPAN_PORT_RTS; 2731 } 2732 } 2733 if (ctrl_msg->setDtr) { 2734 if (ctrl_msg->dtr) { 2735 kp->kp_status_flag |= KEYSPAN_PORT_DTR; 2736 } else { 2737 kp->kp_status_flag &= ~KEYSPAN_PORT_DTR; 2738 } 2739 } 2740 2741 if (ctrl_msg->portEnabled) { 2742 kp->kp_status_flag |= KEYSPAN_PORT_ENABLE; 2743 } else { 2744 kp->kp_status_flag &= ~KEYSPAN_PORT_ENABLE; 2745 } 2746 2747 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2748 "keyspan_save_port_params: baud = %x, lcr = %x," 2749 "status_flag = %x", kp->kp_baud, kp->kp_lcr, kp->kp_status_flag); 2750 2751 } 2752 2753 /* 2754 * Set the port parameters to default values 2755 */ 2756 static void 2757 keyspan_default_port_params_usa19hs(keyspan_port_t *kp) 2758 { 2759 keyspan_usa19hs_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa19hs); 2760 ASSERT(mutex_owned(&kp->kp_mutex)); 2761 2762 keyspan_build_cmd_msg(kp, NULL); 2763 2764 ctrl_msg->setRts = 0x01; 2765 ctrl_msg->rts = 0x1; 2766 ctrl_msg->setDtr = 0x01; 2767 ctrl_msg->dtr = 0x1; 2768 2769 ctrl_msg->setClocking = 1; 2770 ctrl_msg->setRxMode = 1; 2771 ctrl_msg->setTxMode = 1; 2772 2773 /* set baud rate to 9600 */ 2774 ctrl_msg->baudLo = keyspan_speedtab_usa19hs[13] & 0xff; 2775 ctrl_msg->baudHi = (keyspan_speedtab_usa19hs[13] >> 8) & 0xff; 2776 ctrl_msg->rxMode = RXMODE_BYHAND; 2777 ctrl_msg->txMode = TXMODE_BYHAND; 2778 2779 ctrl_msg->lcr = 0x3; 2780 ctrl_msg->setLcr = 0x1; 2781 2782 ctrl_msg->xonChar = CSTART; 2783 ctrl_msg->xoffChar = CSTOP; 2784 ctrl_msg->setTxFlowControl = 1; 2785 ctrl_msg->txFlowControl = TXFLOW_CTS; 2786 ctrl_msg->setRxFlowControl = 1; 2787 ctrl_msg->rxFlowControl = RXFLOW_RTS; 2788 ctrl_msg->rxFlush = 0; 2789 2790 } 2791 2792 /* 2793 * Build the command message according to the params from usbser. 2794 * The message will then be sent to deivce by keyspan_send_cmd. 2795 */ 2796 static void 2797 keyspan_build_cmd_msg_usa19hs(keyspan_port_t *kp, ds_port_params_t *tp) 2798 { 2799 int cnt, i; 2800 uint_t ui; 2801 ds_port_param_entry_t *pe; 2802 keyspan_usa19hs_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa19hs); 2803 2804 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, 2805 "keyspan_build_cmd_msg_usa19hs: tp = %p", (void *)tp); 2806 2807 ASSERT(mutex_owned(&kp->kp_mutex)); 2808 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN || 2809 kp->kp_state == KEYSPAN_PORT_OPENING); 2810 2811 /* bzero all elements */ 2812 bzero(ctrl_msg, sizeof (keyspan_usa19hs_port_ctrl_msg_t)); 2813 2814 /* it is usaually 16, according to Keyspan spec */ 2815 ctrl_msg->rxForwardingLength = 16; 2816 /* from 1ms to 31ms, according to Keyspan spec. */ 2817 ctrl_msg->rxForwardingTimeout = 16; 2818 2819 ctrl_msg->portEnabled = 1; 2820 ctrl_msg->returnStatus = 1; 2821 2822 if (tp == NULL) { 2823 2824 return; 2825 } 2826 2827 cnt = tp->tp_cnt; 2828 pe = tp->tp_entries; 2829 2830 /* translate tp parameters into cmd_msg elements */ 2831 for (i = 0; i < cnt; i++, pe++) { 2832 switch (pe->param) { 2833 case DS_PARAM_BAUD: 2834 ui = pe->val.ui; 2835 2836 /* 2837 * if we don't support this speed, 2838 * then return failure. 2839 */ 2840 if ((ui >= NELEM(keyspan_speedtab_usa19hs)) || 2841 ((ui > 0) && (keyspan_speedtab_usa19hs[ui] == 0))) { 2842 2843 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2844 "keyspan_build_cmd_msg_usa19hs:" 2845 " bad baud %d", ui); 2846 2847 break; 2848 } 2849 2850 /* if the same as the old rate, need not set the rate */ 2851 if (kp->kp_baud == keyspan_speedtab_usa19hs[ui]) { 2852 2853 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2854 "keyspan_build_cmd_msg_usa19hs:" 2855 " same as old baud setting, baud = %d", 2856 keyspan_speed2baud[ui]); 2857 2858 break; 2859 } 2860 ctrl_msg->setClocking = 1; /* enable the setting */ 2861 ctrl_msg->setRxMode = 1; 2862 ctrl_msg->setTxMode = 1; 2863 2864 ctrl_msg->baudLo = keyspan_speedtab_usa19hs[ui] & 0xff; 2865 ctrl_msg->baudHi = (keyspan_speedtab_usa19hs[ui] >> 8) 2866 & 0xff; 2867 2868 ctrl_msg->rxMode = RXMODE_BYHAND; 2869 ctrl_msg->txMode = TXMODE_BYHAND; 2870 2871 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2872 "keyspan_build_cmd_msg_usa19hs: baud=%d", 2873 keyspan_speed2baud[ui]); 2874 2875 break; 2876 case DS_PARAM_PARITY: 2877 if (pe->val.ui & PARENB) { 2878 2879 /* 2880 * Since USA_PARITY_NONE == 0, it's not 2881 * necessary to or it in here. 2882 */ 2883 if (pe->val.ui & PARODD) { 2884 ctrl_msg->lcr |= USA_PARITY_ODD; 2885 } else { 2886 ctrl_msg->lcr |= USA_PARITY_EVEN; 2887 } 2888 } 2889 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2890 "keyspan_build_cmd_msg_usa19hs: parity=%x,lcr = %x", 2891 pe->val.ui, ctrl_msg->lcr); 2892 2893 break; 2894 case DS_PARAM_STOPB: 2895 if (pe->val.ui & CSTOPB) { 2896 ctrl_msg->lcr |= STOPBITS_678_2; 2897 } else { 2898 2899 /* 2900 * STOPBITS_5678_1 equals zero, 2901 * so it's not necessary to or it in. 2902 */ 2903 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2904 "keyspan_build_cmd_msg_usa19hs:" 2905 " STOPBITS_5678_1"); 2906 } 2907 2908 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2909 "keyspan_build_cmd_msg_usa19hs: stopb=%x, lcr = %x", 2910 pe->val.ui, ctrl_msg->lcr); 2911 2912 break; 2913 case DS_PARAM_CHARSZ: 2914 switch (pe->val.ui) { 2915 case CS5: 2916 2917 /* 2918 * USA_DATABITS_5 equals zero, 2919 * not necessary to or it in. 2920 */ 2921 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2922 "keyspan_build_cmd_msg_usa19hs:" 2923 " USA_DATABITS_5"); 2924 2925 break; 2926 case CS6: 2927 ctrl_msg->lcr |= USA_DATABITS_6; 2928 2929 break; 2930 case CS7: 2931 ctrl_msg->lcr |= USA_DATABITS_7; 2932 2933 break; 2934 case CS8: 2935 default: 2936 /* 2937 * The default value is USA_DATABITS_8. It is 2938 * safe to set to the default one here. 2939 */ 2940 ctrl_msg->lcr |= USA_DATABITS_8; 2941 2942 break; 2943 } 2944 2945 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2946 "keyspan_build_cmd_msg_usa19hs: cs=%x, lcr = %x", 2947 pe->val.ui, ctrl_msg->lcr); 2948 2949 break; 2950 case DS_PARAM_XON_XOFF: 2951 ctrl_msg->xonChar = pe->val.uc[0]; /* init to CSTART */ 2952 ctrl_msg->xoffChar = pe->val.uc[1]; /* init to CSTOP */ 2953 2954 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2955 "keyspan_build_cmd_msg_usa19hs: xonChar=%x, " 2956 "xoffChar = %x", ctrl_msg->xonChar, 2957 ctrl_msg->xoffChar); 2958 2959 break; 2960 case DS_PARAM_FLOW_CTL: 2961 if (pe->val.ui & CTSXON) { 2962 ctrl_msg->txFlowControl = TXFLOW_CTS; 2963 ctrl_msg->setTxFlowControl = 1; 2964 } else { 2965 /* Clear the tx flow control setting */ 2966 ctrl_msg->txFlowControl = 0; 2967 ctrl_msg->setTxFlowControl = 1; 2968 } 2969 if (pe->val.ui & RTSXOFF) { 2970 ctrl_msg->rxFlowControl = RXFLOW_RTS; 2971 ctrl_msg->setRxFlowControl = 1; 2972 } else { 2973 /* Clear the rx flow control setting */ 2974 ctrl_msg->rxFlowControl = 0; 2975 ctrl_msg->setRxFlowControl = 1; 2976 } 2977 2978 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 2979 "keyspan_build_cmd_msg_usa19hs: txFlowControl = %x," 2980 "rxFlowControl = %x", ctrl_msg->txFlowControl, 2981 ctrl_msg->rxFlowControl); 2982 2983 break; 2984 default: 2985 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, 2986 "keyspan_build_cmd_msg_usa19hs: bad param %d", 2987 pe->param); 2988 2989 break; 2990 } 2991 2992 } 2993 2994 /* 2995 * Enable the lcr settings only if they are different 2996 * with the existing settings. 2997 */ 2998 ctrl_msg->setLcr = (ctrl_msg->lcr == kp->kp_lcr) ? 0 : 1; 2999 3000 } 3001 3002 3003 /* 3004 * Build the command message according to the params from usbser. 3005 * The message will then be sent to deivce by keyspan_send_cmd. 3006 */ 3007 static void 3008 keyspan_build_cmd_msg_usa49(keyspan_port_t *kp, ds_port_params_t *tp) 3009 { 3010 int cnt, i; 3011 uint_t ui; 3012 ds_port_param_entry_t *pe; 3013 keyspan_usa49_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa49); 3014 3015 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, 3016 "keyspan_build_cmd_msg_usa49: tp = %p", (void *)tp); 3017 3018 ASSERT(mutex_owned(&kp->kp_mutex)); 3019 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN || 3020 kp->kp_state == KEYSPAN_PORT_OPENING); 3021 3022 /* bzero all elements */ 3023 bzero(ctrl_msg, sizeof (keyspan_usa49_port_ctrl_msg_t)); 3024 3025 ctrl_msg->portNumber = kp->kp_port_num; 3026 3027 /* it is usaually 16, according to Keyspan spec */ 3028 ctrl_msg->forwardingLength = 16; 3029 3030 ctrl_msg->enablePort = 1; 3031 ctrl_msg->returnStatus = 1; 3032 3033 if (tp == NULL) { 3034 3035 return; 3036 } 3037 3038 cnt = tp->tp_cnt; 3039 pe = tp->tp_entries; 3040 3041 /* translate tp parameters into cmd_msg elements */ 3042 for (i = 0; i < cnt; i++, pe++) { 3043 switch (pe->param) { 3044 case DS_PARAM_BAUD: 3045 ui = pe->val.ui; 3046 3047 /* 3048 * If we don't support this speed, 3049 * then return failure. 3050 */ 3051 if ((ui >= NELEM(keyspan_speedtab_usa49)) || 3052 ((ui > 0) && (keyspan_speedtab_usa49[ui] == 0))) { 3053 3054 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3055 "keyspan_build_cmd_msg_usa49:" 3056 " bad baud %d", ui); 3057 3058 break; 3059 } 3060 3061 /* if the same as the old rate, need not set the rate */ 3062 if (kp->kp_baud == keyspan_speedtab_usa49[ui]) { 3063 3064 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3065 "keyspan_build_cmd_msg_usa49: " 3066 "same as old baud setting, baud = %d", 3067 keyspan_speed2baud[ui]); 3068 3069 break; 3070 } 3071 ctrl_msg->setClocking = 0xff; /* enable the setting */ 3072 ctrl_msg->baudLo = keyspan_speedtab_usa49[ui] & 0xff; 3073 ctrl_msg->baudHi = (keyspan_speedtab_usa49[ui] >> 8) 3074 & 0xff; 3075 ctrl_msg->prescaler = keyspan_prescaler_49wlc[ui]; 3076 3077 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3078 "keyspan_build_cmd_msg_usa49: baud=%d", 3079 keyspan_speed2baud[ui]); 3080 3081 break; 3082 case DS_PARAM_PARITY: 3083 if (pe->val.ui & PARENB) { 3084 3085 /* 3086 * Since USA_PARITY_NONE == 0, 3087 * it's not necessary to or it in here. 3088 */ 3089 if (pe->val.ui & PARODD) { 3090 ctrl_msg->lcr |= USA_PARITY_ODD; 3091 } else { 3092 ctrl_msg->lcr |= USA_PARITY_EVEN; 3093 } 3094 } 3095 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3096 "keyspan_build_cmd_msg_usa49: parity=%x, lcr = %x", 3097 pe->val.ui, ctrl_msg->lcr); 3098 3099 break; 3100 case DS_PARAM_STOPB: 3101 if (pe->val.ui & CSTOPB) { 3102 ctrl_msg->lcr |= STOPBITS_678_2; 3103 } else { 3104 3105 /* 3106 * STOPBITS_5678_1 equals zero, 3107 * not necessary to or it in. 3108 */ 3109 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3110 "keyspan_build_cmd_msg_usa49: " 3111 "STOPBITS_5678_1"); 3112 } 3113 3114 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3115 "keyspan_build_cmd_msg_usa49: stopb=%x, lcr = %x", 3116 pe->val.ui, ctrl_msg->lcr); 3117 3118 break; 3119 case DS_PARAM_CHARSZ: 3120 switch (pe->val.ui) { 3121 case CS5: 3122 3123 /* 3124 * USA_DATABITS_5 equals zero, 3125 * not necessary to or it in. 3126 */ 3127 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3128 "keyspan_build_cmd_msg_usa49:" 3129 " USA_DATABITS_5"); 3130 3131 break; 3132 case CS6: 3133 ctrl_msg->lcr |= USA_DATABITS_6; 3134 3135 break; 3136 case CS7: 3137 ctrl_msg->lcr |= USA_DATABITS_7; 3138 3139 break; 3140 case CS8: 3141 default: 3142 ctrl_msg->lcr |= USA_DATABITS_8; 3143 3144 break; 3145 } 3146 3147 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3148 "keyspan_build_cmd_msg_usa49: cs=%x, lcr = %x", 3149 pe->val.ui, ctrl_msg->lcr); 3150 3151 break; 3152 case DS_PARAM_XON_XOFF: 3153 ctrl_msg->xonChar = pe->val.uc[0]; /* init to CSTART */ 3154 ctrl_msg->xoffChar = pe->val.uc[1]; /* init to CSTOP */ 3155 3156 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3157 "keyspan_build_cmd_msg_usa49: xonChar=%x, " 3158 "xoffChar = %x", ctrl_msg->xonChar, 3159 ctrl_msg->xoffChar); 3160 3161 break; 3162 case DS_PARAM_FLOW_CTL: 3163 if (pe->val.ui & CTSXON) { 3164 ctrl_msg->ctsFlowControl = 1; 3165 ctrl_msg->setFlowControl = 1; 3166 } else { 3167 ctrl_msg->ctsFlowControl = 0; 3168 ctrl_msg->setFlowControl = 1; 3169 } 3170 if (pe->val.ui & RTSXOFF) { 3171 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3172 "keyspan_build_cmd_msg_usa49: " 3173 "pe->val.ui = %x, flow_ctl: RTSXOFF, " 3174 "no hardware support", pe->val.ui); 3175 } 3176 3177 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3178 "keyspan_build_cmd_msg_usa49: ctsFlowControl = %x," 3179 "dsrFlowControl = %x", ctrl_msg->ctsFlowControl, 3180 ctrl_msg->dsrFlowControl); 3181 3182 break; 3183 default: 3184 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, 3185 "keyspan_build_cmd_msg_usa49: bad param %d", 3186 pe->param); 3187 3188 break; 3189 } 3190 } 3191 3192 /* 3193 * enable the lcr settings only if they are different 3194 * with the existing settings. 3195 */ 3196 ctrl_msg->setLcr = (ctrl_msg->lcr == kp->kp_lcr) ? 0 : 1; 3197 3198 } 3199 3200 3201 /* 3202 * Set the port parameters to default values 3203 */ 3204 static void 3205 keyspan_default_port_params_usa49(keyspan_port_t *kp) 3206 { 3207 keyspan_usa49_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa49); 3208 ASSERT(mutex_owned(&kp->kp_mutex)); 3209 3210 keyspan_build_cmd_msg(kp, NULL); 3211 3212 ctrl_msg->setRts = 1; 3213 ctrl_msg->rts = 1; 3214 ctrl_msg->setDtr = 1; 3215 ctrl_msg->dtr = 1; 3216 3217 ctrl_msg->_txOn = 1; 3218 ctrl_msg->_txOff = 0; 3219 ctrl_msg->txFlush = 0; 3220 ctrl_msg->txBreak = 0; 3221 ctrl_msg->rxOn = 1; 3222 ctrl_msg->rxOff = 0; 3223 ctrl_msg->rxFlush = 0; 3224 ctrl_msg->rxForward = 0; 3225 ctrl_msg->returnStatus = 1; 3226 ctrl_msg->resetDataToggle = 0; 3227 ctrl_msg->enablePort = 1; 3228 ctrl_msg->disablePort = 0; 3229 3230 /* set baud rate to 9600 */ 3231 ctrl_msg->setClocking = 1; 3232 ctrl_msg->baudLo = keyspan_speedtab_usa49[13] & 0xff; 3233 ctrl_msg->baudHi = (keyspan_speedtab_usa49[13] >> 8) & 0xff; 3234 ctrl_msg->prescaler = keyspan_prescaler_49wlc[13]; 3235 3236 ctrl_msg->lcr = 0x3; 3237 ctrl_msg->setLcr = 1; 3238 3239 ctrl_msg->xonChar = CSTART; 3240 ctrl_msg->xoffChar = CSTOP; 3241 ctrl_msg->ctsFlowControl = 1; 3242 ctrl_msg->setFlowControl = 1; 3243 3244 } 3245 3246 3247 /* save the port params after send cmd successfully */ 3248 static void 3249 keyspan_save_port_params_usa49(keyspan_port_t *kp) 3250 { 3251 keyspan_usa49_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa49); 3252 3253 ASSERT(mutex_owned(&kp->kp_mutex)); 3254 3255 if (ctrl_msg->setClocking) { 3256 kp->kp_baud = ctrl_msg->baudHi; 3257 kp->kp_baud = (kp->kp_baud << 8); 3258 kp->kp_baud |= ctrl_msg->baudLo; 3259 } 3260 if (ctrl_msg->setLcr) { 3261 kp->kp_lcr = ctrl_msg->lcr; 3262 } 3263 if (ctrl_msg->setRts) { 3264 if (ctrl_msg->rts) { 3265 kp->kp_status_flag |= KEYSPAN_PORT_RTS; 3266 } else { 3267 kp->kp_status_flag &= ~KEYSPAN_PORT_RTS; 3268 } 3269 } 3270 if (ctrl_msg->setDtr) { 3271 if (ctrl_msg->dtr) { 3272 kp->kp_status_flag |= KEYSPAN_PORT_DTR; 3273 } else { 3274 kp->kp_status_flag &= ~KEYSPAN_PORT_DTR; 3275 } 3276 } 3277 3278 if (ctrl_msg->enablePort) { 3279 kp->kp_status_flag |= KEYSPAN_PORT_ENABLE; 3280 } else { 3281 kp->kp_status_flag &= ~KEYSPAN_PORT_ENABLE; 3282 } 3283 3284 /* 3285 * There are no flags in status msg (49wlc) can indicate the 3286 * break status, so we make use of ctrl_msg->txBreak here. 3287 */ 3288 if (ctrl_msg->txBreak) { 3289 kp->kp_status_flag |= KEYSPAN_PORT_TXBREAK; 3290 } else { 3291 kp->kp_status_flag &= ~KEYSPAN_PORT_TXBREAK; 3292 } 3293 3294 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, 3295 "keyspan_save_port_params: baud = %x, lcr = %x," 3296 "status_flag = %x", kp->kp_baud, kp->kp_lcr, kp->kp_status_flag); 3297 3298 } 3299