Home | History | Annotate | Download | only in usbser_keyspan
      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_usectohz(1000000 * 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 }
   3298