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 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27/*
28 *
29 * keyspanport pipe routines (mostly device-neutral)
30 *
31 */
32#include <sys/types.h>
33#include <sys/param.h>
34#include <sys/conf.h>
35#include <sys/stream.h>
36#include <sys/strsun.h>
37#include <sys/termio.h>
38#include <sys/ddi.h>
39#include <sys/sunddi.h>
40
41#include <sys/usb/usba.h>
42#include <sys/usb/clients/usbser/usbser_keyspan/keyspan_var.h>
43#include <sys/usb/clients/usbser/usbser_keyspan/keyspan_pipe.h>
44
45/*
46 * initialize pipe structure with the given parameters
47 */
48static void
49keyspan_init_one_pipe(keyspan_state_t *ksp, keyspan_port_t *kp,
50    keyspan_pipe_t *pipe)
51{
52	usb_pipe_policy_t	*policy;
53
54	USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_init_one_pipe: "
55	    "pipe = %p, pipe_stat %x", (void *)pipe, pipe->pipe_state);
56
57	/* init sync primitives */
58	mutex_init(&pipe->pipe_mutex, NULL, MUTEX_DRIVER, (void *)NULL);
59
60	/* init pipe policy */
61	policy = &pipe->pipe_policy;
62	policy->pp_max_async_reqs = 2;
63
64	pipe->pipe_ksp = ksp;
65	if (kp == NULL) {
66		/* globle pipes should have device log handle */
67		pipe->pipe_lh = ksp->ks_lh;
68	} else {
69		/* port pipes should have port log handle */
70		pipe->pipe_lh = kp->kp_lh;
71	}
72
73	pipe->pipe_state = KEYSPAN_PIPE_CLOSED;
74}
75
76
77static void
78keyspan_fini_one_pipe(keyspan_pipe_t *pipe)
79{
80	USB_DPRINTF_L4(DPRINT_OPEN, pipe->pipe_ksp->ks_lh,
81	    "keyspan_fini_one_pipe: pipe_stat %x", pipe->pipe_state);
82
83	if (pipe->pipe_state != KEYSPAN_PIPE_NOT_INIT) {
84		mutex_destroy(&pipe->pipe_mutex);
85		pipe->pipe_state = KEYSPAN_PIPE_NOT_INIT;
86	}
87}
88
89/*
90 * Lookup the endpoints defined in the spec;
91 * Allocate resources, initialize pipe structures.
92 * All are bulk pipes, including data in/out, cmd/status pipes.
93 */
94int
95keyspan_init_pipes(keyspan_state_t *ksp)
96{
97	usb_client_dev_data_t *dev_data = ksp->ks_dev_data;
98	int		ifc, alt, i, j, k = 0;
99	uint8_t		port_cnt = ksp->ks_dev_spec.port_cnt;
100	uint8_t		ep_addr, ep_cnt;
101	usb_ep_data_t	*dataout[KEYSPAN_MAX_PORT_NUM],
102	    *datain[KEYSPAN_MAX_PORT_NUM],
103	    *status = NULL, *ctrl = NULL, *tmp_ep;
104	usb_alt_if_data_t *alt_data;
105	usb_if_data_t *if_data;
106
107
108	ifc = dev_data->dev_curr_if;
109	alt = 0;
110	if_data = &dev_data->dev_curr_cfg->cfg_if[ifc];
111	alt_data = &if_data->if_alt[alt];
112
113	/*
114	 * The actual EP number (indicated by bNumEndpoints) is more than
115	 * those defined in spec. We have to match those we need according
116	 * to EP addresses. And we'll lookup In EPs and Out EPs separately.
117	 */
118	ep_cnt = (alt_data->altif_descr.bNumEndpoints + 1) / 2;
119
120	/*
121	 * get DIR_IN EP descriptors, and then match with EP addresses.
122	 * Different keyspan devices may has different EP addresses.
123	 */
124	for (i = 0; i < ep_cnt; i++) {
125		tmp_ep = usb_lookup_ep_data(ksp->ks_dip, dev_data, ifc, alt, i,
126		    USB_EP_ATTR_BULK, USB_EP_DIR_IN);
127		if (tmp_ep == NULL) {
128			USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh,
129			    "keyspan_init_pipes: can't find bulk in ep, i=%d,"
130			    "ep_cnt=%d", i, ep_cnt);
131
132			continue;
133		}
134		ep_addr = tmp_ep->ep_descr.bEndpointAddress;
135
136		USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh, "keyspan_init_pipes: "
137		    "ep_addr =%x, stat_ep_addr=%x, i=%d", ep_addr,
138		    ksp->ks_dev_spec.stat_ep_addr, i);
139
140		/* match the status EP */
141		if (ep_addr == ksp->ks_dev_spec.stat_ep_addr) {
142			status = tmp_ep;
143
144			continue;
145		}
146
147		/* match the EPs of the ports */
148		for (j = 0; j < port_cnt; j++) {
149			USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh,
150			    "keyspan_init_pipes: try to match bulk in data ep,"
151			    " j=%d", j);
152			if (ep_addr == ksp->ks_dev_spec.datain_ep_addr[j]) {
153				datain[j] = tmp_ep;
154				k++;
155				USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh,
156				    "keyspan_init_pipes: matched a bulk in"
157				    " data ep");
158
159				break;
160			}
161		}
162
163		/* if have matched all the necessary endpoints, break out */
164		if (k >= port_cnt && status != NULL) {
165
166			break;
167		}
168
169		USB_DPRINTF_L4(DPRINT_ATTACH, ksp->ks_lh, "keyspan_init_pipes: "
170		    "try to match bulk in data ep, j=%d", j);
171
172		if (j == port_cnt) {
173			/* this ep can't be matched by any addr */
174			USB_DPRINTF_L4(DPRINT_ATTACH, ksp->ks_lh,
175			    "keyspan_init_pipes: can't match bulk in ep,"
176			    " addr =%x,", ep_addr);
177		}
178	}
179
180	if (k != port_cnt || status == NULL) {
181
182		/* Some of the necessary IN endpoints are not matched */
183		USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
184		    "keyspan_init_pipes: matched %d data in endpoints,"
185		    " not enough", k);
186
187		return (USB_FAILURE);
188	}
189
190	k = 0;
191
192	/*
193	 * get DIR_OUT EP descriptors, and then match with ep addrs.
194	 * different keyspan devices may has different ep addresses.
195	 */
196	for (i = 0; i < ep_cnt; i++) {
197		tmp_ep = usb_lookup_ep_data(ksp->ks_dip, dev_data, ifc, alt, i,
198		    USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
199		if (tmp_ep == NULL) {
200			USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh,
201			    "keyspan_init_pipes: can't find bulk out ep, i=%d,"
202			    "ep_cnt=%d", i, ep_cnt);
203
204			continue;
205		}
206		ep_addr = tmp_ep->ep_descr.bEndpointAddress;
207
208		/* match the status ep */
209		if (ep_addr == ksp->ks_dev_spec.ctrl_ep_addr) {
210			ctrl = tmp_ep;
211
212			continue;
213		}
214
215		/* match the ep of the ports */
216		for (j = 0; j < port_cnt; j++) {
217			if (ep_addr == ksp->ks_dev_spec.dataout_ep_addr[j]) {
218				dataout[j] = tmp_ep;
219				k++;
220
221				break;
222			}
223		}
224		/* if have matched all the necessary endpoints, break out */
225		if (k >= port_cnt && ctrl != NULL) {
226
227			break;
228		}
229
230		if (j == port_cnt) {
231
232			/* this ep can't be matched by any addr */
233			USB_DPRINTF_L4(DPRINT_ATTACH, ksp->ks_lh,
234			    "keyspan_init_pipes: can't match bulk out ep,"
235			    " ep_addr =%x", ep_addr);
236
237		}
238	}
239
240	if (k != port_cnt || ctrl == NULL) {
241		/* Not all the necessary OUT endpoints are matched */
242		USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
243		    "keyspan_init_pipes: matched %d data in endpoints,"
244		    " not enough", k);
245
246		return (USB_FAILURE);
247	}
248
249	mutex_enter(&ksp->ks_mutex);
250
251	/*
252	 * Device globle pipes: a bulk in pipe for status and a bulk out
253	 * pipe for controle cmd.
254	 */
255	ksp->ks_statin_pipe.pipe_ep_descr = status->ep_descr;
256	keyspan_init_one_pipe(ksp, NULL, &ksp->ks_statin_pipe);
257
258	ksp->ks_ctrlout_pipe.pipe_ep_descr = ctrl->ep_descr;
259	keyspan_init_one_pipe(ksp, NULL, &ksp->ks_ctrlout_pipe);
260
261	/* for data in/out pipes of each port */
262	for (i = 0; i < port_cnt; i++) {
263
264		ksp->ks_ports[i].kp_datain_pipe.pipe_ep_descr =
265		    datain[i]->ep_descr;
266		keyspan_init_one_pipe(ksp, &ksp->ks_ports[i],
267		    &ksp->ks_ports[i].kp_datain_pipe);
268
269		ksp->ks_ports[i].kp_dataout_pipe.pipe_ep_descr =
270		    dataout[i]->ep_descr;
271		keyspan_init_one_pipe(ksp, &ksp->ks_ports[i],
272		    &ksp->ks_ports[i].kp_dataout_pipe);
273	}
274
275	mutex_exit(&ksp->ks_mutex);
276
277	return (USB_SUCCESS);
278}
279/*
280 * For USA_49WG only.
281 * Lookup the endpoints defined in the spec.
282 * Allocate resources, initialize pipe structures.
283 * There are 6 EPs, 3 bulk out Eps, 1 bulk in EP, 1 intr in EP, 1 intr out EP
284 */
285int
286keyspan_init_pipes_usa49wg(keyspan_state_t *ksp)
287{
288	usb_client_dev_data_t *dev_data = ksp->ks_dev_data;
289	int		ifc, alt, i, j = 0;
290	uint8_t		port_cnt = ksp->ks_dev_spec.port_cnt;
291	uint8_t		ep_addr;
292	usb_ep_data_t	*dataout[KEYSPAN_MAX_PORT_NUM],
293	    *datain[KEYSPAN_MAX_PORT_NUM],
294	    *status = NULL, *tmp_ep;
295
296	ifc = dev_data->dev_curr_if;
297	alt = 0;
298
299	/*
300	 * get intr out EP descriptor as port0 data out EP, and then
301	 * match with EP address.
302	 * Different keyspan devices may has different EP addresses.
303	 */
304	tmp_ep = usb_lookup_ep_data(ksp->ks_dip, dev_data, ifc, alt, 0,
305	    USB_EP_ATTR_INTR, USB_EP_DIR_OUT);
306	if (tmp_ep == NULL) {
307		USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh,
308		    "keyspan_init_pipes: can't find port1 data out ep");
309
310		return (USB_FAILURE);
311		}
312	ep_addr = tmp_ep->ep_descr.bEndpointAddress;
313
314	/* match the port0 data out EP */
315	if (ep_addr == ksp->ks_dev_spec.dataout_ep_addr[0]) {
316		dataout[0] = tmp_ep;
317	}
318
319	/*
320	 * get bulk out EP descriptors as other port data out EPs, and then
321	 * match with EP addresses.
322	 */
323	for (j = 1; j < port_cnt; j++) {
324		tmp_ep = usb_lookup_ep_data(ksp->ks_dip, dev_data, ifc, alt,
325		    j-1, USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
326		if (tmp_ep == NULL) {
327			USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh,
328			    "keyspan_init_pipes: can't find port[%d] "
329			    "data out ep",
330			    j);
331			return (USB_FAILURE);
332		}
333
334		ep_addr = tmp_ep->ep_descr.bEndpointAddress;
335
336		/* match other port data out EPs */
337		if (ep_addr == ksp->ks_dev_spec.dataout_ep_addr[j]) {
338			dataout[j] = tmp_ep;
339		}
340	}
341
342	/*
343	 * get intr in EP descriptor as status EP, and then match with EP addrs
344	 */
345	tmp_ep = usb_lookup_ep_data(ksp->ks_dip, dev_data, ifc, alt, 0,
346	    USB_EP_ATTR_INTR, USB_EP_DIR_IN);
347	if (tmp_ep == NULL) {
348		USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh,
349		    "keyspan_init_pipes: can't find status in ep");
350
351		return (USB_FAILURE);
352	}
353	ep_addr = tmp_ep->ep_descr.bEndpointAddress;
354
355	/* match the status ep */
356	if (ep_addr == ksp->ks_dev_spec.stat_ep_addr) {
357		status = tmp_ep;
358	}
359
360	/*
361	 * get bulk in EP descriptors as data in EP, All the ports share one
362	 * data in EP.
363	 */
364	tmp_ep = usb_lookup_ep_data(ksp->ks_dip, dev_data, ifc, alt, 0,
365	    USB_EP_ATTR_BULK, USB_EP_DIR_IN);
366	if (tmp_ep == NULL) {
367		USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh,
368		    "keyspan_init_pipes: can't find bulk in ep");
369
370		return (USB_FAILURE);
371	}
372	ep_addr = tmp_ep->ep_descr.bEndpointAddress;
373
374	/* match data in EPs */
375	if (ep_addr == ksp->ks_dev_spec.datain_ep_addr[0]) {
376		datain[0] = tmp_ep;
377	}
378
379	mutex_enter(&ksp->ks_mutex);
380
381	/* intr in pipe for status */
382	ksp->ks_statin_pipe.pipe_ep_descr = status->ep_descr;
383	keyspan_init_one_pipe(ksp, NULL, &ksp->ks_statin_pipe);
384
385	/* for data in/out pipes of each port */
386	for (i = 0; i < port_cnt; i++) {
387		ksp->ks_ports[i].kp_datain_pipe.pipe_ep_descr =
388		    datain[0]->ep_descr;
389		keyspan_init_one_pipe(ksp, &ksp->ks_ports[i],
390		    &ksp->ks_ports[i].kp_datain_pipe);
391
392		ksp->ks_ports[i].kp_dataout_pipe.pipe_ep_descr =
393		    dataout[i]->ep_descr;
394		keyspan_init_one_pipe(ksp, &ksp->ks_ports[i],
395		    &ksp->ks_ports[i].kp_dataout_pipe);
396	}
397
398	mutex_exit(&ksp->ks_mutex);
399
400	return (USB_SUCCESS);
401}
402
403void
404keyspan_fini_pipes(keyspan_state_t *ksp)
405{
406	keyspan_port_t	*kp;
407	int		i;
408
409	for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
410		kp = &ksp->ks_ports[i];
411		keyspan_fini_one_pipe(&kp->kp_datain_pipe);
412		keyspan_fini_one_pipe(&kp->kp_dataout_pipe);
413	}
414
415	/* fini status pipe */
416	keyspan_fini_one_pipe(&ksp->ks_statin_pipe);
417	/*
418	 * fini control pipe
419	 * If USA_49WG, don't need fini control pipe
420	 */
421	switch (ksp->ks_dev_spec.id_product) {
422		case KEYSPAN_USA19HS_PID:
423		case KEYSPAN_USA49WLC_PID:
424			keyspan_fini_one_pipe(&ksp->ks_ctrlout_pipe);
425
426			break;
427		case KEYSPAN_USA49WG_PID:
428
429			break;
430		default:
431			USB_DPRINTF_L2(DPRINT_CTLOP, ksp->ks_lh,
432			    "keyspan_fini_pipes: the device's product id"
433			    "can't be recognized");
434	}
435}
436
437static int
438keyspan_open_one_pipe(keyspan_state_t *ksp, keyspan_pipe_t *pipe)
439{
440	int	rval;
441
442	/* don't open for the second time */
443	mutex_enter(&pipe->pipe_mutex);
444	ASSERT(pipe->pipe_state != KEYSPAN_PIPE_NOT_INIT);
445	if (pipe->pipe_state != KEYSPAN_PIPE_CLOSED) {
446		mutex_exit(&pipe->pipe_mutex);
447
448		return (USB_SUCCESS);
449	}
450	mutex_exit(&pipe->pipe_mutex);
451
452	rval = usb_pipe_open(ksp->ks_dip, &pipe->pipe_ep_descr,
453	    &pipe->pipe_policy, USB_FLAGS_SLEEP, &pipe->pipe_handle);
454
455	if (rval == USB_SUCCESS) {
456		mutex_enter(&pipe->pipe_mutex);
457		pipe->pipe_state = KEYSPAN_PIPE_OPEN;
458		mutex_exit(&pipe->pipe_mutex);
459	}
460
461	return (rval);
462}
463
464/*
465 * Open shared datain pipe for USA_49WG
466 */
467static int
468keyspan_open_pipe_datain_usa49wg(keyspan_state_t *ksp, keyspan_pipe_t *pipe)
469{
470	int	rval = USB_SUCCESS;
471
472	/* don't open for the second time */
473	mutex_enter(&pipe->pipe_mutex);
474	ASSERT(pipe->pipe_state != KEYSPAN_PIPE_NOT_INIT);
475	if (pipe->pipe_state != KEYSPAN_PIPE_CLOSED) {
476		mutex_exit(&pipe->pipe_mutex);
477
478		return (USB_SUCCESS);
479	}
480	mutex_exit(&pipe->pipe_mutex);
481
482	mutex_enter(&ksp->ks_mutex);
483	ksp->ks_datain_open_cnt++;
484	if (ksp->ks_datain_open_cnt == 1) {
485		mutex_exit(&ksp->ks_mutex);
486
487		if ((rval = (usb_pipe_open(ksp->ks_dip, &pipe->pipe_ep_descr,
488		    &pipe->pipe_policy, USB_FLAGS_SLEEP,
489		    &pipe->pipe_handle))) == USB_SUCCESS) {
490				mutex_enter(&pipe->pipe_mutex);
491				pipe->pipe_state = KEYSPAN_PIPE_OPEN;
492				mutex_exit(&pipe->pipe_mutex);
493
494				mutex_enter(&ksp->ks_mutex);
495				ksp->ks_datain_pipe_handle = pipe->pipe_handle;
496				mutex_exit(&ksp->ks_mutex);
497		} else {
498				mutex_enter(&ksp->ks_mutex);
499				ksp->ks_datain_open_cnt--;
500				mutex_exit(&ksp->ks_mutex);
501		}
502
503		return (rval);
504	} else {
505		/* data in pipe has been opened by other port */
506		ASSERT(ksp->ks_datain_pipe_handle != NULL);
507
508		mutex_enter(&pipe->pipe_mutex);
509		pipe->pipe_handle = ksp->ks_datain_pipe_handle;
510		/* Set datain pipe state */
511		pipe->pipe_state = KEYSPAN_PIPE_OPEN;
512		mutex_exit(&pipe->pipe_mutex);
513		mutex_exit(&ksp->ks_mutex);
514
515		return (USB_SUCCESS);
516	}
517}
518
519/*
520 * close one pipe if open
521 */
522static void
523keyspan_close_one_pipe(keyspan_pipe_t *pipe)
524{
525	/*
526	 * pipe may already be closed, e.g. if device has been physically
527	 * disconnected and the driver immediately detached
528	 */
529	if (pipe->pipe_handle != NULL) {
530		usb_pipe_close(pipe->pipe_ksp->ks_dip, pipe->pipe_handle,
531		    USB_FLAGS_SLEEP, NULL, NULL);
532		mutex_enter(&pipe->pipe_mutex);
533		pipe->pipe_handle = NULL;
534		pipe->pipe_state = KEYSPAN_PIPE_CLOSED;
535		mutex_exit(&pipe->pipe_mutex);
536	}
537}
538
539/*
540 * close shared datain pipe if open for USA_49WG
541 */
542static void
543keyspan_close_pipe_datain_usa49wg(keyspan_pipe_t *pipe)
544{
545	keyspan_state_t *ksp = pipe->pipe_ksp;
546	/*
547	 * pipe may already be closed, e.g. if device has been physically
548	 * disconnected and the driver immediately detached
549	 */
550	if (pipe->pipe_handle != NULL) {
551		mutex_enter(&ksp->ks_mutex);
552		ksp->ks_datain_open_cnt--;
553		if (!ksp->ks_datain_open_cnt) {
554			mutex_exit(&ksp->ks_mutex);
555			usb_pipe_close(pipe->pipe_ksp->ks_dip,
556			    pipe->pipe_handle, USB_FLAGS_SLEEP,
557			    NULL, NULL);
558		} else {
559			mutex_exit(&ksp->ks_mutex);
560		}
561
562		mutex_enter(&pipe->pipe_mutex);
563		pipe->pipe_handle = NULL;
564		pipe->pipe_state = KEYSPAN_PIPE_CLOSED;
565		mutex_exit(&pipe->pipe_mutex);
566	}
567}
568
569/*
570 * For USA19HS and USA49WLC:
571 * Open global pipes, a status pipe and a control pipe
572 */
573int
574keyspan_open_dev_pipes_usa49(keyspan_state_t *ksp)
575{
576	int		rval;
577
578	USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh,
579	    "keyspan_open_dev_pipes_usa49");
580
581	rval = keyspan_open_one_pipe(ksp, &ksp->ks_ctrlout_pipe);
582	if (rval != USB_SUCCESS) {
583		USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh,
584		    "keyspan_open_dev_pipes_usa49: open ctrl pipe failed %d",
585		    rval);
586		return (rval);
587	}
588
589	rval = keyspan_open_one_pipe(ksp, &ksp->ks_statin_pipe);
590	if (rval != USB_SUCCESS) {
591		USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh,
592		    "keyspan_open_dev_pipes_usa49: open status pipe failed %d",
593		    rval);
594
595		/* close the first opened pipe here */
596		keyspan_close_one_pipe(&ksp->ks_ctrlout_pipe);
597
598		return (rval);
599	}
600
601	/* start receive device status */
602	rval = keyspan_receive_status(ksp);
603	if (rval != USB_SUCCESS) {
604		USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh,
605		    "keyspan_open_dev_pipes_usa49: receive device status"
606		    " failed %d", rval);
607
608		/* close opened pipes here */
609		keyspan_close_one_pipe(&ksp->ks_statin_pipe);
610		keyspan_close_one_pipe(&ksp->ks_ctrlout_pipe);
611
612		return (rval);
613	}
614
615	return (rval);
616}
617
618/*
619 * For keyspan USA_49WG:
620 * Open global pipes, a status pipe
621 * Use default control pipe, don't need to open it.
622 */
623int
624keyspan_open_dev_pipes_usa49wg(keyspan_state_t *ksp)
625{
626	int		rval;
627
628	/* Open status pipe */
629	rval = keyspan_open_one_pipe(ksp, &ksp->ks_statin_pipe);
630	if (rval != USB_SUCCESS) {
631		USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh,
632		    "keyspan_open_dev_pipes_usa49wg: "
633		    "open status pipe failed %d",
634		    rval);
635
636		return (rval);
637	}
638	/* start device polling */
639	keyspan_pipe_start_polling(&ksp->ks_statin_pipe);
640
641	return (rval);
642}
643
644/*
645 * Open global pipes, status pipe and control pipe,
646 */
647int
648keyspan_open_dev_pipes(keyspan_state_t *ksp)
649{
650	int		rval = USB_SUCCESS;
651
652	USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_open_dev_pipes");
653
654	switch (ksp->ks_dev_spec.id_product) {
655	case KEYSPAN_USA19HS_PID:
656	case KEYSPAN_USA49WLC_PID:
657		rval = keyspan_open_dev_pipes_usa49(ksp);
658
659		break;
660	case KEYSPAN_USA49WG_PID:
661		rval = keyspan_open_dev_pipes_usa49wg(ksp);
662
663		break;
664	default:
665		USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh,
666		    "keyspan_open_dev_pipes: the device's product id can't"
667		    "be recognized");
668
669		return (USB_FAILURE);
670	}
671	return (rval);
672}
673
674/*
675 * Reopen all pipes if the port had them open
676 */
677int
678keyspan_reopen_pipes(keyspan_state_t *ksp)
679{
680	keyspan_port_t	*kp;
681	int		i;
682
683	USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_reopen_pipes");
684
685	if (keyspan_open_dev_pipes(ksp) != USB_SUCCESS) {
686
687		return (USB_FAILURE);
688	}
689
690	for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
691		kp = &ksp->ks_ports[i];
692		mutex_enter(&kp->kp_mutex);
693		if (kp->kp_state == KEYSPAN_PORT_OPEN) {
694			USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh,
695			    "keyspan_reopen_pipes() reopen pipe #%d", i);
696			mutex_exit(&kp->kp_mutex);
697			if (keyspan_open_port_pipes(kp) != USB_SUCCESS) {
698
699				return (USB_FAILURE);
700			}
701			mutex_enter(&kp->kp_mutex);
702			kp->kp_no_more_reads = B_FALSE;
703		}
704		mutex_exit(&kp->kp_mutex);
705	}
706
707	return (USB_SUCCESS);
708}
709
710void
711keyspan_close_port_pipes(keyspan_port_t *kp)
712{
713	keyspan_state_t *ksp =	kp->kp_ksp;
714
715	USB_DPRINTF_L4(DPRINT_CLOSE, kp->kp_lh, "keyspan_close_port_pipes");
716
717	switch (ksp->ks_dev_spec.id_product) {
718	case KEYSPAN_USA19HS_PID:
719	case KEYSPAN_USA49WLC_PID:
720		keyspan_close_one_pipe(&kp->kp_datain_pipe);
721
722		break;
723	case KEYSPAN_USA49WG_PID:
724		keyspan_close_pipe_datain_usa49wg(&kp->kp_datain_pipe);
725
726		break;
727	default:
728		USB_DPRINTF_L2(DPRINT_CLOSE, kp->kp_lh,
729		    "keyspan_close_port_pipes:"
730		    "the device's product id can't be recognized");
731	}
732	keyspan_close_one_pipe(&kp->kp_dataout_pipe);
733}
734
735/*
736 * Close IN and OUT bulk pipes of all ports
737 */
738void
739keyspan_close_open_pipes(keyspan_state_t *ksp)
740{
741	keyspan_port_t	*kp;
742	int		i;
743	int		port_num = -1;
744
745	USB_DPRINTF_L4(DPRINT_CLOSE, ksp->ks_lh, "keyspan_close_open_pipes");
746
747	switch (ksp->ks_dev_spec.id_product) {
748	case KEYSPAN_USA19HS_PID:
749	case KEYSPAN_USA49WLC_PID:
750		for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
751			kp = &ksp->ks_ports[i];
752			mutex_enter(&kp->kp_mutex);
753			if (kp->kp_state == KEYSPAN_PORT_OPEN) {
754				kp->kp_no_more_reads = B_TRUE;
755				mutex_exit(&kp->kp_mutex);
756				usb_pipe_reset(ksp->ks_dip,
757				    kp->kp_datain_pipe.pipe_handle,
758				    USB_FLAGS_SLEEP, NULL, NULL);
759				keyspan_close_port_pipes(kp);
760			} else {
761				mutex_exit(&kp->kp_mutex);
762			}
763		}
764
765		break;
766
767	case KEYSPAN_USA49WG_PID:
768		for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
769			kp = &ksp->ks_ports[i];
770			mutex_enter(&kp->kp_mutex);
771			if (kp->kp_state == KEYSPAN_PORT_OPEN) {
772				kp->kp_no_more_reads = B_TRUE;
773				port_num = i;
774			}
775			mutex_exit(&kp->kp_mutex);
776		}
777		if (port_num >= 0) {
778			kp = &ksp->ks_ports[port_num];
779			usb_pipe_reset(ksp->ks_dip,
780			    kp->kp_datain_pipe.pipe_handle,
781			    USB_FLAGS_SLEEP, NULL, NULL);
782		}
783
784		for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
785			kp = &ksp->ks_ports[i];
786			mutex_enter(&kp->kp_mutex);
787			if (kp->kp_state == KEYSPAN_PORT_OPEN) {
788				mutex_exit(&kp->kp_mutex);
789				keyspan_close_port_pipes(kp);
790			} else {
791				mutex_exit(&kp->kp_mutex);
792			}
793		}
794
795		break;
796	default:
797		USB_DPRINTF_L2(DPRINT_CLOSE, ksp->ks_lh,
798		    "keyspan_close_open_pipes:"
799		    "the device's product id can't be recognized");
800
801	}
802}
803
804/*
805 * Close global pipes
806 */
807void
808keyspan_close_dev_pipes(keyspan_state_t *ksp)
809{
810	USB_DPRINTF_L4(DPRINT_CLOSE, ksp->ks_lh, "keyspan_close_dev_pipes");
811
812	switch (ksp->ks_dev_spec.id_product) {
813	case KEYSPAN_USA19HS_PID:
814	case KEYSPAN_USA49WLC_PID:
815		keyspan_close_one_pipe(&ksp->ks_statin_pipe);
816		keyspan_close_one_pipe(&ksp->ks_ctrlout_pipe);
817
818		break;
819
820	case KEYSPAN_USA49WG_PID:
821		/*
822		 * USA_49WG use default control pipe, don't need close it
823		 * Stop polling before close status in pipe
824		 */
825		usb_pipe_stop_intr_polling(ksp->ks_statin_pipe.pipe_handle,
826		    USB_FLAGS_SLEEP);
827		keyspan_close_one_pipe(&ksp->ks_statin_pipe);
828
829		break;
830	default:
831		USB_DPRINTF_L2(DPRINT_CLOSE, ksp->ks_lh,
832		    "keyspan_close_dev_pipes:"
833		    "the device's product id can't be recognized");
834	}
835
836}
837
838/*
839 * Open bulk data IN and data OUT pipes for one port.
840 * The status and control pipes are opened in attach because they are global.
841 */
842int
843keyspan_open_port_pipes(keyspan_port_t *kp)
844{
845	keyspan_state_t	*ksp = kp->kp_ksp;
846	int		rval;
847
848	USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh, "keyspan_open_port_pipes");
849
850	switch (ksp->ks_dev_spec.id_product) {
851	case KEYSPAN_USA19HS_PID:
852	case KEYSPAN_USA49WLC_PID:
853		rval = keyspan_open_one_pipe(ksp, &kp->kp_datain_pipe);
854
855		break;
856	case KEYSPAN_USA49WG_PID:
857		rval = keyspan_open_pipe_datain_usa49wg(ksp,
858		    &kp->kp_datain_pipe);
859
860		break;
861	default:
862		USB_DPRINTF_L2(DPRINT_OPEN, kp->kp_lh,
863		    "keyspan_open_port_pipes:"
864		    "the device's product id can't be recognized");
865	}
866
867	if (rval != USB_SUCCESS) {
868
869		goto fail;
870	}
871
872	rval = keyspan_open_one_pipe(ksp, &kp->kp_dataout_pipe);
873	if (rval != USB_SUCCESS) {
874
875		goto fail;
876	}
877
878	return (rval);
879
880fail:
881	USB_DPRINTF_L2(DPRINT_OPEN, kp->kp_lh,
882	    "keyspan_open_port_pipes: failed %d", rval);
883	keyspan_close_port_pipes(kp);
884
885	return (rval);
886}
887
888void
889keyspan_close_pipes(keyspan_state_t *ksp)
890{
891	USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_close_pipes");
892
893	/* close all ports' pipes first, and then device ctrl/status pipes. */
894	keyspan_close_open_pipes(ksp);
895	keyspan_close_dev_pipes(ksp);
896}
897/*
898 * bulk out common callback
899 */
900/*ARGSUSED*/
901void
902keyspan_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
903{
904	keyspan_port_t	*kp = (keyspan_port_t *)req->bulk_client_private;
905	keyspan_pipe_t	*bulkout = &kp->kp_dataout_pipe;
906	mblk_t		*data = req->bulk_data;
907	int		data_len;
908
909	data_len = (data) ? MBLKL(data) : 0;
910
911	USB_DPRINTF_L4(DPRINT_OUT_PIPE, bulkout->pipe_lh,
912	    "keyspan_bulkout_cb: len=%d cr=%d cb_flags=%x",
913	    data_len, req->bulk_completion_reason, req->bulk_cb_flags);
914
915	if (req->bulk_completion_reason && data) {
916
917		/*
918		 * Data wasn't transfered successfully.
919		 * Put data back on the queue.
920		 */
921		keyspan_put_head(&kp->kp_tx_mp, data, kp);
922
923		/* don't release mem in usb_free_bulk_req */
924		req->bulk_data = NULL;
925	}
926
927	usb_free_bulk_req(req);
928
929	/* if more data available, kick off another transmit */
930	mutex_enter(&kp->kp_mutex);
931	if (kp->kp_tx_mp == NULL) {
932		/*
933		 * Attach a zero packet if data length is muliple of 64,
934		 * due to the specification of keyspan_usa19hs.
935		 */
936		if ((kp->kp_ksp->ks_dev_spec.id_product ==
937		    KEYSPAN_USA19HS_PID) && (data_len == 64)) {
938			kp->kp_tx_mp = allocb(0, BPRI_LO);
939			if (kp->kp_tx_mp) {
940				keyspan_tx_start(kp, NULL);
941				mutex_exit(&kp->kp_mutex);
942
943				return;
944			}
945		}
946		/* no more data, notify waiters */
947		cv_broadcast(&kp->kp_tx_cv);
948		mutex_exit(&kp->kp_mutex);
949
950		/* tx callback for this port */
951		kp->kp_cb.cb_tx(kp->kp_cb.cb_arg);
952	} else {
953		keyspan_tx_start(kp, NULL);
954		mutex_exit(&kp->kp_mutex);
955	}
956}
957
958/*
959 * intr out common callback for USA_49WG port0 only
960 */
961/*ARGSUSED*/
962void
963keyspan_introut_cb_usa49wg(usb_pipe_handle_t pipe, usb_intr_req_t *req)
964{
965	keyspan_port_t	*kp = (keyspan_port_t *)req->intr_client_private;
966	keyspan_pipe_t	*introut = &kp->kp_dataout_pipe;
967	mblk_t		*data = req->intr_data;
968	int		data_len;
969
970	data_len = (data) ? MBLKL(data) : 0;
971
972	USB_DPRINTF_L4(DPRINT_OUT_PIPE, introut->pipe_lh,
973	    "keyspan_introut_cb_usa49wg: len=%d cr=%d cb_flags=%x",
974	    data_len, req->intr_completion_reason, req->intr_cb_flags);
975
976	if (req->intr_completion_reason && (data_len > 0)) {
977
978		/*
979		 * Data wasn't transfered successfully.
980		 * Put data back on the queue.
981		 */
982		keyspan_put_head(&kp->kp_tx_mp, data, kp);
983
984		/* don't release mem in usb_free_bulk_req */
985		req->intr_data = NULL;
986	}
987
988	usb_free_intr_req(req);
989
990	/* if more data available, kick off another transmit */
991	mutex_enter(&kp->kp_mutex);
992	if (kp->kp_tx_mp == NULL) {
993
994		/* no more data, notify waiters */
995		cv_broadcast(&kp->kp_tx_cv);
996		mutex_exit(&kp->kp_mutex);
997
998		/* tx callback for this port */
999		kp->kp_cb.cb_tx(kp->kp_cb.cb_arg);
1000	} else {
1001		keyspan_tx_start(kp, NULL);
1002		mutex_exit(&kp->kp_mutex);
1003	}
1004}
1005
1006
1007/* For incoming data only. Parse a status byte and return the err code */
1008void
1009keyspan_parse_status(uchar_t *status, uchar_t *err)
1010{
1011	if (*status & RXERROR_BREAK) {
1012		/*
1013		 * Parity and Framing errors only count if they
1014		 * occur exclusive of a break being received.
1015		 */
1016		*status &= (uint8_t)(RXERROR_OVERRUN | RXERROR_BREAK);
1017	}
1018	*err |= (*status & RXERROR_OVERRUN) ? DS_OVERRUN_ERR : 0;
1019	*err |= (*status & RXERROR_PARITY) ? DS_PARITY_ERR : 0;
1020	*err |= (*status & RXERROR_FRAMING) ? DS_FRAMING_ERR : 0;
1021	*err |= (*status & RXERROR_BREAK) ? DS_BREAK_ERR : 0;
1022}
1023
1024/* Bulk in data process function, used by all models */
1025int
1026keyspan_bulkin_cb_process(keyspan_port_t *kp,
1027		uint8_t data_len, uchar_t status, mblk_t *data)
1028{
1029	uchar_t	err = 0;
1030	mblk_t	*mp;
1031	/*
1032	 * According to Keyspan spec, if 0x80 bit is clear, there is
1033	 * only one status byte at the head of the data buf; if 0x80 bit
1034	 * set, then data buf contains alternate status and data bytes;
1035	 * In the first case, only OVERRUN err can exist; In the second
1036	 * case, there are four kinds of err bits may appear in status.
1037	 */
1038
1039	/* if 0x80 bit AND overrun bit are clear, just send up data */
1040	if (!(status & 0x80) && !(status & RXERROR_OVERRUN)) {
1041
1042		/* Get rid of the first status byte */
1043		data->b_rptr++;
1044		data_len--;
1045
1046	} else if (!(status & 0x80)) {
1047		/* If 0x80 bit is clear and overrun bit is set */
1048
1049		keyspan_parse_status(&status, &err);
1050		mutex_exit(&kp->kp_mutex);
1051		if ((mp = allocb(2, BPRI_HI)) == NULL) {
1052			USB_DPRINTF_L2(DPRINT_IN_PIPE, kp->kp_lh,
1053			    "keyspan_bulkin_cb_process: allocb failed");
1054			mutex_enter(&kp->kp_mutex);
1055
1056			return (0);
1057		}
1058		DB_TYPE(mp) = M_BREAK;
1059		*mp->b_wptr++ = err;
1060		*mp->b_wptr++ = status;
1061		mutex_enter(&kp->kp_mutex);
1062
1063		/* Add to the received list; Send up the err code. */
1064		keyspan_put_tail(&kp->kp_rx_mp, mp);
1065
1066		/*
1067		 * Don't send up the first byte because
1068		 * it is a status byte.
1069		 */
1070		data->b_rptr++;
1071		data_len--;
1072
1073	} else { /* 0x80 bit set, there are some errs in the data */
1074		/*
1075		 * Usually, there are at least two bytes,
1076		 * one status and one data.
1077		 */
1078		if (data_len > 1) {
1079			int i = 0;
1080			int j = 1;
1081			/*
1082			 * In this case, there might be multi status
1083			 * bytes. Parse each status byte and move the
1084			 * data bytes together.
1085			 */
1086			for (j = 1; j < data_len; j += 2) {
1087				status = data->b_rptr[j-1];
1088				keyspan_parse_status(&status, &err);
1089
1090				/* move the data togeter */
1091				data->b_rptr[i] = data->b_rptr[j];
1092				i++;
1093			}
1094			data->b_wptr = data->b_rptr + i;
1095		} else { /* There are only one byte in incoming buf */
1096			keyspan_parse_status(&status, &err);
1097		}
1098		mutex_exit(&kp->kp_mutex);
1099		if ((mp = allocb(2, BPRI_HI)) == NULL) {
1100			USB_DPRINTF_L2(DPRINT_IN_PIPE, kp->kp_lh,
1101			    "keyspan_bulkin_cb_process: allocb failed");
1102			mutex_enter(&kp->kp_mutex);
1103
1104			return (0);
1105		}
1106		DB_TYPE(mp) = M_BREAK;
1107		*mp->b_wptr++ = err;
1108		if (data_len > 2) {
1109			/*
1110			 * There are multiple status bytes in this case.
1111			 * Use err as status character since err is got
1112			 * by or in all status bytes.
1113			 */
1114			*mp->b_wptr++ = err;
1115		} else {
1116			*mp->b_wptr++ = status;
1117		}
1118		mutex_enter(&kp->kp_mutex);
1119
1120		/* Add to the received list; Send up the err code. */
1121		keyspan_put_tail(&kp->kp_rx_mp, mp);
1122
1123		if (data_len > 1) {
1124			data_len = MBLKL(data);
1125		}
1126	}
1127	return (data_len);
1128}
1129
1130/*
1131 * pipe callbacks
1132 * --------------
1133 *
1134 * bulk in common callback for USA19HS and USA49WLC model
1135 */
1136/*ARGSUSED*/
1137int
1138keyspan_bulkin_cb_usa49(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
1139{
1140	keyspan_port_t	*kp = (keyspan_port_t *)req->bulk_client_private;
1141	keyspan_pipe_t	*bulkin = &kp->kp_datain_pipe;
1142	mblk_t		*data = req->bulk_data;
1143	uint_t		cr = req->bulk_completion_reason;
1144	int		data_len;
1145
1146	ASSERT(mutex_owned(&kp->kp_mutex));
1147
1148	data_len = (data) ? MBLKL(data) : 0;
1149
1150	USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh,
1151	    "keyspan_bulkin_cb_usa49: len=%d"
1152	    " cr=%d flags=%x", data_len, cr, req->bulk_cb_flags);
1153
1154	/* put data on the read queue */
1155	if ((data_len > 0) && (kp->kp_state != KEYSPAN_PORT_CLOSED) &&
1156	    (cr == USB_CR_OK)) {
1157		uchar_t	status = data->b_rptr[0];
1158
1159		if ((data_len = keyspan_bulkin_cb_process(kp, data_len,
1160		    status, data)) > 0) {
1161			keyspan_put_tail(&kp->kp_rx_mp, data);
1162			/*
1163			 * the data will not be freed and
1164			 * will be sent up later.
1165			 */
1166			req->bulk_data = NULL;
1167		}
1168	} else {
1169		/* usb error happened, so don't send up data */
1170		data_len = 0;
1171		USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh,
1172		    "keyspan_bulkin_cb_usa49: port_state=%d"
1173		    " b_rptr[0]=%c", kp->kp_state, data->b_rptr[0]);
1174	}
1175	if (kp->kp_state != KEYSPAN_PORT_OPEN) {
1176		kp->kp_no_more_reads = B_TRUE;
1177	}
1178
1179	return (data_len);
1180}
1181
1182/*
1183 * pipe callbacks
1184 * --------------
1185 *
1186 * bulk in common callback for USA_49WG model
1187 */
1188/*ARGSUSED*/
1189void
1190keyspan_bulkin_cb_usa49wg(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
1191{
1192	keyspan_port_t	*kp = (keyspan_port_t *)req->bulk_client_private,
1193	    *kp_true;
1194	keyspan_state_t *ksp = (keyspan_state_t *)kp->kp_ksp;
1195	mblk_t		*data = req->bulk_data,
1196	    *mp_data;
1197	uint_t		cr = req->bulk_completion_reason,
1198	    port_data_len;
1199	int		data_len, copy_len;
1200	uint8_t		port_num,
1201	    port_cnt = 0,
1202	    port[4],
1203	    receive_flag = 1;
1204	uint16_t	status;
1205	unsigned char	*old_rptr;
1206
1207	data_len = (data) ? MBLKL(data) : 0;
1208
1209	USB_DPRINTF_L2(DPRINT_IN_PIPE, ksp->ks_lh,
1210	    "keyspan_bulkin_cb_usa49wg: len=%d"
1211	    " cr=%d flags=%x", data_len, cr, req->bulk_cb_flags);
1212
1213	/* put data on the read queue */
1214	if ((data_len > 0) && (cr == USB_CR_OK)) {
1215		old_rptr = data->b_rptr;
1216		while (data->b_rptr < data->b_wptr) {
1217			port_num = data->b_rptr[0];
1218			port_data_len = data->b_rptr[1];
1219			status = data->b_rptr[2];
1220			data->b_rptr += 2;
1221
1222			if (port_num > 3) {
1223				USB_DPRINTF_L2(DPRINT_IN_PIPE, ksp->ks_lh,
1224				    "keyspan_bulkin_cb_usa49wg,port num is not"
1225				    " correct: port=%d, len=%d, status=%x",
1226				    port_num, port_data_len, status);
1227
1228				break;
1229			}
1230
1231			kp_true = &ksp->ks_ports[port_num];
1232			port[++port_cnt] = port_num;
1233			mutex_enter(&kp_true->kp_mutex);
1234
1235			if (kp_true->kp_state != KEYSPAN_PORT_OPEN) {
1236				mutex_exit(&kp_true->kp_mutex);
1237
1238				USB_DPRINTF_L2(DPRINT_IN_PIPE, kp_true->kp_lh,
1239				    "keyspan_bulkin_cb_usa49wg, "
1240				    "port isn't opened");
1241				data->b_rptr += port_data_len;
1242				port_cnt--;
1243
1244				continue;
1245			}
1246
1247			USB_DPRINTF_L2(DPRINT_IN_PIPE, kp_true->kp_lh,
1248			    "keyspan_bulkin_cb_usa49wg: status=0x%x, len=%d",
1249			    status, port_data_len);
1250
1251			if ((copy_len = keyspan_bulkin_cb_process(kp_true,
1252			    port_data_len, status, data)) > 0) {
1253
1254				mutex_exit(&kp_true->kp_mutex);
1255				if ((mp_data = allocb(copy_len, BPRI_HI))
1256				    == NULL) {
1257					USB_DPRINTF_L2(DPRINT_IN_PIPE,
1258					    kp_true->kp_lh, "keyspan_bulkin_cb_"
1259					    "usa49wg: allocb failed");
1260
1261					return;
1262				}
1263				mutex_enter(&kp_true->kp_mutex);
1264				DB_TYPE(mp_data) = M_DATA;
1265				bcopy(data->b_rptr, mp_data->b_wptr, copy_len);
1266				mp_data->b_wptr += copy_len;
1267				if (copy_len < port_data_len -1) {
1268					/*
1269					 * data has multi status bytes, b_wptr
1270					 * has changed by
1271					 * keyspan_bulkin_process(), need to
1272					 * be recovered to old one
1273					 */
1274					data->b_rptr += port_data_len;
1275					data->b_wptr = old_rptr + data_len;
1276				} else {
1277					data->b_rptr += copy_len;
1278				}
1279
1280				keyspan_put_tail(&kp_true->kp_rx_mp, mp_data);
1281				mutex_exit(&kp_true->kp_mutex);
1282			} else {
1283				mutex_exit(&kp_true->kp_mutex);
1284
1285				break;
1286			}
1287		} /* End of while loop */
1288
1289		while (port_cnt) {
1290			port_num = port[port_cnt--];
1291			kp_true = &ksp->ks_ports[port_num];
1292			mutex_enter(&kp_true->kp_mutex);
1293
1294			if (kp_true->kp_state != KEYSPAN_PORT_OPEN) {
1295				kp_true->kp_no_more_reads = B_TRUE;
1296			}
1297			if (receive_flag && (!kp_true->kp_no_more_reads)) {
1298				mutex_exit(&kp_true->kp_mutex);
1299				/* kick off another read */
1300				(void) keyspan_receive_data(
1301				    &kp_true->kp_datain_pipe,
1302				    kp_true->kp_read_len, kp_true);
1303
1304				receive_flag = 0;
1305			} else {
1306				mutex_exit(&kp_true->kp_mutex);
1307			}
1308			/* setup rx callback for this port */
1309			kp_true->kp_cb.cb_rx(kp_true->kp_cb.cb_arg);
1310		}
1311	} else {
1312		/* cr != USB_CR_OK, usb error happened */
1313		USB_DPRINTF_L2(DPRINT_IN_PIPE, ksp->ks_lh,
1314		    "keyspan_bulkin_cb_usa49wg: port=%d, len=%d, status=%x",
1315		    data->b_rptr[0], data->b_rptr[1], data->b_rptr[2]);
1316
1317		mutex_enter(&kp->kp_mutex);
1318		if (kp->kp_state != KEYSPAN_PORT_OPEN) {
1319			kp->kp_no_more_reads = B_TRUE;
1320		}
1321		if (!kp->kp_no_more_reads) {
1322			mutex_exit(&kp->kp_mutex);
1323			/* kick off another read */
1324			(void) keyspan_receive_data(&kp->kp_datain_pipe,
1325			    kp->kp_read_len, kp);
1326		} else {
1327			mutex_exit(&kp->kp_mutex);
1328		}
1329	}
1330
1331	freemsg(data);
1332	req->bulk_data = NULL;
1333	usb_free_bulk_req(req);
1334
1335}
1336
1337/*
1338 * pipe callbacks
1339 * --------------
1340 *
1341 * bulk in common callback for USA19HS and USA49WLC
1342 */
1343/*ARGSUSED*/
1344void
1345keyspan_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
1346{
1347	keyspan_port_t	*kp = (keyspan_port_t *)req->bulk_client_private;
1348	int		data_len;
1349	boolean_t	no_more_reads = B_FALSE;
1350
1351	USB_DPRINTF_L4(DPRINT_IN_PIPE, (&kp->kp_datain_pipe)->pipe_lh,
1352	    "keyspan_bulkin_cb");
1353
1354	mutex_enter(&kp->kp_mutex);
1355
1356	/* put data on the read queue */
1357	data_len = keyspan_bulkin_cb_usa49(pipe, req);
1358	no_more_reads = kp->kp_no_more_reads;
1359
1360	mutex_exit(&kp->kp_mutex);
1361
1362	usb_free_bulk_req(req);
1363
1364	/* kick off another read unless indicated otherwise */
1365	if (!no_more_reads) {
1366		(void) keyspan_receive_data(&kp->kp_datain_pipe,
1367		    kp->kp_read_len, kp);
1368	}
1369
1370	/* setup rx callback for this port */
1371	if (data_len > 0)  {
1372		kp->kp_cb.cb_rx(kp->kp_cb.cb_arg);
1373	}
1374}
1375
1376/*
1377 * pipe callbacks
1378 * --------------
1379 *
1380 * bulk in status callback for usa19hs model
1381 */
1382/*ARGSUSED*/
1383void
1384keyspan_status_cb_usa19hs(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
1385{
1386	keyspan_state_t	*ksp = (keyspan_state_t *)req->bulk_client_private;
1387	keyspan_pipe_t	*bulkin = &ksp->ks_statin_pipe;
1388	mblk_t		*data = req->bulk_data;
1389	usb_cr_t	cr = req->bulk_completion_reason;
1390	int		data_len;
1391
1392	data_len = (data) ? MBLKL(data) : 0;
1393
1394	USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh,
1395	    "keyspan_status_cb_usa19hs: len=%d"
1396	    " cr=%d flags=%x", data_len, cr, req->bulk_cb_flags);
1397
1398	/* put data on the read queue */
1399	if ((data_len == 14) && (cr == USB_CR_OK)) {
1400		keyspan_port_t	*kp = &ksp->ks_ports[0];
1401		keyspan_usa19hs_port_status_msg_t *status_msg =
1402		    &(kp->kp_status_msg.usa19hs);
1403
1404		mutex_enter(&kp->kp_mutex);
1405		bcopy(data->b_rptr, status_msg, data_len);
1406
1407		if (status_msg->controlResponse) {
1408			kp->kp_status_flag |= KEYSPAN_PORT_CTRLRESP;
1409		} else {
1410			kp->kp_status_flag &= ~KEYSPAN_PORT_CTRLRESP;
1411		}
1412
1413		if (status_msg->portState & PORTSTATE_ENABLED) {
1414			kp->kp_status_flag |= KEYSPAN_PORT_ENABLE;
1415		} else {
1416			kp->kp_status_flag &= ~KEYSPAN_PORT_ENABLE;
1417		}
1418
1419		if (status_msg->portState & PORTSTATE_TXBREAK) {
1420			kp->kp_status_flag |= KEYSPAN_PORT_TXBREAK;
1421		} else {
1422			kp->kp_status_flag &= ~KEYSPAN_PORT_TXBREAK;
1423		}
1424
1425		if (status_msg->rxBreak) {
1426			kp->kp_status_flag |= KEYSPAN_PORT_RXBREAK;
1427		} else {
1428			kp->kp_status_flag &= ~KEYSPAN_PORT_RXBREAK;
1429		}
1430
1431		if (status_msg->portState & PORTSTATE_LOOPBACK) {
1432			kp->kp_status_flag |= KEYSPAN_PORT_LOOPBACK;
1433		} else {
1434			kp->kp_status_flag &= ~KEYSPAN_PORT_LOOPBACK;
1435		}
1436
1437		/* if msr status changed, then invoke status callback */
1438		if (status_msg->msr & USA_MSR_dCTS ||
1439		    status_msg->msr & USA_MSR_dDSR ||
1440		    status_msg->msr & USA_MSR_dRI ||
1441		    status_msg->msr & USA_MSR_dDCD) {
1442
1443			mutex_exit(&kp->kp_mutex);
1444			kp->kp_cb.cb_status(kp->kp_cb.cb_arg);
1445		} else {
1446			mutex_exit(&kp->kp_mutex);
1447		}
1448	} else {
1449
1450		USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh,
1451		    "keyspan_status_cb_usa19hs: get status failed, cr=%d"
1452		    " data_len=%d", cr, data_len);
1453	}
1454}
1455
1456
1457/*
1458 * pipe callbacks
1459 * --------------
1460 *
1461 * bulk in status callback for usa49 model
1462 */
1463/*ARGSUSED*/
1464void
1465keyspan_status_cb_usa49(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
1466{
1467	keyspan_state_t	*ksp = (keyspan_state_t *)req->bulk_client_private;
1468	keyspan_pipe_t	*bulkin = &ksp->ks_statin_pipe;
1469	mblk_t		*data = req->bulk_data;
1470	uint_t		cr = req->bulk_completion_reason;
1471	int		data_len;
1472
1473	data_len = (data) ? MBLKL(data) : 0;
1474
1475	USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh,
1476	    "keyspan_status_cb_usa49: len=%d"
1477	    " cr=%d flags=%x", data_len, cr, req->bulk_cb_flags);
1478
1479	/* put data on the read queue */
1480	if ((data_len == 11) && (cr == USB_CR_OK)) {
1481		keyspan_usa49_port_status_msg_t status_msg;
1482		keyspan_port_t *cur_kp;
1483		keyspan_usa49_port_status_msg_t *kp_status_msg;
1484		boolean_t need_cb = B_FALSE;
1485
1486		bcopy(data->b_rptr, &status_msg, data_len);
1487		if (status_msg.portNumber >= ksp->ks_dev_spec.port_cnt) {
1488
1489			return;
1490		}
1491		cur_kp = &ksp->ks_ports[status_msg.portNumber];
1492		kp_status_msg = &(cur_kp->kp_status_msg.usa49);
1493
1494		mutex_enter(&cur_kp->kp_mutex);
1495
1496		/* if msr status changed, then need invoke status callback */
1497		if (status_msg.cts !=  kp_status_msg->cts ||
1498		    status_msg.dsr != kp_status_msg->dsr ||
1499		    status_msg.ri != kp_status_msg->ri ||
1500		    status_msg.dcd != kp_status_msg->dcd) {
1501
1502			need_cb = B_TRUE;
1503		}
1504
1505		bcopy(&status_msg, kp_status_msg, data_len);
1506
1507		if (kp_status_msg->controlResponse) {
1508			cur_kp->kp_status_flag |= KEYSPAN_PORT_CTRLRESP;
1509		} else {
1510			cur_kp->kp_status_flag &= ~KEYSPAN_PORT_CTRLRESP;
1511		}
1512
1513		if (!kp_status_msg->rxEnabled) {
1514			cur_kp->kp_status_flag |= KEYSPAN_PORT_RXBREAK;
1515		} else {
1516			cur_kp->kp_status_flag &= ~KEYSPAN_PORT_RXBREAK;
1517		}
1518
1519		mutex_exit(&cur_kp->kp_mutex);
1520
1521		if (need_cb) {
1522
1523			cur_kp->kp_cb.cb_status(cur_kp->kp_cb.cb_arg);
1524		}
1525	} else {
1526
1527		USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh,
1528		    "keyspan_status_cb_usa49: get status failed, cr=%d"
1529		    " data_len=%d", cr, data_len);
1530	}
1531}
1532
1533
1534/*
1535 * pipe callbacks
1536 * --------------
1537 *
1538 * bulk in callback for status receiving
1539 */
1540/*ARGSUSED*/
1541void
1542keyspan_status_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
1543{
1544	keyspan_state_t	*ksp = (keyspan_state_t *)req->bulk_client_private;
1545	usb_cr_t	cr = req->bulk_completion_reason;
1546
1547	USB_DPRINTF_L4(DPRINT_IN_PIPE, (&ksp->ks_statin_pipe)->pipe_lh,
1548	    "keyspan_status_cb");
1549
1550	/* put data on the read queue */
1551	switch (ksp->ks_dev_spec.id_product) {
1552	case KEYSPAN_USA19HS_PID:
1553		keyspan_status_cb_usa19hs(pipe, req);
1554
1555		break;
1556
1557
1558	case KEYSPAN_USA49WLC_PID:
1559		keyspan_status_cb_usa49(pipe, req);
1560
1561		break;
1562
1563	default:
1564		USB_DPRINTF_L2(DPRINT_IN_PIPE,
1565		    (&ksp->ks_statin_pipe)->pipe_lh, "keyspan_status_cb:"
1566		    "the device's product id can't be recognized");
1567
1568		return;
1569	}
1570
1571	usb_free_bulk_req(req);
1572
1573	/* kick off another read to receive status */
1574	if ((cr != USB_CR_FLUSHED) && (cr != USB_CR_DEV_NOT_RESP) &&
1575	    keyspan_dev_is_online(ksp)) {
1576		if (keyspan_receive_status(ksp) != USB_SUCCESS) {
1577			USB_DPRINTF_L2(DPRINT_IN_PIPE,
1578			    (&ksp->ks_statin_pipe)->pipe_lh,
1579			    "keyspan_status_cb:"
1580			    "receive status can't be restarted.");
1581		}
1582	} else {
1583		USB_DPRINTF_L2(DPRINT_IN_PIPE,
1584		    (&ksp->ks_statin_pipe)->pipe_lh, "keyspan_status_cb:"
1585		    "get status failed: cr=%d", cr);
1586	}
1587}
1588
1589/*
1590 * Submit data read request (asynchronous). If this function returns
1591 * USB_SUCCESS, pipe is acquired and request is sent, otherwise req is free.
1592 */
1593int
1594keyspan_receive_data(keyspan_pipe_t *bulkin, int len, void *cb_arg)
1595{
1596	keyspan_state_t	*ksp = bulkin->pipe_ksp;
1597	usb_bulk_req_t	*br;
1598	int		rval = USB_SUCCESS;
1599
1600	USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, "keyspan_receive_data:"
1601	    "len=%d", len);
1602
1603	ASSERT(!mutex_owned(&bulkin->pipe_mutex));
1604
1605	br = usb_alloc_bulk_req(ksp->ks_dip, len, USB_FLAGS_SLEEP);
1606	br->bulk_len = len;
1607
1608	/* No timeout, just wait for data */
1609	br->bulk_timeout = 0;
1610	br->bulk_client_private = cb_arg;
1611	br->bulk_attributes = USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING;
1612
1613	switch (ksp->ks_dev_spec.id_product) {
1614	case KEYSPAN_USA19HS_PID:
1615	case KEYSPAN_USA49WLC_PID:
1616		br->bulk_cb = keyspan_bulkin_cb;
1617		br->bulk_exc_cb = keyspan_bulkin_cb;
1618
1619		break;
1620
1621	case KEYSPAN_USA49WG_PID:
1622		br->bulk_cb = keyspan_bulkin_cb_usa49wg;
1623		br->bulk_exc_cb = keyspan_bulkin_cb_usa49wg;
1624
1625		break;
1626
1627	default:
1628		usb_free_bulk_req(br);
1629
1630		USB_DPRINTF_L2(DPRINT_IN_PIPE,
1631		    (&ksp->ks_statin_pipe)->pipe_lh, "keyspan_receive_data:"
1632		    "the device's product id can't be recognized");
1633
1634		return (USB_FAILURE);
1635	}
1636
1637
1638	rval = usb_pipe_bulk_xfer(bulkin->pipe_handle, br, 0);
1639	if (rval != USB_SUCCESS) {
1640		usb_free_bulk_req(br);
1641	}
1642	USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh,
1643	    "keyspan_receive_data: rval = %d", rval);
1644	return (rval);
1645}
1646
1647/*
1648 * submit device status read request (asynchronous).
1649 */
1650int
1651keyspan_receive_status(keyspan_state_t	*ksp)
1652{
1653	keyspan_pipe_t *bulkin = &ksp->ks_statin_pipe;
1654	usb_bulk_req_t	*br;
1655	int		rval;
1656
1657	USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh,
1658	    "keyspan_receive_status");
1659
1660	ASSERT(!mutex_owned(&bulkin->pipe_mutex));
1661
1662	br = usb_alloc_bulk_req(ksp->ks_dip, 32, USB_FLAGS_SLEEP);
1663	br->bulk_len = KEYSPAN_STATIN_MAX_LEN;
1664
1665	/* No timeout, just wait for data */
1666	br->bulk_timeout = 0;
1667	br->bulk_client_private = (void *)ksp;
1668	br->bulk_attributes = USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING;
1669	br->bulk_cb = keyspan_status_cb;
1670	br->bulk_exc_cb = keyspan_status_cb;
1671
1672	rval = usb_pipe_bulk_xfer(bulkin->pipe_handle, br, 0);
1673	if (rval != USB_SUCCESS) {
1674		usb_free_bulk_req(br);
1675	}
1676	USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh,
1677	    "keyspan_receive_status: rval = %d", rval);
1678	return (rval);
1679}
1680
1681/*
1682 * submit data for transfer (asynchronous)
1683 *
1684 * if data was sent successfully, 'mpp' will be nulled to indicate
1685 * that mblk is consumed by USBA and no longer belongs to the caller.
1686 *
1687 * if this function returns USB_SUCCESS, pipe is acquired and request
1688 * is sent, otherwise pipe is free.
1689 */
1690int
1691keyspan_send_data(keyspan_pipe_t *bulkout, mblk_t **mpp, void *cb_arg)
1692{
1693	keyspan_state_t	*ksp = bulkout->pipe_ksp;
1694	usb_bulk_req_t	*br;
1695	int		rval;
1696
1697	ASSERT(!mutex_owned(&bulkout->pipe_mutex));
1698	USB_DPRINTF_L4(DPRINT_OUT_PIPE, bulkout->pipe_lh,
1699	    "keyspan_send_data");
1700
1701	br = usb_alloc_bulk_req(ksp->ks_dip, 0, USB_FLAGS_SLEEP);
1702	br->bulk_len = MBLKL(*mpp);
1703	br->bulk_data = *mpp;
1704	br->bulk_timeout = KEYSPAN_BULK_TIMEOUT;
1705	br->bulk_client_private = cb_arg;
1706	br->bulk_attributes = USB_ATTRS_AUTOCLEARING;
1707	br->bulk_cb = keyspan_bulkout_cb;
1708	br->bulk_exc_cb = keyspan_bulkout_cb;
1709
1710	USB_DPRINTF_L3(DPRINT_OUT_PIPE, bulkout->pipe_lh, "keyspan_send_data:"
1711	    "bulk_len = %d", br->bulk_len);
1712
1713	rval = usb_pipe_bulk_xfer(bulkout->pipe_handle, br, 0);
1714	if (rval == USB_SUCCESS) {
1715
1716		/* data consumed. The mem will be released in bulkout_cb */
1717		*mpp = NULL;
1718	} else {
1719
1720		/*
1721		 * Don't free it in usb_free_bulk_req because it will
1722		 * be linked in keyspan_put_head
1723		 */
1724		br->bulk_data = NULL;
1725
1726		usb_free_bulk_req(br);
1727	}
1728	USB_DPRINTF_L4(DPRINT_OUT_PIPE, bulkout->pipe_lh,
1729	    "keyspan_send_data: rval = %d", rval);
1730
1731	return (rval);
1732}
1733
1734/*
1735 * submit data for transfer (asynchronous) for USA_49WG Port0 only
1736 *
1737 * if data was sent successfully, 'mpp' will be nulled to indicate
1738 * that mblk is consumed by USBA and no longer belongs to the caller.
1739 *
1740 * if this function returns USB_SUCCESS, pipe is acquired and request
1741 * is sent, otherwise pipe is free.
1742 */
1743int
1744keyspan_send_data_port0(keyspan_pipe_t *introut, mblk_t **mpp, void *cb_arg)
1745{
1746	keyspan_state_t	*ksp = introut->pipe_ksp;
1747	usb_intr_req_t	*br;
1748	int		rval;
1749
1750	ASSERT(!mutex_owned(&introut->pipe_mutex));
1751	USB_DPRINTF_L4(DPRINT_OUT_PIPE, introut->pipe_lh,
1752	    "keyspan_send_data_port0");
1753
1754	br = usb_alloc_intr_req(ksp->ks_dip, 0, USB_FLAGS_SLEEP);
1755	br->intr_len = MBLKL(*mpp);
1756	br->intr_data = *mpp;
1757	br->intr_timeout = KEYSPAN_BULK_TIMEOUT;
1758	br->intr_client_private = cb_arg;
1759	br->intr_cb = keyspan_introut_cb_usa49wg;
1760	br->intr_exc_cb = keyspan_introut_cb_usa49wg;
1761
1762	USB_DPRINTF_L3(DPRINT_OUT_PIPE, introut->pipe_lh,
1763	    "keyspan_send_data_port0: intr_len = %d",
1764	    br->intr_len);
1765
1766	rval = usb_pipe_intr_xfer(introut->pipe_handle, br, 0);
1767	if (rval == USB_SUCCESS) {
1768
1769		/*
1770		 * data consumed. The mem will be released in
1771		 * introut_cb_usa49wg
1772		 */
1773		*mpp = NULL;
1774	} else {
1775		br->intr_data = NULL;
1776
1777		usb_free_intr_req(br);
1778	}
1779	USB_DPRINTF_L4(DPRINT_OUT_PIPE, introut->pipe_lh,
1780	    "keyspan_send_data_port0: rval = %d", rval);
1781
1782	return (rval);
1783}
1784
1785/*
1786 * pipe callbacks
1787 * --------------
1788 *
1789 * bulk in status callback for USA_49WG model
1790 */
1791/*ARGSUSED*/
1792void
1793keyspan_status_cb_usa49wg(usb_pipe_handle_t pipe, usb_intr_req_t *req)
1794{
1795	keyspan_state_t	*ksp = (keyspan_state_t *)req->intr_client_private;
1796	keyspan_pipe_t	*intr = &ksp->ks_statin_pipe;
1797	mblk_t		*data = req->intr_data;
1798	uint_t		cr = req->intr_completion_reason;
1799	int		data_len;
1800
1801	data_len = (data) ? MBLKL(data) : 0;
1802
1803	USB_DPRINTF_L4(DPRINT_IN_PIPE, intr->pipe_lh,
1804	    "keyspan_status_cb_usa49wg: len=%d"
1805	    " cr=%d flags=%x", data_len, cr, req->intr_cb_flags);
1806
1807	/* put data on the read queue */
1808	if ((data_len == 11) && (cr == USB_CR_OK)) {
1809		keyspan_usa49_port_status_msg_t status_msg;
1810		keyspan_port_t *cur_kp;
1811		keyspan_usa49_port_status_msg_t *kp_status_msg;
1812		boolean_t need_cb = B_FALSE;
1813
1814		bcopy(data->b_rptr, &status_msg, data_len);
1815		if (status_msg.portNumber >= ksp->ks_dev_spec.port_cnt) {
1816
1817			return;
1818		}
1819		cur_kp = &ksp->ks_ports[status_msg.portNumber];
1820		kp_status_msg = &(cur_kp->kp_status_msg.usa49);
1821
1822		mutex_enter(&cur_kp->kp_mutex);
1823
1824		/* if msr status changed, then need invoke status callback */
1825		if (status_msg.cts !=  kp_status_msg->cts ||
1826		    status_msg.dsr != kp_status_msg->dsr ||
1827		    status_msg.ri != kp_status_msg->ri ||
1828		    status_msg.dcd != kp_status_msg->dcd) {
1829
1830			need_cb = B_TRUE;
1831		}
1832
1833		bcopy(&status_msg, kp_status_msg, data_len);
1834
1835		if (kp_status_msg->controlResponse) {
1836			cur_kp->kp_status_flag |= KEYSPAN_PORT_CTRLRESP;
1837		} else {
1838			cur_kp->kp_status_flag &= ~KEYSPAN_PORT_CTRLRESP;
1839		}
1840
1841		if (!kp_status_msg->rxEnabled) {
1842			cur_kp->kp_status_flag |= KEYSPAN_PORT_RXBREAK;
1843		} else {
1844			cur_kp->kp_status_flag &= ~KEYSPAN_PORT_RXBREAK;
1845		}
1846
1847		mutex_exit(&cur_kp->kp_mutex);
1848
1849		if (need_cb) {
1850
1851			cur_kp->kp_cb.cb_status(cur_kp->kp_cb.cb_arg);
1852		}
1853	} else {
1854
1855		USB_DPRINTF_L2(DPRINT_IN_PIPE, intr->pipe_lh,
1856		    "keyspan_status_cb_usa49wg: get status failed, cr=%d"
1857		    " data_len=%d", cr, data_len);
1858	}
1859}
1860
1861/*
1862 * pipe callbacks
1863 * --------------
1864 *
1865 * intr in callback for status receiving for USA_49WG model only
1866 */
1867/*ARGSUSED*/
1868void
1869keyspan_intr_cb_usa49wg(usb_pipe_handle_t pipe, usb_intr_req_t *req)
1870{
1871	keyspan_state_t	*ksp = (keyspan_state_t *)req->intr_client_private;
1872	usb_cr_t	cr = req->intr_completion_reason;
1873
1874	USB_DPRINTF_L4(DPRINT_IN_PIPE, (&ksp->ks_statin_pipe)->pipe_lh,
1875	    "keyspan_intr_cb_usa49wg: cr=%d", cr);
1876
1877	/* put data on the read queue */
1878	(void) keyspan_status_cb_usa49wg(pipe, req);
1879
1880	usb_free_intr_req(req);
1881}
1882
1883/*
1884 * pipe callbacks
1885 * --------------
1886 *
1887 * intr in exception callback for status receiving for USA_49WG model only
1888 */
1889/*ARGSUSED*/
1890void
1891keyspan_intr_ex_cb_usa49wg(usb_pipe_handle_t pipe, usb_intr_req_t *req)
1892{
1893	keyspan_state_t	*ksp = (keyspan_state_t *)req->intr_client_private;
1894	usb_cr_t	cr = req->intr_completion_reason;
1895
1896	USB_DPRINTF_L4(DPRINT_IN_PIPE, (&ksp->ks_statin_pipe)->pipe_lh,
1897	    "keyspan_intr_ex_cb_usa49wg: cr=%d", cr);
1898
1899	usb_free_intr_req(req);
1900
1901	if ((cr != USB_CR_PIPE_CLOSING) && (cr != USB_CR_STOPPED_POLLING) &&
1902	    (cr != USB_CR_FLUSHED) && (cr != USB_CR_DEV_NOT_RESP) &&
1903	    (cr != USB_CR_PIPE_RESET) && keyspan_dev_is_online(ksp)) {
1904		keyspan_pipe_start_polling(&ksp->ks_statin_pipe);
1905	} else {
1906		USB_DPRINTF_L2(DPRINT_IN_PIPE,
1907		    (&ksp->ks_statin_pipe)->pipe_lh,
1908		    "keyspan_intr_ex_cb_usa49wg:"
1909		    "get status failed: cr=%d", cr);
1910	}
1911}
1912
1913/*
1914 * start polling on the interrupt pipe for USA_49WG model only
1915 */
1916void
1917keyspan_pipe_start_polling(keyspan_pipe_t *intr)
1918{
1919	usb_intr_req_t	*br;
1920	keyspan_state_t	*ksp = intr->pipe_ksp;
1921	int		rval;
1922
1923	USB_DPRINTF_L4(DPRINT_IN_PIPE, ksp->ks_lh,
1924	    "keyspan_pipe_start_polling");
1925
1926	br = usb_alloc_intr_req(ksp->ks_dip, 0, USB_FLAGS_SLEEP);
1927
1928	/*
1929	 * If it is in interrupt context, usb_alloc_intr_req will return NULL if
1930	 * called with SLEEP flag.
1931	 */
1932	if (!br) {
1933		USB_DPRINTF_L2(DPRINT_IN_PIPE, ksp->ks_lh,
1934		    "keyspan_pipe_start_polling: alloc req failed.");
1935
1936		return;
1937	}
1938	br->intr_attributes = USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING;
1939	br->intr_len = intr->pipe_ep_descr.wMaxPacketSize;
1940	br->intr_client_private = (void *)ksp;
1941
1942	br->intr_cb = keyspan_intr_cb_usa49wg;
1943	br->intr_exc_cb = keyspan_intr_ex_cb_usa49wg;
1944
1945
1946	rval = usb_pipe_intr_xfer(intr->pipe_handle, br, USB_FLAGS_SLEEP);
1947
1948	mutex_enter(&intr->pipe_mutex);
1949	if (rval != USB_SUCCESS) {
1950		usb_free_intr_req(br);
1951		intr->pipe_state = KEYSPAN_PIPE_CLOSED;
1952
1953		USB_DPRINTF_L3(DPRINT_IN_PIPE, ksp->ks_lh,
1954		    "keyspan_pipe_start_polling: failed (%d)", rval);
1955	} else {
1956		intr->pipe_state = KEYSPAN_PIPE_OPEN;
1957	}
1958
1959	mutex_exit(&intr->pipe_mutex);
1960}
1961