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