xref: /illumos-gate/usr/src/uts/common/io/usb/clients/usbser/usbser_keyspan/keyspan_dsd.c (revision e8ed0869d5c65afe0c37c4755bf81f7381d1f43c)
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
keyspan_attach(ds_attach_info_t * aip)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
keyspan_detach(ds_hdl_t hdl)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
keyspan_register_cb(ds_hdl_t hdl,uint_t port_num,ds_cb_t * cb)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
keyspan_unregister_cb(ds_hdl_t hdl,uint_t port_num)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
keyspan_open_hw_port(keyspan_port_t * kp,boolean_t open_pipes)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
keyspan_open_port(ds_hdl_t hdl,uint_t port_num)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
keyspan_close_hw_port(keyspan_port_t * kp)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
keyspan_close_port(ds_hdl_t hdl,uint_t port_num)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
keyspan_usb_power(ds_hdl_t hdl,int comp,int level,int * new_state)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
keyspan_suspend(ds_hdl_t hdl)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
keyspan_resume(ds_hdl_t hdl)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
keyspan_disconnect(ds_hdl_t hdl)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
keyspan_reconnect(ds_hdl_t hdl)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
keyspan_set_port_params(ds_hdl_t hdl,uint_t port_num,ds_port_params_t * tp)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
keyspan_set_modem_ctl(ds_hdl_t hdl,uint_t port_num,int mask,int val)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
keyspan_get_modem_ctl(ds_hdl_t hdl,uint_t port_num,int mask,int * valp)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
keyspan_break_ctl(ds_hdl_t hdl,uint_t port_num,int ctl)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
keyspan_loopback(ds_hdl_t hdl,uint_t port_num,int ctl)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
keyspan_tx(ds_hdl_t hdl,uint_t port_num,mblk_t * mp)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 *
keyspan_rx(ds_hdl_t hdl,uint_t port_num)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
keyspan_stop(ds_hdl_t hdl,uint_t port_num,int dir)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
keyspan_start(ds_hdl_t hdl,uint_t port_num,int dir)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
keyspan_fifo_flush(ds_hdl_t hdl,uint_t port_num,int dir)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
keyspan_fifo_drain(ds_hdl_t hdl,uint_t port_num,int timeout)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
keyspan_free_soft_state(keyspan_state_t * ksp)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
keyspan_usb_register(keyspan_state_t * ksp)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
keyspan_usb_unregister(keyspan_state_t * ksp)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
keyspan_init_sync_objs(keyspan_state_t * ksp)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
keyspan_fini_sync_objs(keyspan_state_t * ksp)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
keyspan_attach_dev(keyspan_state_t * ksp)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
keyspan_attach_ports(keyspan_state_t * ksp)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
keyspan_detach_ports(keyspan_state_t * ksp)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
keyspan_init_port_params(keyspan_state_t * ksp)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
keyspan_free_descr_tree(keyspan_state_t * ksp)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
keyspan_register_events(keyspan_state_t * ksp)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
keyspan_unregister_events(keyspan_state_t * ksp)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
keyspan_set_dev_state_online(keyspan_state_t * ksp)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
keyspan_send_cmd_usa49(keyspan_port_t * kp)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
keyspan_send_cmd_usa49wg(keyspan_port_t * kp)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
keyspan_send_cmd(keyspan_port_t * kp)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
keyspan_restore_device_state(keyspan_state_t * ksp)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
keyspan_restore_ports_state(keyspan_state_t * ksp)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
keyspan_create_pm_components(keyspan_state_t * ksp)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
keyspan_destroy_pm_components(keyspan_state_t * ksp)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
keyspan_pm_set_busy(keyspan_state_t * ksp)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
keyspan_pm_set_idle(keyspan_state_t * ksp)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
keyspan_pwrlvl0(keyspan_state_t * ksp)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
keyspan_pwrlvl1(keyspan_state_t * ksp)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
keyspan_pwrlvl2(keyspan_state_t * ksp)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
keyspan_pwrlvl3(keyspan_state_t * ksp)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
keyspan_attach_pipes(keyspan_state_t * ksp)2295 keyspan_attach_pipes(keyspan_state_t *ksp)
2296 {
2297 	return (keyspan_open_dev_pipes(ksp));
2298 }
2299 
2300 void
keyspan_detach_pipes(keyspan_state_t * ksp)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
keyspan_disconnect_pipes(keyspan_state_t * ksp)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
keyspan_reconnect_pipes(keyspan_state_t * ksp)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
keyspan_tx_start(keyspan_port_t * kp,int * xferd)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
keyspan_tx_copy_data(keyspan_port_t * kp,mblk_t * data,int len)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
keyspan_wait_tx_drain(keyspan_port_t * kp,int timeout)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
keyspan_dev_is_online(keyspan_state_t * ksp)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
keyspan_put_tail(mblk_t ** mpp,mblk_t * bp)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
keyspan_put_head(mblk_t ** mpp,mblk_t * bp,keyspan_port_t * kp)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
keyspan_default_port_params(keyspan_port_t * kp)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
keyspan_build_cmd_msg(keyspan_port_t * kp,ds_port_params_t * tp)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
keyspan_save_port_params(keyspan_port_t * kp)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
keyspan_save_port_params_usa19hs(keyspan_port_t * kp)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
keyspan_default_port_params_usa19hs(keyspan_port_t * kp)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
keyspan_build_cmd_msg_usa19hs(keyspan_port_t * kp,ds_port_params_t * tp)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
keyspan_build_cmd_msg_usa49(keyspan_port_t * kp,ds_port_params_t * tp)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
keyspan_default_port_params_usa49(keyspan_port_t * kp)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
keyspan_save_port_params_usa49(keyspan_port_t * kp)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