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