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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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