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  */
48 static void
keyspan_init_one_pipe(keyspan_state_t * ksp,keyspan_port_t * kp,keyspan_pipe_t * pipe)49 keyspan_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 
77 static void
keyspan_fini_one_pipe(keyspan_pipe_t * pipe)78 keyspan_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  */
94 int
keyspan_init_pipes(keyspan_state_t * ksp)95 keyspan_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  */
285 int
keyspan_init_pipes_usa49wg(keyspan_state_t * ksp)286 keyspan_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 
403 void
keyspan_fini_pipes(keyspan_state_t * ksp)404 keyspan_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 
437 static int
keyspan_open_one_pipe(keyspan_state_t * ksp,keyspan_pipe_t * pipe)438 keyspan_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  */
467 static int
keyspan_open_pipe_datain_usa49wg(keyspan_state_t * ksp,keyspan_pipe_t * pipe)468 keyspan_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  */
522 static void
keyspan_close_one_pipe(keyspan_pipe_t * pipe)523 keyspan_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  */
542 static void
keyspan_close_pipe_datain_usa49wg(keyspan_pipe_t * pipe)543 keyspan_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  */
573 int
keyspan_open_dev_pipes_usa49(keyspan_state_t * ksp)574 keyspan_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  */
623 int
keyspan_open_dev_pipes_usa49wg(keyspan_state_t * ksp)624 keyspan_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  */
647 int
keyspan_open_dev_pipes(keyspan_state_t * ksp)648 keyspan_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  */
677 int
keyspan_reopen_pipes(keyspan_state_t * ksp)678 keyspan_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 
710 void
keyspan_close_port_pipes(keyspan_port_t * kp)711 keyspan_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  */
738 void
keyspan_close_open_pipes(keyspan_state_t * ksp)739 keyspan_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  */
807 void
keyspan_close_dev_pipes(keyspan_state_t * ksp)808 keyspan_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  */
842 int
keyspan_open_port_pipes(keyspan_port_t * kp)843 keyspan_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 
880 fail:
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 
888 void
keyspan_close_pipes(keyspan_state_t * ksp)889 keyspan_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*/
901 void
keyspan_bulkout_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)902 keyspan_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*/
962 void
keyspan_introut_cb_usa49wg(usb_pipe_handle_t pipe,usb_intr_req_t * req)963 keyspan_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 */
1008 void
keyspan_parse_status(uchar_t * status,uchar_t * err)1009 keyspan_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 */
1025 int
keyspan_bulkin_cb_process(keyspan_port_t * kp,uint8_t data_len,uchar_t status,mblk_t * data)1026 keyspan_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*/
1137 int
keyspan_bulkin_cb_usa49(usb_pipe_handle_t pipe,usb_bulk_req_t * req)1138 keyspan_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*/
1189 void
keyspan_bulkin_cb_usa49wg(usb_pipe_handle_t pipe,usb_bulk_req_t * req)1190 keyspan_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*/
1344 void
keyspan_bulkin_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)1345 keyspan_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*/
1383 void
keyspan_status_cb_usa19hs(usb_pipe_handle_t pipe,usb_bulk_req_t * req)1384 keyspan_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*/
1464 void
keyspan_status_cb_usa49(usb_pipe_handle_t pipe,usb_bulk_req_t * req)1465 keyspan_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*/
1541 void
keyspan_status_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)1542 keyspan_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  */
1593 int
keyspan_receive_data(keyspan_pipe_t * bulkin,int len,void * cb_arg)1594 keyspan_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  */
1650 int
keyspan_receive_status(keyspan_state_t * ksp)1651 keyspan_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  */
1690 int
keyspan_send_data(keyspan_pipe_t * bulkout,mblk_t ** mpp,void * cb_arg)1691 keyspan_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  */
1743 int
keyspan_send_data_port0(keyspan_pipe_t * introut,mblk_t ** mpp,void * cb_arg)1744 keyspan_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*/
1792 void
keyspan_status_cb_usa49wg(usb_pipe_handle_t pipe,usb_intr_req_t * req)1793 keyspan_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*/
1868 void
keyspan_intr_cb_usa49wg(usb_pipe_handle_t pipe,usb_intr_req_t * req)1869 keyspan_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*/
1890 void
keyspan_intr_ex_cb_usa49wg(usb_pipe_handle_t pipe,usb_intr_req_t * req)1891 keyspan_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  */
1916 void
keyspan_pipe_start_polling(keyspan_pipe_t * intr)1917 keyspan_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