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