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