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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * 31 * keyspanport pipe routines (mostly device-neutral) 32 * 33 */ 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/conf.h> 37 #include <sys/stream.h> 38 #include <sys/strsun.h> 39 #include <sys/termio.h> 40 #include <sys/ddi.h> 41 #include <sys/sunddi.h> 42 43 #include <sys/usb/usba.h> 44 #include <sys/usb/clients/usbser/usbser_keyspan/keyspan_var.h> 45 #include <sys/usb/clients/usbser/usbser_keyspan/keyspan_pipe.h> 46 47 /* 48 * initialize pipe structure with the given parameters 49 */ 50 static void 51 keyspan_init_one_pipe(keyspan_state_t *ksp, keyspan_port_t *kp, 52 keyspan_pipe_t *pipe) 53 { 54 usb_pipe_policy_t *policy; 55 56 USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_init_one_pipe: " 57 "pipe = %p, pipe_stat %x", (void *)pipe, pipe->pipe_state); 58 59 /* init sync primitives */ 60 mutex_init(&pipe->pipe_mutex, NULL, MUTEX_DRIVER, (void *)NULL); 61 62 /* init pipe policy */ 63 policy = &pipe->pipe_policy; 64 policy->pp_max_async_reqs = 2; 65 66 pipe->pipe_ksp = ksp; 67 if (kp == NULL) { 68 /* globle pipes should have device log handle */ 69 pipe->pipe_lh = ksp->ks_lh; 70 } else { 71 /* port pipes should have port log handle */ 72 pipe->pipe_lh = kp->kp_lh; 73 } 74 75 pipe->pipe_state = KEYSPAN_PIPE_CLOSED; 76 } 77 78 79 static void 80 keyspan_fini_one_pipe(keyspan_pipe_t *pipe) 81 { 82 USB_DPRINTF_L4(DPRINT_OPEN, pipe->pipe_ksp->ks_lh, 83 "keyspan_fini_one_pipe: pipe_stat %x", pipe->pipe_state); 84 85 if (pipe->pipe_state != KEYSPAN_PIPE_NOT_INIT) { 86 mutex_destroy(&pipe->pipe_mutex); 87 pipe->pipe_state = KEYSPAN_PIPE_NOT_INIT; 88 } 89 } 90 91 /* 92 * Lookup the endpoints defined in the spec; 93 * Allocate resources, initialize pipe structures. 94 * All are bulk pipes, including data in/out, cmd/status pipes. 95 */ 96 int 97 keyspan_init_pipes(keyspan_state_t *ksp) 98 { 99 usb_client_dev_data_t *dev_data = ksp->ks_dev_data; 100 int ifc, alt, i, j, k = 0; 101 uint8_t port_cnt = ksp->ks_dev_spec.port_cnt; 102 uint8_t ep_addr, ep_cnt; 103 usb_ep_data_t *dataout[KEYSPAN_MAX_PORT_NUM], 104 *datain[KEYSPAN_MAX_PORT_NUM], 105 *status = NULL, *ctrl = NULL, *tmp_ep; 106 usb_alt_if_data_t *alt_data; 107 usb_if_data_t *if_data; 108 109 110 ifc = dev_data->dev_curr_if; 111 alt = 0; 112 if_data = &dev_data->dev_curr_cfg->cfg_if[ifc]; 113 alt_data = &if_data->if_alt[alt]; 114 115 /* 116 * The actual EP number (indicated by bNumEndpoints) is more than 117 * those defined in spec. We have to match those we need according 118 * to EP addresses. And we'll lookup In EPs and Out EPs separately. 119 */ 120 ep_cnt = (alt_data->altif_descr.bNumEndpoints + 1) / 2; 121 122 /* 123 * get DIR_IN EP descriptors, and then match with EP addresses. 124 * Different keyspan devices may has different EP addresses. 125 */ 126 for (i = 0; i < ep_cnt; i++) { 127 tmp_ep = usb_lookup_ep_data(ksp->ks_dip, dev_data, ifc, alt, i, 128 USB_EP_ATTR_BULK, USB_EP_DIR_IN); 129 if (tmp_ep == NULL) { 130 USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh, 131 "keyspan_init_pipes: can't find bulk in ep, i=%d," 132 "ep_cnt=%d", i, ep_cnt); 133 134 continue; 135 } 136 ep_addr = tmp_ep->ep_descr.bEndpointAddress; 137 138 USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh, "keyspan_init_pipes: " 139 "ep_addr =%x, stat_ep_addr=%x, i=%d", ep_addr, 140 ksp->ks_dev_spec.stat_ep_addr, i); 141 142 /* match the status EP */ 143 if (ep_addr == ksp->ks_dev_spec.stat_ep_addr) { 144 status = tmp_ep; 145 146 continue; 147 } 148 149 /* match the EPs of the ports */ 150 for (j = 0; j < port_cnt; j++) { 151 USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh, 152 "keyspan_init_pipes: try to match bulk in data ep," 153 " j=%d", j); 154 if (ep_addr == ksp->ks_dev_spec.datain_ep_addr[j]) { 155 datain[j] = tmp_ep; 156 k++; 157 USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh, 158 "keyspan_init_pipes: matched a bulk in" 159 " data ep"); 160 161 break; 162 } 163 } 164 165 /* if have matched all the necessary endpoints, break out */ 166 if (k >= port_cnt && status != NULL) { 167 168 break; 169 } 170 171 USB_DPRINTF_L4(DPRINT_ATTACH, ksp->ks_lh, "keyspan_init_pipes: " 172 "try to match bulk in data ep, j=%d", j); 173 174 if (j == port_cnt) { 175 /* this ep can't be matched by any addr */ 176 USB_DPRINTF_L4(DPRINT_ATTACH, ksp->ks_lh, 177 "keyspan_init_pipes: can't match bulk in ep," 178 " addr =%x,", ep_addr); 179 } 180 } 181 182 if (k != port_cnt || status == NULL) { 183 184 /* Some of the necessary IN endpoints are not matched */ 185 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 186 "keyspan_init_pipes: matched %d data in endpoints," 187 " not enough", k); 188 189 return (USB_FAILURE); 190 } 191 192 k = 0; 193 194 /* 195 * get DIR_OUT EP descriptors, and then match with ep addrs. 196 * different keyspan devices may has different ep addresses. 197 */ 198 for (i = 0; i < ep_cnt; i++) { 199 tmp_ep = usb_lookup_ep_data(ksp->ks_dip, dev_data, ifc, alt, i, 200 USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 201 if (tmp_ep == NULL) { 202 USB_DPRINTF_L3(DPRINT_ATTACH, ksp->ks_lh, 203 "keyspan_init_pipes: can't find bulk out ep, i=%d," 204 "ep_cnt=%d", i, ep_cnt); 205 206 continue; 207 } 208 ep_addr = tmp_ep->ep_descr.bEndpointAddress; 209 210 /* match the status ep */ 211 if (ep_addr == ksp->ks_dev_spec.ctrl_ep_addr) { 212 ctrl = tmp_ep; 213 214 continue; 215 } 216 217 /* match the ep of the ports */ 218 for (j = 0; j < port_cnt; j++) { 219 if (ep_addr == ksp->ks_dev_spec.dataout_ep_addr[j]) { 220 dataout[j] = tmp_ep; 221 k++; 222 223 break; 224 } 225 } 226 /* if have matched all the necessary endpoints, break out */ 227 if (k >= port_cnt && ctrl != NULL) { 228 229 break; 230 } 231 232 if (j == port_cnt) { 233 234 /* this ep can't be matched by any addr */ 235 USB_DPRINTF_L4(DPRINT_ATTACH, ksp->ks_lh, 236 "keyspan_init_pipes: can't match bulk out ep," 237 " ep_addr =%x", ep_addr); 238 239 } 240 } 241 242 if (k != port_cnt || ctrl == NULL) { 243 /* Not all the necessary OUT endpoints are matched */ 244 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, 245 "keyspan_init_pipes: matched %d data in endpoints," 246 " not enough", k); 247 248 return (USB_FAILURE); 249 } 250 251 mutex_enter(&ksp->ks_mutex); 252 253 /* 254 * Device globle pipes: a bulk in pipe for status and a bulk out 255 * pipe for controle cmd. 256 */ 257 ksp->ks_statin_pipe.pipe_ep_descr = status->ep_descr; 258 keyspan_init_one_pipe(ksp, NULL, &ksp->ks_statin_pipe); 259 260 ksp->ks_ctrlout_pipe.pipe_ep_descr = ctrl->ep_descr; 261 keyspan_init_one_pipe(ksp, NULL, &ksp->ks_ctrlout_pipe); 262 263 /* for data in/out pipes of each port */ 264 for (i = 0; i < port_cnt; i++) { 265 266 ksp->ks_ports[i].kp_datain_pipe.pipe_ep_descr = 267 datain[i]->ep_descr; 268 keyspan_init_one_pipe(ksp, &ksp->ks_ports[i], 269 &ksp->ks_ports[i].kp_datain_pipe); 270 271 ksp->ks_ports[i].kp_dataout_pipe.pipe_ep_descr = 272 dataout[i]->ep_descr; 273 keyspan_init_one_pipe(ksp, &ksp->ks_ports[i], 274 &ksp->ks_ports[i].kp_dataout_pipe); 275 } 276 277 mutex_exit(&ksp->ks_mutex); 278 279 return (USB_SUCCESS); 280 } 281 282 void 283 keyspan_fini_pipes(keyspan_state_t *ksp) 284 { 285 keyspan_port_t *kp; 286 int i; 287 288 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) { 289 kp = &ksp->ks_ports[i]; 290 keyspan_fini_one_pipe(&kp->kp_datain_pipe); 291 keyspan_fini_one_pipe(&kp->kp_dataout_pipe); 292 } 293 294 /* fini global pipes */ 295 keyspan_fini_one_pipe(&ksp->ks_statin_pipe); 296 keyspan_fini_one_pipe(&ksp->ks_ctrlout_pipe); 297 } 298 299 300 static int 301 keyspan_open_one_pipe(keyspan_state_t *ksp, keyspan_pipe_t *pipe) 302 { 303 int rval; 304 305 /* don't open for the second time */ 306 mutex_enter(&pipe->pipe_mutex); 307 ASSERT(pipe->pipe_state != KEYSPAN_PIPE_NOT_INIT); 308 if (pipe->pipe_state != KEYSPAN_PIPE_CLOSED) { 309 mutex_exit(&pipe->pipe_mutex); 310 311 return (USB_SUCCESS); 312 } 313 mutex_exit(&pipe->pipe_mutex); 314 315 rval = usb_pipe_open(ksp->ks_dip, &pipe->pipe_ep_descr, 316 &pipe->pipe_policy, USB_FLAGS_SLEEP, &pipe->pipe_handle); 317 318 if (rval == USB_SUCCESS) { 319 mutex_enter(&pipe->pipe_mutex); 320 pipe->pipe_state = KEYSPAN_PIPE_OPEN; 321 mutex_exit(&pipe->pipe_mutex); 322 } 323 324 return (rval); 325 } 326 327 328 /* 329 * close one pipe if open 330 */ 331 static void 332 keyspan_close_one_pipe(keyspan_pipe_t *pipe) 333 { 334 /* 335 * pipe may already be closed, e.g. if device has been physically 336 * disconnected and the driver immediately detached 337 */ 338 if (pipe->pipe_handle != NULL) { 339 usb_pipe_close(pipe->pipe_ksp->ks_dip, pipe->pipe_handle, 340 USB_FLAGS_SLEEP, NULL, NULL); 341 mutex_enter(&pipe->pipe_mutex); 342 pipe->pipe_handle = NULL; 343 pipe->pipe_state = KEYSPAN_PIPE_CLOSED; 344 mutex_exit(&pipe->pipe_mutex); 345 } 346 } 347 348 /* 349 * Open global pipes, a status pipe and a control pipe 350 */ 351 int 352 keyspan_open_dev_pipes(keyspan_state_t *ksp) 353 { 354 int rval; 355 356 USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_open_dev_pipes"); 357 358 rval = keyspan_open_one_pipe(ksp, &ksp->ks_ctrlout_pipe); 359 if (rval != USB_SUCCESS) { 360 USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh, 361 "keyspan_open_dev_pipes: open ctrl pipe failed %d", rval); 362 363 return (rval); 364 } 365 366 rval = keyspan_open_one_pipe(ksp, &ksp->ks_statin_pipe); 367 if (rval != USB_SUCCESS) { 368 USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh, 369 "keyspan_open_dev_pipes: open status pipe failed %d", rval); 370 371 /* close the first opened pipe here */ 372 keyspan_close_one_pipe(&ksp->ks_ctrlout_pipe); 373 374 return (rval); 375 } 376 377 /* start receive device status */ 378 rval = keyspan_receive_status(ksp); 379 if (rval != USB_SUCCESS) { 380 USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh, 381 "keyspan_open_dev_pipes: receive device status failed %d", 382 rval); 383 384 /* close opened pipes here */ 385 keyspan_close_one_pipe(&ksp->ks_statin_pipe); 386 keyspan_close_one_pipe(&ksp->ks_ctrlout_pipe); 387 388 return (rval); 389 } 390 391 return (rval); 392 } 393 394 395 /* 396 * Reopen all pipes if the port had them open 397 */ 398 int 399 keyspan_reopen_pipes(keyspan_state_t *ksp) 400 { 401 keyspan_port_t *kp; 402 int i; 403 404 USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_reopen_pipes"); 405 406 if (keyspan_open_dev_pipes(ksp) != USB_SUCCESS) { 407 408 return (USB_FAILURE); 409 } 410 411 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) { 412 kp = &ksp->ks_ports[i]; 413 mutex_enter(&kp->kp_mutex); 414 if (kp->kp_state == KEYSPAN_PORT_OPEN) { 415 USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, 416 "keyspan_reopen_pipes() reopen pipe #%d", i); 417 mutex_exit(&kp->kp_mutex); 418 if (keyspan_open_port_pipes(kp) != USB_SUCCESS) { 419 420 return (USB_FAILURE); 421 } 422 mutex_enter(&kp->kp_mutex); 423 kp->kp_no_more_reads = B_FALSE; 424 } 425 mutex_exit(&kp->kp_mutex); 426 } 427 428 return (USB_SUCCESS); 429 } 430 431 void 432 keyspan_close_port_pipes(keyspan_port_t *kp) 433 { 434 USB_DPRINTF_L4(DPRINT_CLOSE, kp->kp_lh, "keyspan_close_port_pipes"); 435 436 keyspan_close_one_pipe(&kp->kp_dataout_pipe); 437 keyspan_close_one_pipe(&kp->kp_datain_pipe); 438 } 439 440 /* 441 * Close IN and OUT bulk pipes of all ports 442 */ 443 void 444 keyspan_close_open_pipes(keyspan_state_t *ksp) 445 { 446 keyspan_port_t *kp; 447 int i; 448 449 USB_DPRINTF_L4(DPRINT_CLOSE, ksp->ks_lh, "keyspan_close_open_pipes"); 450 451 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) { 452 kp = &ksp->ks_ports[i]; 453 mutex_enter(&kp->kp_mutex); 454 if (kp->kp_state == KEYSPAN_PORT_OPEN) { 455 kp->kp_no_more_reads = B_TRUE; 456 mutex_exit(&kp->kp_mutex); 457 usb_pipe_reset(ksp->ks_dip, 458 kp->kp_datain_pipe.pipe_handle, USB_FLAGS_SLEEP, 459 NULL, NULL); 460 keyspan_close_port_pipes(kp); 461 } else { 462 mutex_exit(&kp->kp_mutex); 463 } 464 } 465 } 466 467 468 /* 469 * Close global pipes 470 */ 471 void 472 keyspan_close_dev_pipes(keyspan_state_t *ksp) 473 { 474 USB_DPRINTF_L4(DPRINT_CLOSE, ksp->ks_lh, "keyspan_close_dev_pipes"); 475 476 keyspan_close_one_pipe(&ksp->ks_statin_pipe); 477 keyspan_close_one_pipe(&ksp->ks_ctrlout_pipe); 478 } 479 480 481 /* 482 * Open bulk data IN and data OUT pipes for one port. 483 * The status and control pipes are opened in attach because they are global. 484 */ 485 int 486 keyspan_open_port_pipes(keyspan_port_t *kp) 487 { 488 keyspan_state_t *ksp = kp->kp_ksp; 489 int rval; 490 491 USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh, "keyspan_open_port_pipes"); 492 493 rval = keyspan_open_one_pipe(ksp, &kp->kp_datain_pipe); 494 if (rval != USB_SUCCESS) { 495 496 goto fail; 497 } 498 499 rval = keyspan_open_one_pipe(ksp, &kp->kp_dataout_pipe); 500 if (rval != USB_SUCCESS) { 501 502 goto fail; 503 } 504 505 return (rval); 506 507 fail: 508 USB_DPRINTF_L2(DPRINT_OPEN, kp->kp_lh, 509 "keyspan_open_port_pipes: failed %d", rval); 510 keyspan_close_port_pipes(kp); 511 512 return (rval); 513 } 514 515 void 516 keyspan_close_pipes(keyspan_state_t *ksp) 517 { 518 USB_DPRINTF_L4(DPRINT_OPEN, ksp->ks_lh, "keyspan_close_pipes"); 519 520 /* close all ports' pipes first, and then device ctrl/status pipes. */ 521 keyspan_close_open_pipes(ksp); 522 keyspan_close_dev_pipes(ksp); 523 524 } 525 526 527 /* 528 * bulk out common callback 529 */ 530 /*ARGSUSED*/ 531 void 532 keyspan_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 533 { 534 keyspan_port_t *kp = (keyspan_port_t *)req->bulk_client_private; 535 keyspan_pipe_t *bulkout = &kp->kp_dataout_pipe; 536 mblk_t *data = req->bulk_data; 537 int data_len; 538 539 data_len = (data) ? MBLKL(data) : 0; 540 541 USB_DPRINTF_L4(DPRINT_OUT_PIPE, bulkout->pipe_lh, 542 "keyspan_bulkout_cb: len=%d cr=%d cb_flags=%x", 543 data_len, req->bulk_completion_reason, req->bulk_cb_flags); 544 545 if (req->bulk_completion_reason && (data_len > 0)) { 546 547 /* 548 * Data wasn't transfered successfully. 549 * Put data back on the queue. 550 */ 551 keyspan_put_head(&kp->kp_tx_mp, data, kp); 552 553 /* don't release mem in usb_free_bulk_req */ 554 req->bulk_data = NULL; 555 } 556 557 usb_free_bulk_req(req); 558 559 /* if more data available, kick off another transmit */ 560 mutex_enter(&kp->kp_mutex); 561 if (kp->kp_tx_mp == NULL) { 562 563 /* no more data, notify waiters */ 564 cv_broadcast(&kp->kp_tx_cv); 565 mutex_exit(&kp->kp_mutex); 566 567 /* tx callback for this port */ 568 kp->kp_cb.cb_tx(kp->kp_cb.cb_arg); 569 } else { 570 keyspan_tx_start(kp, NULL); 571 mutex_exit(&kp->kp_mutex); 572 } 573 } 574 575 /* 576 * pipe callbacks 577 * -------------- 578 * 579 * bulk in common callback for usa19hs model 580 */ 581 /*ARGSUSED*/ 582 int 583 keyspan_bulkin_cb_usa19hs(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 584 { 585 keyspan_port_t *kp = (keyspan_port_t *)req->bulk_client_private; 586 keyspan_pipe_t *bulkin = &kp->kp_datain_pipe; 587 mblk_t *data = req->bulk_data; 588 uint_t cr = req->bulk_completion_reason; 589 int data_len; 590 591 ASSERT(mutex_owned(&kp->kp_mutex)); 592 593 data_len = (data) ? MBLKL(data) : 0; 594 595 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 596 "keyspan_bulkin_cb_usa19hs: len=%d" 597 " cr=%d flags=%x baud=%x", 598 data_len, cr, req->bulk_cb_flags, kp->kp_baud); 599 600 /* put data on the read queue */ 601 if ((data_len > 0) && (kp->kp_state != KEYSPAN_PORT_CLOSED) && 602 (cr == USB_CR_OK)) { 603 604 /* 605 * According to Keyspan spec, if 0x80 bit set, the data 606 * buf contains alternate status and data bytes; 607 * if 0x80 bit is clear, then there are no status bytes, 608 * so we put tail to send up data. 609 */ 610 if ((data->b_rptr[0] & 0x80) == 0) { 611 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 612 "keyspan_bulkin_cb_usa19hs: len=%d", 613 data_len); 614 615 data->b_rptr++; 616 data_len--; 617 if (data_len > 0) { 618 keyspan_put_tail(&kp->kp_rx_mp, data); 619 620 /* 621 * the data will not be freed and 622 * will be sent up later. 623 */ 624 req->bulk_data = NULL; 625 } 626 } else { /* there might be some errs in the data */ 627 628 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 629 "keyspan_bulkin_cb_usa19hs:" 630 " err in the data, len=%d", 631 data_len); 632 633 if (data_len > 1) { 634 int i = 0; 635 int j = 1; 636 637 /* get rid of status bytes. */ 638 for (j = 1; j < data_len; j += 2) { 639 data->b_rptr[i] = data->b_rptr[j]; 640 i++; 641 } 642 data->b_wptr = data->b_rptr + i; 643 keyspan_put_tail(&kp->kp_rx_mp, data); 644 645 /* 646 * The data will not be freed and 647 * will be sent up later. 648 */ 649 req->bulk_data = NULL; 650 } else { 651 /* 652 * When zero len returned, no data will 653 * be sent up and the data buf will be 654 * just freed. 655 */ 656 data_len = 0; 657 } 658 } 659 660 } else { 661 662 /* usb error happened, so don't send up data */ 663 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 664 "keyspan_bulkin_cb_usa19hs: error happened, len=%d, " 665 "cr=0x%x, cb_flags=0x%x", data_len, cr, req->bulk_cb_flags); 666 667 data_len = 0; 668 if (kp->kp_state != KEYSPAN_PORT_OPEN) { 669 kp->kp_no_more_reads = B_TRUE; 670 } 671 } 672 673 return (data_len); 674 } 675 676 #ifdef KEYSPAN_USA49WLC 677 /* 678 * pipe callbacks 679 * -------------- 680 * 681 * bulk in common callback for usa49 model 682 */ 683 /*ARGSUSED*/ 684 int 685 keyspan_bulkin_cb_usa49(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 686 { 687 keyspan_port_t *kp = (keyspan_port_t *)req->bulk_client_private; 688 keyspan_pipe_t *bulkin = &kp->kp_datain_pipe; 689 mblk_t *data = req->bulk_data; 690 uint_t cr = req->bulk_completion_reason; 691 int data_len; 692 693 ASSERT(mutex_owned(&kp->kp_mutex)); 694 695 data_len = (data) ? MBLKL(data) : 0; 696 697 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 698 "keyspan_bulkin_cb_usa49: len=%d" 699 " cr=%d flags=%x", data_len, cr, req->bulk_cb_flags); 700 701 /* put data on the read queue */ 702 if ((data_len > 0) && (kp->kp_state != KEYSPAN_PORT_CLOSED) && 703 (cr == USB_CR_OK)) { 704 705 /* 706 * According to Keyspan spec, if 0x80 bit set, the data 707 * buf contains alternate status and data bytes; 708 * if 0x80 bit is clear, then there are no status bytes, 709 * so we put tail to send up data. 710 */ 711 if ((data->b_rptr[0] & 0x80) == 0) { 712 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 713 "keyspan_bulkin_cb_usa49: len=%d" 714 "cr=%d", data_len, cr); 715 716 data->b_rptr++; 717 data_len--; 718 if (data_len > 0) { 719 keyspan_put_tail(&kp->kp_rx_mp, data); 720 721 /* 722 * The data will not be freed and 723 * will be sent up later. 724 */ 725 req->bulk_data = NULL; 726 } 727 } else { 728 if (data_len > 1) { 729 int i = 0; 730 int j = 1; 731 732 /* get rid of the status bytes in the data. */ 733 for (j = 1; j < data_len; j += 2) { 734 data->b_rptr[i] = data->b_rptr[j]; 735 i++; 736 } 737 data->b_wptr = data->b_rptr + i; 738 keyspan_put_tail(&kp->kp_rx_mp, data); 739 740 /* 741 * The data will not be freed and 742 * will be sent up later. 743 */ 744 req->bulk_data = NULL; 745 } else { 746 /* 747 * When zero len returned, no data will be sent 748 * up and the data buf will be just freed. 749 */ 750 data_len = 0; 751 } 752 } 753 } else { 754 755 /* usb error happened, so don't send up data */ 756 data_len = 0; 757 USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh, 758 "keyspan_bulkin_cb_usa49: port_state=%d" 759 " b_rptr[0]=%c", kp->kp_state, data->b_rptr[0]); 760 761 if (kp->kp_state != KEYSPAN_PORT_OPEN) { 762 kp->kp_no_more_reads = B_TRUE; 763 } 764 } 765 766 return (data_len); 767 } 768 #endif /* If KEYSPAN_USA49WLC defined */ 769 770 /* 771 * pipe callbacks 772 * -------------- 773 * 774 * bulk in common callback 775 */ 776 /*ARGSUSED*/ 777 void 778 keyspan_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 779 { 780 keyspan_port_t *kp = (keyspan_port_t *)req->bulk_client_private; 781 keyspan_state_t *ksp = kp->kp_ksp; 782 int data_len; 783 boolean_t no_more_reads = B_FALSE; 784 785 USB_DPRINTF_L4(DPRINT_IN_PIPE, (&kp->kp_datain_pipe)->pipe_lh, 786 "keyspan_bulkin_cb"); 787 788 mutex_enter(&kp->kp_mutex); 789 790 /* put data on the read queue */ 791 switch (ksp->ks_dev_spec.id_product) { 792 case KEYSPAN_USA19HS_PID: 793 data_len = keyspan_bulkin_cb_usa19hs(pipe, req); 794 795 break; 796 797 #ifdef KEYSPAN_USA49WLC 798 case KEYSPAN_USA49WLC_PID: 799 data_len = keyspan_bulkin_cb_usa49(pipe, req); 800 801 break; 802 #endif /* If KEYSPAN_USA49WLC defined */ 803 default: 804 USB_DPRINTF_L2(DPRINT_IN_PIPE, (&kp->kp_datain_pipe)->pipe_lh, 805 "keyspan_bulkin_cb:" 806 "the device's product id can't be recognized"); 807 mutex_exit(&kp->kp_mutex); 808 809 return; 810 } 811 812 no_more_reads = kp->kp_no_more_reads; 813 814 mutex_exit(&kp->kp_mutex); 815 816 usb_free_bulk_req(req); 817 818 /* kick off another read unless indicated otherwise */ 819 if (!no_more_reads) { 820 (void) keyspan_receive_data(&kp->kp_datain_pipe, 821 kp->kp_read_len, kp); 822 } 823 824 /* setup rx callback for this port */ 825 if (data_len > 0) { 826 kp->kp_cb.cb_rx(kp->kp_cb.cb_arg); 827 } 828 } 829 830 /* 831 * pipe callbacks 832 * -------------- 833 * 834 * bulk in status callback for usa19hs model 835 */ 836 /*ARGSUSED*/ 837 void 838 keyspan_status_cb_usa19hs(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 839 { 840 keyspan_state_t *ksp = (keyspan_state_t *)req->bulk_client_private; 841 keyspan_pipe_t *bulkin = &ksp->ks_statin_pipe; 842 mblk_t *data = req->bulk_data; 843 usb_cr_t cr = req->bulk_completion_reason; 844 int data_len; 845 846 data_len = (data) ? MBLKL(data) : 0; 847 848 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 849 "keyspan_status_cb_usa19hs: len=%d" 850 " cr=%d flags=%x", data_len, cr, req->bulk_cb_flags); 851 852 /* put data on the read queue */ 853 if ((data_len == 14) && (cr == USB_CR_OK)) { 854 keyspan_port_t *kp = &ksp->ks_ports[0]; 855 keyspan_usa19hs_port_status_msg_t *status_msg = 856 &(kp->kp_status_msg.usa19hs); 857 858 mutex_enter(&kp->kp_mutex); 859 bcopy(data->b_rptr, status_msg, data_len); 860 861 if (status_msg->controlResponse) { 862 kp->kp_status_flag |= KEYSPAN_PORT_CTRLRESP; 863 } else { 864 kp->kp_status_flag &= ~KEYSPAN_PORT_CTRLRESP; 865 } 866 867 if (status_msg->portState & PORTSTATE_ENABLED) { 868 kp->kp_status_flag |= KEYSPAN_PORT_ENABLE; 869 } else { 870 kp->kp_status_flag &= ~KEYSPAN_PORT_ENABLE; 871 } 872 873 if (status_msg->portState & PORTSTATE_TXBREAK) { 874 kp->kp_status_flag |= KEYSPAN_PORT_TXBREAK; 875 } else { 876 kp->kp_status_flag &= ~KEYSPAN_PORT_TXBREAK; 877 } 878 879 if (status_msg->rxBreak) { 880 kp->kp_status_flag |= KEYSPAN_PORT_RXBREAK; 881 } else { 882 kp->kp_status_flag &= ~KEYSPAN_PORT_RXBREAK; 883 } 884 885 if (status_msg->portState & PORTSTATE_LOOPBACK) { 886 kp->kp_status_flag |= KEYSPAN_PORT_LOOPBACK; 887 } else { 888 kp->kp_status_flag &= ~KEYSPAN_PORT_LOOPBACK; 889 } 890 891 /* if msr status changed, then invoke status callback */ 892 if (status_msg->msr & USA_MSR_dCTS || 893 status_msg->msr & USA_MSR_dDSR || 894 status_msg->msr & USA_MSR_dRI || 895 status_msg->msr & USA_MSR_dDCD) { 896 897 mutex_exit(&kp->kp_mutex); 898 kp->kp_cb.cb_status(kp->kp_cb.cb_arg); 899 } else { 900 mutex_exit(&kp->kp_mutex); 901 } 902 } else { 903 904 USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh, 905 "keyspan_status_cb_usa19hs: get status failed, cr=%d" 906 " data_len=%d", cr, data_len); 907 } 908 } 909 910 #ifdef KEYSPAN_USA49WLC 911 /* 912 * pipe callbacks 913 * -------------- 914 * 915 * bulk in status callback for usa49 model 916 */ 917 /*ARGSUSED*/ 918 void 919 keyspan_status_cb_usa49(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 920 { 921 keyspan_state_t *ksp = (keyspan_state_t *)req->bulk_client_private; 922 keyspan_pipe_t *bulkin = &ksp->ks_statin_pipe; 923 mblk_t *data = req->bulk_data; 924 uint_t cr = req->bulk_completion_reason; 925 int data_len; 926 927 data_len = (data) ? MBLKL(data) : 0; 928 929 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 930 "keyspan_status_cb_usa49: len=%d" 931 " cr=%d flags=%x", data_len, cr, req->bulk_cb_flags); 932 933 /* put data on the read queue */ 934 if ((data_len == 11) && (cr == USB_CR_OK)) { 935 keyspan_usa49_port_status_msg_t status_msg; 936 keyspan_port_t *cur_kp; 937 keyspan_usa49_port_status_msg_t *kp_status_msg; 938 boolean_t need_cb = B_FALSE; 939 940 bcopy(data->b_rptr, &status_msg, data_len); 941 if (status_msg.portNumber >= ksp->ks_dev_spec.port_cnt) { 942 943 return; 944 } 945 cur_kp = &ksp->ks_ports[status_msg.portNumber]; 946 kp_status_msg = &(cur_kp->kp_status_msg.usa49); 947 948 mutex_enter(&cur_kp->kp_mutex); 949 950 /* if msr status changed, then need invoke status callback */ 951 if (status_msg.cts != kp_status_msg->cts || 952 status_msg.dsr != kp_status_msg->dsr || 953 status_msg.ri != kp_status_msg->ri || 954 status_msg.dcd != kp_status_msg->dcd) { 955 956 need_cb = B_TRUE; 957 } 958 959 bcopy(&status_msg, kp_status_msg, data_len); 960 961 if (kp_status_msg->controlResponse) { 962 cur_kp->kp_status_flag |= KEYSPAN_PORT_CTRLRESP; 963 } else { 964 cur_kp->kp_status_flag &= ~KEYSPAN_PORT_CTRLRESP; 965 } 966 967 if (!kp_status_msg->rxEnabled) { 968 cur_kp->kp_status_flag |= KEYSPAN_PORT_RXBREAK; 969 } else { 970 cur_kp->kp_status_flag &= ~KEYSPAN_PORT_RXBREAK; 971 } 972 973 mutex_exit(&cur_kp->kp_mutex); 974 975 if (need_cb) { 976 977 cur_kp->kp_cb.cb_status(cur_kp->kp_cb.cb_arg); 978 } 979 } else { 980 981 USB_DPRINTF_L2(DPRINT_IN_PIPE, bulkin->pipe_lh, 982 "keyspan_status_cb_usa49: get status failed, cr=%d" 983 " data_len=%d", cr, data_len); 984 } 985 } 986 #endif /* If KEYSPAN_USA49WLC defined */ 987 988 /* 989 * pipe callbacks 990 * -------------- 991 * 992 * bulk in callback for status receiving 993 */ 994 /*ARGSUSED*/ 995 void 996 keyspan_status_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 997 { 998 keyspan_state_t *ksp = (keyspan_state_t *)req->bulk_client_private; 999 usb_cr_t cr = req->bulk_completion_reason; 1000 1001 USB_DPRINTF_L4(DPRINT_IN_PIPE, (&ksp->ks_statin_pipe)->pipe_lh, 1002 "keyspan_status_cb"); 1003 1004 /* put data on the read queue */ 1005 switch (ksp->ks_dev_spec.id_product) { 1006 case KEYSPAN_USA19HS_PID: 1007 keyspan_status_cb_usa19hs(pipe, req); 1008 1009 break; 1010 1011 #ifdef KEYSPAN_USA49WLC 1012 case KEYSPAN_USA49WLC_PID: 1013 keyspan_status_cb_usa49(pipe, req); 1014 1015 break; 1016 #endif /* If KEYSPAN_USA49WLC defined */ 1017 default: 1018 USB_DPRINTF_L2(DPRINT_IN_PIPE, 1019 (&ksp->ks_statin_pipe)->pipe_lh, "keyspan_status_cb:" 1020 "the device's product id can't be recognized"); 1021 1022 return; 1023 } 1024 1025 usb_free_bulk_req(req); 1026 1027 /* kick off another read to receive status */ 1028 if ((cr != USB_CR_FLUSHED) && (cr != USB_CR_DEV_NOT_RESP) && 1029 keyspan_dev_is_online(ksp)) { 1030 if (keyspan_receive_status(ksp) != USB_SUCCESS) { 1031 USB_DPRINTF_L2(DPRINT_IN_PIPE, 1032 (&ksp->ks_statin_pipe)->pipe_lh, 1033 "keyspan_status_cb:" 1034 "receive status can't be restarted."); 1035 } 1036 } else { 1037 USB_DPRINTF_L2(DPRINT_IN_PIPE, 1038 (&ksp->ks_statin_pipe)->pipe_lh, "keyspan_status_cb:" 1039 "get status failed: cr=%d", cr); 1040 } 1041 } 1042 1043 /* 1044 * Submit data read request (asynchronous). If this function returns 1045 * USB_SUCCESS, pipe is acquired and request is sent, otherwise req is free. 1046 */ 1047 int 1048 keyspan_receive_data(keyspan_pipe_t *bulkin, int len, void *cb_arg) 1049 { 1050 keyspan_state_t *ksp = bulkin->pipe_ksp; 1051 usb_bulk_req_t *br; 1052 int rval; 1053 1054 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, "keyspan_receive_data:" 1055 "len=%d", len); 1056 1057 ASSERT(!mutex_owned(&bulkin->pipe_mutex)); 1058 1059 br = usb_alloc_bulk_req(ksp->ks_dip, len, USB_FLAGS_SLEEP); 1060 br->bulk_len = len; 1061 1062 /* No timeout, just wait for data */ 1063 br->bulk_timeout = 0; 1064 br->bulk_client_private = cb_arg; 1065 br->bulk_attributes = USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING; 1066 br->bulk_cb = keyspan_bulkin_cb; 1067 br->bulk_exc_cb = keyspan_bulkin_cb; 1068 1069 rval = usb_pipe_bulk_xfer(bulkin->pipe_handle, br, 0); 1070 if (rval != USB_SUCCESS) { 1071 usb_free_bulk_req(br); 1072 } 1073 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 1074 "keyspan_receive_data: rval = %d", rval); 1075 return (rval); 1076 } 1077 1078 /* 1079 * submit device status read request (asynchronous). 1080 */ 1081 int 1082 keyspan_receive_status(keyspan_state_t *ksp) 1083 { 1084 keyspan_pipe_t *bulkin = &ksp->ks_statin_pipe; 1085 usb_bulk_req_t *br; 1086 int rval; 1087 1088 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 1089 "keyspan_receive_status"); 1090 1091 ASSERT(!mutex_owned(&bulkin->pipe_mutex)); 1092 1093 br = usb_alloc_bulk_req(ksp->ks_dip, 32, USB_FLAGS_SLEEP); 1094 br->bulk_len = KEYSPAN_STATIN_MAX_LEN; 1095 1096 /* No timeout, just wait for data */ 1097 br->bulk_timeout = 0; 1098 br->bulk_client_private = (void *)ksp; 1099 br->bulk_attributes = USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING; 1100 br->bulk_cb = keyspan_status_cb; 1101 br->bulk_exc_cb = keyspan_status_cb; 1102 1103 rval = usb_pipe_bulk_xfer(bulkin->pipe_handle, br, 0); 1104 if (rval != USB_SUCCESS) { 1105 usb_free_bulk_req(br); 1106 } 1107 USB_DPRINTF_L4(DPRINT_IN_PIPE, bulkin->pipe_lh, 1108 "keyspan_receive_status: rval = %d", rval); 1109 return (rval); 1110 } 1111 1112 /* 1113 * submit data for transfer (asynchronous) 1114 * 1115 * if data was sent successfully, 'mpp' will be nulled to indicate 1116 * that mblk is consumed by USBA and no longer belongs to the caller. 1117 * 1118 * if this function returns USB_SUCCESS, pipe is acquired and request 1119 * is sent, otherwise pipe is free. 1120 */ 1121 int 1122 keyspan_send_data(keyspan_pipe_t *bulkout, mblk_t **mpp, void *cb_arg) 1123 { 1124 keyspan_state_t *ksp = bulkout->pipe_ksp; 1125 usb_bulk_req_t *br; 1126 int rval; 1127 1128 ASSERT(!mutex_owned(&bulkout->pipe_mutex)); 1129 USB_DPRINTF_L4(DPRINT_OUT_PIPE, bulkout->pipe_lh, 1130 "keyspan_send_data"); 1131 1132 br = usb_alloc_bulk_req(ksp->ks_dip, 0, USB_FLAGS_SLEEP); 1133 br->bulk_len = MBLKL(*mpp); 1134 br->bulk_data = *mpp; 1135 br->bulk_timeout = KEYSPAN_BULK_TIMEOUT; 1136 br->bulk_client_private = cb_arg; 1137 br->bulk_attributes = USB_ATTRS_AUTOCLEARING; 1138 br->bulk_cb = keyspan_bulkout_cb; 1139 br->bulk_exc_cb = keyspan_bulkout_cb; 1140 1141 USB_DPRINTF_L3(DPRINT_OUT_PIPE, bulkout->pipe_lh, "keyspan_send_data:" 1142 "bulk_len = %d", br->bulk_len); 1143 1144 rval = usb_pipe_bulk_xfer(bulkout->pipe_handle, br, 0); 1145 if (rval == USB_SUCCESS) { 1146 1147 /* data consumed. The mem will be released in bulkout_cb */ 1148 *mpp = NULL; 1149 } else { 1150 1151 /* 1152 * Don't free it in usb_free_bulk_req because it will 1153 * be linked in keyspan_put_head 1154 */ 1155 br->bulk_data = NULL; 1156 1157 usb_free_bulk_req(br); 1158 } 1159 USB_DPRINTF_L4(DPRINT_OUT_PIPE, bulkout->pipe_lh, 1160 "keyspan_send_data: rval = %d", rval); 1161 1162 return (rval); 1163 } 1164