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