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