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