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 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * 30 * USB generic serial driver (GSD) 31 * 32 */ 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <sys/stream.h> 36 #include <sys/stropts.h> 37 #include <sys/errno.h> 38 #include <sys/cred.h> 39 #include <sys/conf.h> 40 #include <sys/stat.h> 41 #include <sys/modctl.h> 42 #include <sys/ddi.h> 43 #include <sys/sunddi.h> 44 #include <sys/sunndi.h> 45 #include <sys/termio.h> 46 #include <sys/termiox.h> 47 #include <sys/stropts.h> 48 #include <sys/stream.h> 49 #include <sys/strsubr.h> 50 #include <sys/strsun.h> 51 #include <sys/strtty.h> 52 #include <sys/policy.h> 53 #include <sys/consdev.h> 54 55 #include <sys/usb/usba.h> 56 #include <sys/usb/clients/usbser/usbser_var.h> 57 #include <sys/usb/clients/usbser/usbser_dsdi.h> 58 #include <sys/usb/clients/usbser/usbser_rseq.h> 59 #include <sys/usb/usba/genconsole.h> 60 61 /* autoconfiguration subroutines */ 62 static int usbser_rseq_do_cb(rseq_t *, int, uintptr_t); 63 static int usbser_free_soft_state(usbser_state_t *); 64 static int usbser_init_soft_state(usbser_state_t *); 65 static int usbser_fini_soft_state(usbser_state_t *); 66 static int usbser_attach_dev(usbser_state_t *); 67 static void usbser_detach_dev(usbser_state_t *); 68 static int usbser_attach_ports(usbser_state_t *); 69 static int usbser_create_port_minor_nodes(usbser_state_t *, int); 70 static void usbser_detach_ports(usbser_state_t *); 71 static int usbser_create_taskq(usbser_state_t *); 72 static void usbser_destroy_taskq(usbser_state_t *); 73 static void usbser_set_dev_state_init(usbser_state_t *); 74 75 /* hotplugging and power management */ 76 static int usbser_disconnect_cb(dev_info_t *); 77 static int usbser_reconnect_cb(dev_info_t *); 78 static void usbser_disconnect_ports(usbser_state_t *); 79 static int usbser_cpr_suspend(dev_info_t *); 80 static int usbser_suspend_ports(usbser_state_t *); 81 static void usbser_cpr_resume(dev_info_t *); 82 static int usbser_restore_device_state(usbser_state_t *); 83 static void usbser_restore_ports_state(usbser_state_t *); 84 85 /* STREAMS subroutines */ 86 static int usbser_open_setup(queue_t *, usbser_port_t *, int, int, 87 cred_t *); 88 static int usbser_open_init(usbser_port_t *, int); 89 static void usbser_check_port_props(usbser_port_t *); 90 static void usbser_open_fini(usbser_port_t *); 91 static int usbser_open_line_setup(usbser_port_t *, int, int); 92 static int usbser_open_carrier_check(usbser_port_t *, int, int); 93 static void usbser_open_queues_init(usbser_port_t *, queue_t *); 94 static void usbser_open_queues_fini(usbser_port_t *); 95 static void usbser_close_drain(usbser_port_t *); 96 static void usbser_close_cancel_break(usbser_port_t *); 97 static void usbser_close_hangup(usbser_port_t *); 98 static void usbser_close_cleanup(usbser_port_t *); 99 100 /* threads */ 101 static void usbser_thr_dispatch(usbser_thread_t *); 102 static void usbser_thr_cancel(usbser_thread_t *); 103 static void usbser_thr_wake(usbser_thread_t *); 104 static void usbser_wq_thread(void *); 105 static void usbser_rq_thread(void *); 106 107 /* DSD callbacks */ 108 static void usbser_tx_cb(caddr_t); 109 static void usbser_rx_cb(caddr_t); 110 static void usbser_rx_massage_data(usbser_port_t *, mblk_t *); 111 static void usbser_rx_massage_mbreak(usbser_port_t *, mblk_t *); 112 static void usbser_rx_cb_put(usbser_port_t *, queue_t *, queue_t *, 113 mblk_t *); 114 static void usbser_status_cb(caddr_t); 115 static void usbser_status_proc_cb(usbser_port_t *); 116 117 /* serial support */ 118 static void usbser_wmsg(usbser_port_t *); 119 static int usbser_data(usbser_port_t *, mblk_t *); 120 static int usbser_ioctl(usbser_port_t *, mblk_t *); 121 static void usbser_iocdata(usbser_port_t *, mblk_t *); 122 static void usbser_stop(usbser_port_t *, mblk_t *); 123 static void usbser_start(usbser_port_t *, mblk_t *); 124 static void usbser_stopi(usbser_port_t *, mblk_t *); 125 static void usbser_starti(usbser_port_t *, mblk_t *); 126 static void usbser_flush(usbser_port_t *, mblk_t *); 127 static void usbser_break(usbser_port_t *, mblk_t *); 128 static void usbser_delay(usbser_port_t *, mblk_t *); 129 static void usbser_restart(void *); 130 static int usbser_port_program(usbser_port_t *); 131 static void usbser_inbound_flow_ctl(usbser_port_t *); 132 133 /* misc */ 134 static int usbser_dev_is_online(usbser_state_t *); 135 static void usbser_serialize_port_act(usbser_port_t *, int); 136 static void usbser_release_port_act(usbser_port_t *, int); 137 static char *usbser_msgtype2str(int); 138 static char *usbser_ioctl2str(int); 139 140 141 /* USBA events */ 142 usb_event_t usbser_usb_events = { 143 usbser_disconnect_cb, /* disconnect */ 144 usbser_reconnect_cb, /* reconnect */ 145 NULL, /* pre-suspend */ 146 NULL, /* pre-resume */ 147 }; 148 149 /* debug support */ 150 uint_t usbser_errlevel = USB_LOG_L4; 151 uint_t usbser_errmask = DPRINT_MASK_ALL; 152 uint_t usbser_instance_debug = (uint_t)-1; 153 154 /* usb serial console */ 155 static struct usbser_state *usbser_list; 156 static kmutex_t usbser_lock; 157 static int usbser_console_abort; 158 static usb_console_info_t console_input, console_output; 159 static uchar_t *console_input_buf; 160 static uchar_t *console_input_start, *console_input_end; 161 162 _NOTE(SCHEME_PROTECTS_DATA("unshared", usbser_console_abort)) 163 _NOTE(SCHEME_PROTECTS_DATA("unshared", console_input)) 164 _NOTE(SCHEME_PROTECTS_DATA("unshared", console_output)) 165 _NOTE(SCHEME_PROTECTS_DATA("unshared", console_input_start)) 166 _NOTE(SCHEME_PROTECTS_DATA("unshared", console_input_end)) 167 168 static void usbser_putchar(cons_polledio_arg_t, uchar_t); 169 static int usbser_getchar(cons_polledio_arg_t); 170 static boolean_t usbser_ischar(cons_polledio_arg_t); 171 static void usbser_polledio_enter(cons_polledio_arg_t); 172 static void usbser_polledio_exit(cons_polledio_arg_t); 173 static int usbser_polledio_init(usbser_port_t *); 174 static void usbser_polledio_fini(usbser_port_t *); 175 176 static struct cons_polledio usbser_polledio = { 177 CONSPOLLEDIO_V1, 178 NULL, /* to be set later */ 179 usbser_putchar, 180 usbser_getchar, 181 usbser_ischar, 182 usbser_polledio_enter, 183 usbser_polledio_exit 184 }; 185 186 /* various statistics. TODO: replace with kstats */ 187 static int usbser_st_tx_data_loss = 0; 188 static int usbser_st_rx_data_loss = 0; 189 static int usbser_st_put_stopi = 0; 190 static int usbser_st_mstop = 0; 191 static int usbser_st_mstart = 0; 192 static int usbser_st_mstopi = 0; 193 static int usbser_st_mstarti = 0; 194 static int usbser_st_rsrv = 0; 195 _NOTE(SCHEME_PROTECTS_DATA("monotonic stats", usbser_st_{ 196 tx_data_loss rx_data_loss put_stopi mstop mstart mstopi mstarti rsrv})) 197 _NOTE(SCHEME_PROTECTS_DATA("unshared", usb_bulk_req_t)) 198 _NOTE(SCHEME_PROTECTS_DATA("unshared", usb_intr_req_t)) 199 200 /* taskq parameter */ 201 extern pri_t minclsyspri; 202 203 /* 204 * tell warlock not to worry about STREAMS structures 205 */ 206 _NOTE(SCHEME_PROTECTS_DATA("unique per call", iocblk datab msgb queue copyreq)) 207 208 /* 209 * modload support 210 */ 211 extern struct mod_ops mod_miscops; 212 213 static struct modlmisc modlmisc = { 214 &mod_miscops, /* Type of module */ 215 "USB generic serial module" 216 }; 217 218 static struct modlinkage modlinkage = { 219 MODREV_1, (void *)&modlmisc, NULL 220 }; 221 222 223 #define RSEQ(f1, f2) RSEQE(f1, usbser_rseq_do_cb, f2, NULL) 224 225 226 /* 227 * loadable module entry points 228 * ---------------------------- 229 */ 230 231 int 232 _init(void) 233 { 234 int err; 235 236 mutex_init(&usbser_lock, NULL, MUTEX_DRIVER, (void *)NULL); 237 if (err = mod_install(&modlinkage)) 238 mutex_destroy(&usbser_lock); 239 240 return (err); 241 } 242 243 244 int 245 _fini(void) 246 { 247 int err; 248 249 if (err = mod_remove(&modlinkage)) 250 251 return (err); 252 253 mutex_destroy(&usbser_lock); 254 255 return (0); 256 } 257 258 259 int 260 _info(struct modinfo *modinfop) 261 { 262 return (mod_info(&modlinkage, modinfop)); 263 } 264 265 266 /* 267 * soft state size 268 */ 269 int 270 usbser_soft_state_size() 271 { 272 return (sizeof (usbser_state_t)); 273 } 274 275 276 /* 277 * autoconfiguration entry points 278 * ------------------------------ 279 */ 280 281 /*ARGSUSED*/ 282 int 283 usbser_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 284 void **result, void *statep) 285 { 286 int instance; 287 int ret = DDI_FAILURE; 288 usbser_state_t *usbserp; 289 290 instance = USBSER_MINOR2INST(getminor((dev_t)arg)); 291 292 switch (infocmd) { 293 case DDI_INFO_DEVT2DEVINFO: 294 *result = NULL; 295 usbserp = ddi_get_soft_state(statep, instance); 296 if (usbserp != NULL) { 297 *result = usbserp->us_dip; 298 if (*result != NULL) { 299 ret = DDI_SUCCESS; 300 } 301 } 302 303 break; 304 case DDI_INFO_DEVT2INSTANCE: 305 *result = (void *)(uintptr_t)instance; 306 ret = DDI_SUCCESS; 307 308 break; 309 default: 310 break; 311 } 312 313 return (ret); 314 } 315 316 /* 317 * device attach 318 */ 319 static rseq_t rseq_att[] = { 320 RSEQ(NULL, usbser_free_soft_state), 321 RSEQ(usbser_init_soft_state, usbser_fini_soft_state), 322 RSEQ(usbser_attach_dev, usbser_detach_dev), 323 RSEQ(usbser_attach_ports, usbser_detach_ports), 324 RSEQ(usbser_create_taskq, usbser_destroy_taskq), 325 RSEQ(NULL, usbser_set_dev_state_init) 326 }; 327 328 static void 329 usbser_insert(struct usbser_state *usp) 330 { 331 struct usbser_state *tmp; 332 333 mutex_enter(&usbser_lock); 334 tmp = usbser_list; 335 if (tmp == NULL) 336 usbser_list = usp; 337 else { 338 while (tmp->us_next) 339 tmp = tmp->us_next; 340 tmp->us_next = usp; 341 } 342 mutex_exit(&usbser_lock); 343 } 344 345 static void 346 usbser_remove(struct usbser_state *usp) 347 { 348 struct usbser_state *tmp, *prev = NULL; 349 350 mutex_enter(&usbser_lock); 351 tmp = usbser_list; 352 while (tmp != usp) { 353 prev = tmp; 354 tmp = tmp->us_next; 355 } 356 ASSERT(tmp == usp); /* must exist, else attach/detach wrong */ 357 if (prev) 358 prev->us_next = usp->us_next; 359 else 360 usbser_list = usp->us_next; 361 usp->us_next = NULL; 362 mutex_exit(&usbser_lock); 363 } 364 365 /* 366 * Return the first serial device, with dip held. This is called 367 * from the console subsystem to place console on usb serial device. 368 */ 369 dev_info_t * 370 usbser_first_device(void) 371 { 372 dev_info_t *dip = NULL; 373 374 mutex_enter(&usbser_lock); 375 if (usbser_list) { 376 dip = usbser_list->us_dip; 377 ndi_hold_devi(dip); 378 } 379 mutex_exit(&usbser_lock); 380 381 return (dip); 382 } 383 384 int 385 usbser_attach(dev_info_t *dip, ddi_attach_cmd_t cmd, 386 void *statep, ds_ops_t *ds_ops) 387 { 388 int instance; 389 usbser_state_t *usp; 390 391 instance = ddi_get_instance(dip); 392 393 switch (cmd) { 394 case DDI_ATTACH: 395 396 break; 397 case DDI_RESUME: 398 usbser_cpr_resume(dip); 399 400 return (DDI_SUCCESS); 401 default: 402 403 return (DDI_FAILURE); 404 } 405 406 /* allocate and get soft state */ 407 if (ddi_soft_state_zalloc(statep, instance) != DDI_SUCCESS) { 408 409 return (DDI_FAILURE); 410 } 411 if ((usp = ddi_get_soft_state(statep, instance)) == NULL) { 412 ddi_soft_state_free(statep, instance); 413 414 return (DDI_FAILURE); 415 } 416 417 usp->us_statep = statep; 418 usp->us_dip = dip; 419 usp->us_instance = instance; 420 usp->us_ds_ops = ds_ops; 421 422 if (rseq_do(rseq_att, NELEM(rseq_att), (uintptr_t)usp, 0) == RSEQ_OK) { 423 ddi_report_dev(dip); 424 usbser_insert(usp); 425 426 return (DDI_SUCCESS); 427 } else { 428 429 return (DDI_FAILURE); 430 } 431 } 432 433 /* 434 * device detach 435 */ 436 int 437 usbser_detach(dev_info_t *dip, ddi_detach_cmd_t cmd, void *statep) 438 { 439 int instance = ddi_get_instance(dip); 440 usbser_state_t *usp; 441 int rval; 442 443 usp = ddi_get_soft_state(statep, instance); 444 445 switch (cmd) { 446 case DDI_DETACH: 447 USB_DPRINTF_L4(DPRINT_DETACH, usp->us_lh, "usbser_detach"); 448 usbser_remove(usp); 449 (void) rseq_undo(rseq_att, NELEM(rseq_att), (uintptr_t)usp, 0); 450 USB_DPRINTF_L4(DPRINT_DETACH, NULL, 451 "usbser_detach.%d: end", instance); 452 453 return (DDI_SUCCESS); 454 case DDI_SUSPEND: 455 rval = usbser_cpr_suspend(dip); 456 457 return ((rval == USB_SUCCESS)? DDI_SUCCESS : DDI_FAILURE); 458 default: 459 460 return (DDI_FAILURE); 461 } 462 } 463 464 /* 465 * STREAMS entry points 466 * -------------------- 467 * 468 * 469 * port open 470 */ 471 /*ARGSUSED*/ 472 int 473 usbser_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr, 474 void *statep) 475 { 476 usbser_state_t *usp; 477 usbser_port_t *pp; 478 int minor = getminor(*dev); 479 int instance; 480 uint_t port_num; 481 int rval; 482 483 instance = USBSER_MINOR2INST(minor); 484 if (instance < 0) { 485 486 return (ENXIO); 487 } 488 489 usp = ddi_get_soft_state(statep, instance); 490 if (usp == NULL) { 491 492 return (ENXIO); 493 } 494 495 /* don't allow to open disconnected device */ 496 mutex_enter(&usp->us_mutex); 497 if (usp->us_dev_state == USB_DEV_DISCONNECTED) { 498 mutex_exit(&usp->us_mutex); 499 500 return (ENXIO); 501 } 502 mutex_exit(&usp->us_mutex); 503 504 /* get port soft state */ 505 port_num = USBSER_MINOR2PORT(minor); 506 if (port_num >= usp->us_port_cnt) { 507 508 return (ENXIO); 509 } 510 pp = &usp->us_ports[port_num]; 511 512 /* set up everything for open */ 513 rval = usbser_open_setup(rq, pp, minor, flag, cr); 514 515 USB_DPRINTF_L4(DPRINT_OPEN, pp->port_lh, "usbser_open: rval=%d", rval); 516 517 return (rval); 518 } 519 520 521 /* 522 * port close 523 * 524 * some things driver should do when the last app closes the line: 525 * 526 * drain data; 527 * cancel break/delay; 528 * hangup line (if necessary); 529 * DSD close; 530 * cleanup soft state; 531 */ 532 /*ARGSUSED*/ 533 int 534 usbser_close(queue_t *rq, int flag, cred_t *cr) 535 { 536 usbser_port_t *pp = (usbser_port_t *)rq->q_ptr; 537 int online; 538 539 if (pp == NULL) { 540 541 return (ENXIO); 542 } 543 544 online = usbser_dev_is_online(pp->port_usp); 545 546 /* 547 * in the closing state new activities will not be initiated 548 */ 549 mutex_enter(&pp->port_mutex); 550 pp->port_state = USBSER_PORT_CLOSING; 551 552 if (online) { 553 /* drain the data */ 554 usbser_close_drain(pp); 555 } 556 557 /* stop break/delay */ 558 usbser_close_cancel_break(pp); 559 560 if (online) { 561 /* hangup line */ 562 usbser_close_hangup(pp); 563 } 564 565 /* 566 * close DSD, cleanup state and transition to 'closed' state 567 */ 568 usbser_close_cleanup(pp); 569 mutex_exit(&pp->port_mutex); 570 571 USB_DPRINTF_L4(DPRINT_CLOSE, pp->port_lh, "usbser_close: end"); 572 573 return (0); 574 } 575 576 577 /* 578 * read side service routine: send as much as possible messages upstream 579 * and if there is still place on the queue, enable receive (if not already) 580 */ 581 int 582 usbser_rsrv(queue_t *q) 583 { 584 usbser_port_t *pp = (usbser_port_t *)q->q_ptr; 585 mblk_t *mp; 586 587 usbser_st_rsrv++; 588 USB_DPRINTF_L4(DPRINT_RQ, pp->port_lh, "usbser_rsrv"); 589 590 while (canputnext(q) && (mp = getq(q))) { 591 putnext(q, mp); 592 } 593 594 if (canputnext(q)) { 595 mutex_enter(&pp->port_mutex); 596 ASSERT(pp->port_state != USBSER_PORT_CLOSED); 597 598 if (USBSER_PORT_ACCESS_OK(pp)) { 599 usbser_thr_wake(&pp->port_rq_thread); 600 } 601 mutex_exit(&pp->port_mutex); 602 } 603 604 return (0); 605 } 606 607 608 /* 609 * wput: put message on the queue and wake wq thread 610 */ 611 int 612 usbser_wput(queue_t *q, mblk_t *mp) 613 { 614 usbser_port_t *pp = (usbser_port_t *)q->q_ptr; 615 616 USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wput"); 617 618 mutex_enter(&pp->port_mutex); 619 ASSERT(pp->port_state != USBSER_PORT_CLOSED); 620 621 /* ignore new messages if port is already closing */ 622 if (pp->port_state == USBSER_PORT_CLOSING) { 623 freemsg(mp); 624 } else if (putq(q, mp)) { 625 /* 626 * this counter represents amount of tx data on the wq. 627 * each time the data is passed to DSD for transmission, 628 * the counter is decremented accordingly 629 */ 630 pp->port_wq_data_cnt += msgdsize(mp); 631 } else { 632 usbser_st_tx_data_loss++; 633 } 634 mutex_exit(&pp->port_mutex); 635 636 return (0); 637 } 638 639 640 /* 641 * we need wsrv() routine to take advantage of STREAMS flow control: 642 * without it the framework will consider we are always able to process msgs 643 */ 644 int 645 usbser_wsrv(queue_t *q) 646 { 647 usbser_port_t *pp = (usbser_port_t *)q->q_ptr; 648 649 USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wsrv"); 650 651 mutex_enter(&pp->port_mutex); 652 ASSERT(pp->port_state != USBSER_PORT_CLOSED); 653 654 if (USBSER_PORT_ACCESS_OK(pp)) { 655 usbser_thr_wake(&pp->port_wq_thread); 656 } 657 mutex_exit(&pp->port_mutex); 658 659 return (0); 660 } 661 662 663 /* 664 * power entry point 665 */ 666 int 667 usbser_power(dev_info_t *dip, int comp, int level) 668 { 669 void *statep; 670 usbser_state_t *usp; 671 int new_state; 672 int rval; 673 674 statep = ddi_get_driver_private(dip); 675 usp = ddi_get_soft_state(statep, ddi_get_instance(dip)); 676 677 USB_DPRINTF_L3(DPRINT_EVENTS, usp->us_lh, 678 "usbser_power: dip=0x%p, comp=%d, level=%d", 679 (void *)dip, comp, level); 680 681 mutex_enter(&usp->us_mutex); 682 new_state = usp->us_dev_state; 683 mutex_exit(&usp->us_mutex); 684 685 /* let DSD do the job */ 686 rval = USBSER_DS_USB_POWER(usp, comp, level, &new_state); 687 688 /* stay in sync with DSD */ 689 mutex_enter(&usp->us_mutex); 690 usp->us_dev_state = new_state; 691 mutex_exit(&usp->us_mutex); 692 693 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 694 } 695 696 697 /* 698 * 699 * configuration entry point subroutines 700 * ------------------------------------- 701 * 702 * rseq callback 703 */ 704 static int 705 usbser_rseq_do_cb(rseq_t *rseq, int num, uintptr_t arg) 706 { 707 usbser_state_t *usp = (usbser_state_t *)arg; 708 int rval = rseq[num].r_do.s_rval; 709 char *name = rseq[num].r_do.s_name; 710 711 if (rval != DDI_SUCCESS) { 712 USB_DPRINTF_L2(DPRINT_ATTACH, usp->us_lh, 713 "do %s failed (%d)", name, rval); 714 715 return (RSEQ_UNDO); 716 } else { 717 718 return (RSEQ_OK); 719 } 720 } 721 722 723 /* 724 * free soft state 725 */ 726 static int 727 usbser_free_soft_state(usbser_state_t *usp) 728 { 729 ddi_soft_state_free(usp->us_statep, usp->us_instance); 730 731 return (USB_SUCCESS); 732 } 733 734 /* 735 * init instance soft state 736 */ 737 static int 738 usbser_init_soft_state(usbser_state_t *usp) 739 { 740 usp->us_lh = usb_alloc_log_hdl(usp->us_dip, "usbs[*].", 741 &usbser_errlevel, &usbser_errmask, &usbser_instance_debug, 742 0); 743 mutex_init(&usp->us_mutex, NULL, MUTEX_DRIVER, (void *)NULL); 744 745 /* save state pointer for use in event callbacks */ 746 ddi_set_driver_private(usp->us_dip, usp->us_statep); 747 748 usp->us_dev_state = USBSER_DEV_INIT; 749 750 return (DDI_SUCCESS); 751 } 752 753 /* 754 * fini instance soft state 755 */ 756 static int 757 usbser_fini_soft_state(usbser_state_t *usp) 758 { 759 usb_free_log_hdl(usp->us_lh); 760 mutex_destroy(&usp->us_mutex); 761 ddi_set_driver_private(usp->us_dip, NULL); 762 763 return (DDI_SUCCESS); 764 } 765 766 /* 767 * attach entire device 768 */ 769 static int 770 usbser_attach_dev(usbser_state_t *usp) 771 { 772 ds_attach_info_t ai; 773 int rval; 774 775 usp->us_dev_state = USB_DEV_ONLINE; 776 777 ai.ai_dip = usp->us_dip; 778 ai.ai_usb_events = &usbser_usb_events; 779 ai.ai_hdl = &usp->us_ds_hdl; 780 ai.ai_port_cnt = &usp->us_port_cnt; 781 782 rval = USBSER_DS_ATTACH(usp, &ai); 783 784 if ((rval != USB_SUCCESS) || (usp->us_ds_hdl == NULL) || 785 (usp->us_port_cnt == 0)) { 786 USB_DPRINTF_L4(DPRINT_ATTACH, usp->us_lh, "usbser_attach_dev: " 787 "failed %d %p %d", rval, usp->us_ds_hdl, usp->us_port_cnt); 788 789 return (DDI_FAILURE); 790 } 791 792 USB_DPRINTF_L4(DPRINT_ATTACH, usp->us_lh, 793 "usbser_attach_dev: port_cnt = %d", usp->us_port_cnt); 794 795 return (DDI_SUCCESS); 796 } 797 798 799 /* 800 * detach entire device 801 */ 802 static void 803 usbser_detach_dev(usbser_state_t *usp) 804 { 805 USBSER_DS_DETACH(usp); 806 } 807 808 809 /* 810 * attach each individual port 811 */ 812 static int 813 usbser_attach_ports(usbser_state_t *usp) 814 { 815 int i; 816 usbser_port_t *pp; 817 ds_cb_t ds_cb; 818 819 /* 820 * allocate port array 821 */ 822 usp->us_ports = kmem_zalloc(usp->us_port_cnt * 823 sizeof (usbser_port_t), KM_SLEEP); 824 825 /* callback handlers */ 826 ds_cb.cb_tx = usbser_tx_cb; 827 ds_cb.cb_rx = usbser_rx_cb; 828 ds_cb.cb_status = usbser_status_cb; 829 830 /* 831 * initialize each port 832 */ 833 for (i = 0; i < usp->us_port_cnt; i++) { 834 pp = &usp->us_ports[i]; 835 836 /* 837 * initialize data 838 */ 839 pp->port_num = i; 840 pp->port_usp = usp; 841 pp->port_ds_ops = usp->us_ds_ops; 842 pp->port_ds_hdl = usp->us_ds_hdl; 843 844 /* allocate log handle */ 845 (void) sprintf(pp->port_lh_name, "usbs[%d].", i); 846 pp->port_lh = usb_alloc_log_hdl(usp->us_dip, 847 pp->port_lh_name, &usbser_errlevel, &usbser_errmask, 848 &usbser_instance_debug, 0); 849 850 mutex_init(&pp->port_mutex, NULL, MUTEX_DRIVER, (void *)NULL); 851 cv_init(&pp->port_state_cv, NULL, CV_DEFAULT, NULL); 852 cv_init(&pp->port_act_cv, NULL, CV_DEFAULT, NULL); 853 cv_init(&pp->port_car_cv, NULL, CV_DEFAULT, NULL); 854 855 /* 856 * init threads 857 */ 858 pp->port_wq_thread.thr_port = pp; 859 pp->port_wq_thread.thr_func = usbser_wq_thread; 860 pp->port_wq_thread.thr_arg = (void *)&pp->port_wq_thread; 861 cv_init(&pp->port_wq_thread.thr_cv, NULL, CV_DEFAULT, NULL); 862 863 pp->port_rq_thread.thr_port = pp; 864 pp->port_rq_thread.thr_func = usbser_rq_thread; 865 pp->port_rq_thread.thr_arg = (void *)&pp->port_rq_thread; 866 cv_init(&pp->port_rq_thread.thr_cv, NULL, CV_DEFAULT, NULL); 867 868 /* 869 * register callbacks 870 */ 871 ds_cb.cb_arg = (caddr_t)pp; 872 USBSER_DS_REGISTER_CB(usp, i, &ds_cb); 873 874 pp->port_state = USBSER_PORT_CLOSED; 875 876 if (usbser_create_port_minor_nodes(usp, i) != USB_SUCCESS) { 877 usbser_detach_ports(usp); 878 879 return (DDI_FAILURE); 880 } 881 } 882 883 return (DDI_SUCCESS); 884 } 885 886 887 /* 888 * create a pair of minor nodes for the port 889 */ 890 static int 891 usbser_create_port_minor_nodes(usbser_state_t *usp, int port_num) 892 { 893 int instance = usp->us_instance; 894 minor_t minor; 895 char name[16]; 896 897 /* 898 * tty node 899 */ 900 (void) sprintf(name, "%d", port_num); 901 minor = USBSER_MAKEMINOR(instance, port_num, 0); 902 903 if (ddi_create_minor_node(usp->us_dip, name, 904 S_IFCHR, minor, DDI_NT_SERIAL, NULL) != DDI_SUCCESS) { 905 906 return (USB_FAILURE); 907 } 908 909 /* 910 * dial-out node 911 */ 912 (void) sprintf(name, "%d,cu", port_num); 913 minor = USBSER_MAKEMINOR(instance, port_num, OUTLINE); 914 915 if (ddi_create_minor_node(usp->us_dip, name, 916 S_IFCHR, minor, DDI_NT_SERIAL_DO, NULL) != DDI_SUCCESS) { 917 918 return (USB_FAILURE); 919 } 920 921 return (USB_SUCCESS); 922 } 923 924 925 /* 926 * detach each port individually 927 */ 928 static void 929 usbser_detach_ports(usbser_state_t *usp) 930 { 931 int i; 932 int sz; 933 usbser_port_t *pp; 934 935 /* 936 * remove all minor nodes 937 */ 938 ddi_remove_minor_node(usp->us_dip, NULL); 939 940 for (i = 0; i < usp->us_port_cnt; i++) { 941 pp = &usp->us_ports[i]; 942 943 if (pp->port_state != USBSER_PORT_CLOSED) { 944 ASSERT(pp->port_state == USBSER_PORT_NOT_INIT); 945 946 continue; 947 } 948 949 USBSER_DS_UNREGISTER_CB(usp, i); 950 951 mutex_destroy(&pp->port_mutex); 952 cv_destroy(&pp->port_state_cv); 953 cv_destroy(&pp->port_act_cv); 954 cv_destroy(&pp->port_car_cv); 955 956 cv_destroy(&pp->port_wq_thread.thr_cv); 957 cv_destroy(&pp->port_rq_thread.thr_cv); 958 959 usb_free_log_hdl(pp->port_lh); 960 } 961 962 /* 963 * free memory 964 */ 965 sz = usp->us_port_cnt * sizeof (usbser_port_t); 966 kmem_free(usp->us_ports, sz); 967 usp->us_ports = NULL; 968 } 969 970 971 /* 972 * create a taskq with two threads per port (read and write sides) 973 */ 974 static int 975 usbser_create_taskq(usbser_state_t *usp) 976 { 977 int nthr = usp->us_port_cnt * 2; 978 979 usp->us_taskq = ddi_taskq_create(usp->us_dip, "usbser_taskq", 980 nthr, TASKQ_DEFAULTPRI, 0); 981 982 return ((usp->us_taskq == NULL) ? DDI_FAILURE : DDI_SUCCESS); 983 } 984 985 986 static void 987 usbser_destroy_taskq(usbser_state_t *usp) 988 { 989 ddi_taskq_destroy(usp->us_taskq); 990 } 991 992 993 static void 994 usbser_set_dev_state_init(usbser_state_t *usp) 995 { 996 mutex_enter(&usp->us_mutex); 997 usp->us_dev_state = USBSER_DEV_INIT; 998 mutex_exit(&usp->us_mutex); 999 } 1000 1001 /* 1002 * hotplugging and power management 1003 * --------------------------------- 1004 * 1005 * disconnect event callback 1006 */ 1007 /*ARGSUSED*/ 1008 static int 1009 usbser_disconnect_cb(dev_info_t *dip) 1010 { 1011 void *statep; 1012 usbser_state_t *usp; 1013 1014 statep = ddi_get_driver_private(dip); 1015 usp = ddi_get_soft_state(statep, ddi_get_instance(dip)); 1016 1017 USB_DPRINTF_L3(DPRINT_EVENTS, usp->us_lh, 1018 "usbser_disconnect_cb: dip=%p", (void *)dip); 1019 1020 mutex_enter(&usp->us_mutex); 1021 switch (usp->us_dev_state) { 1022 case USB_DEV_ONLINE: 1023 case USB_DEV_PWRED_DOWN: 1024 /* prevent further activity */ 1025 usp->us_dev_state = USB_DEV_DISCONNECTED; 1026 mutex_exit(&usp->us_mutex); 1027 1028 /* see if any of the ports are open and do necessary handling */ 1029 usbser_disconnect_ports(usp); 1030 1031 /* call DSD to do any necessary work */ 1032 if (USBSER_DS_DISCONNECT(usp) != USB_DEV_DISCONNECTED) { 1033 USB_DPRINTF_L2(DPRINT_EVENTS, usp->us_lh, 1034 "usbser_disconnect_cb: ds_disconnect failed"); 1035 } 1036 1037 break; 1038 case USB_DEV_SUSPENDED: 1039 /* we remain suspended */ 1040 default: 1041 mutex_exit(&usp->us_mutex); 1042 1043 break; 1044 } 1045 1046 return (USB_SUCCESS); 1047 } 1048 1049 1050 /* 1051 * reconnect event callback 1052 */ 1053 /*ARGSUSED*/ 1054 static int 1055 usbser_reconnect_cb(dev_info_t *dip) 1056 { 1057 void *statep; 1058 usbser_state_t *usp; 1059 1060 statep = ddi_get_driver_private(dip); 1061 usp = ddi_get_soft_state(statep, ddi_get_instance(dip)); 1062 1063 USB_DPRINTF_L3(DPRINT_EVENTS, usp->us_lh, 1064 "usbser_reconnect_cb: dip=%p", (void *)dip); 1065 1066 (void) usbser_restore_device_state(usp); 1067 1068 return (USB_SUCCESS); 1069 } 1070 1071 1072 /* 1073 * if any of the ports is open during disconnect, 1074 * send M_HANGUP message upstream and log a warning 1075 */ 1076 static void 1077 usbser_disconnect_ports(usbser_state_t *usp) 1078 { 1079 usbser_port_t *pp; 1080 queue_t *rq; 1081 int complain = 0; 1082 int hangup = 0; 1083 timeout_id_t delay_id = 0; 1084 int i; 1085 1086 if (usp->us_ports == NULL) { 1087 return; 1088 } 1089 1090 for (i = 0; i < usp->us_port_cnt; i++) { 1091 pp = &usp->us_ports[i]; 1092 1093 mutex_enter(&pp->port_mutex); 1094 if (pp->port_state == USBSER_PORT_OPEN || 1095 USBSER_IS_OPENING(pp) || 1096 pp->port_state == USBSER_PORT_CLOSING) { 1097 complain = 1; 1098 } 1099 1100 if (pp->port_state == USBSER_PORT_OPEN) { 1101 rq = pp->port_ttycommon.t_readq; 1102 1103 /* 1104 * hangup the stream; will send actual 1105 * M_HANGUP message after releasing mutex 1106 */ 1107 pp->port_flags |= USBSER_FL_HUNGUP; 1108 hangup = 1; 1109 1110 /* 1111 * cancel all activities 1112 */ 1113 usbser_release_port_act(pp, USBSER_ACT_ALL); 1114 1115 delay_id = pp->port_delay_id; 1116 pp->port_delay_id = 0; 1117 1118 /* mark disconnected */ 1119 pp->port_state = USBSER_PORT_DISCONNECTED; 1120 cv_broadcast(&pp->port_state_cv); 1121 } 1122 mutex_exit(&pp->port_mutex); 1123 1124 if (hangup) { 1125 (void) putnextctl(rq, M_HANGUP); 1126 hangup = 0; 1127 } 1128 1129 /* 1130 * we couldn't untimeout while holding the mutex - do it now 1131 */ 1132 if (delay_id) { 1133 (void) untimeout(delay_id); 1134 delay_id = 0; 1135 } 1136 } 1137 1138 /* 1139 * complain about disconnecting device while open 1140 */ 1141 if (complain) { 1142 USB_DPRINTF_L0(DPRINT_EVENTS, usp->us_lh, "device was " 1143 "disconnected while open. Data may have been lost"); 1144 } 1145 } 1146 1147 1148 /* 1149 * do CPR suspend 1150 * 1151 * We use a trivial CPR strategy - fail if any of the device's ports are open. 1152 * The problem with more sophisticated strategies is that each open port uses 1153 * two threads that sit in the loop until the port is closed, while CPR has to 1154 * stop all kernel threads to succeed. Stopping port threads is a rather 1155 * intrusive and delicate procedure; I leave it as an RFE for now. 1156 * 1157 */ 1158 static int 1159 usbser_cpr_suspend(dev_info_t *dip) 1160 { 1161 void *statep; 1162 usbser_state_t *usp; 1163 int new_state; 1164 int rval; 1165 1166 statep = ddi_get_driver_private(dip); 1167 usp = ddi_get_soft_state(statep, ddi_get_instance(dip)); 1168 1169 USB_DPRINTF_L4(DPRINT_EVENTS, usp->us_lh, "usbser_cpr_suspend"); 1170 1171 /* suspend each port first */ 1172 if (usbser_suspend_ports(usp) != USB_SUCCESS) { 1173 USB_DPRINTF_L3(DPRINT_EVENTS, usp->us_lh, 1174 "usbser_cpr_suspend: GSD failure"); 1175 1176 return (USB_FAILURE); 1177 } 1178 1179 new_state = USBSER_DS_SUSPEND(usp); /* let DSD do its part */ 1180 1181 mutex_enter(&usp->us_mutex); 1182 if (new_state == USB_DEV_SUSPENDED) { 1183 rval = USB_SUCCESS; 1184 } else { 1185 ASSERT(new_state == USB_DEV_ONLINE); 1186 rval = USB_FAILURE; 1187 } 1188 usp->us_dev_state = new_state; 1189 mutex_exit(&usp->us_mutex); 1190 1191 return (rval); 1192 } 1193 1194 1195 static int 1196 usbser_suspend_ports(usbser_state_t *usp) 1197 { 1198 usbser_port_t *pp; 1199 int i; 1200 1201 for (i = 0; i < usp->us_port_cnt; i++) { 1202 pp = &usp->us_ports[i]; 1203 1204 mutex_enter(&pp->port_mutex); 1205 if (pp->port_state != USBSER_PORT_CLOSED) { 1206 mutex_exit(&pp->port_mutex); 1207 1208 return (USB_FAILURE); 1209 } 1210 mutex_exit(&pp->port_mutex); 1211 } 1212 1213 return (USB_SUCCESS); 1214 } 1215 1216 1217 /* 1218 * do CPR resume 1219 * 1220 * DSD will return USB_DEV_ONLINE in case of success 1221 */ 1222 static void 1223 usbser_cpr_resume(dev_info_t *dip) 1224 { 1225 void *statep; 1226 usbser_state_t *usp; 1227 1228 statep = ddi_get_driver_private(dip); 1229 usp = ddi_get_soft_state(statep, ddi_get_instance(dip)); 1230 1231 USB_DPRINTF_L3(DPRINT_EVENTS, usp->us_lh, "usbser_cpr_resume"); 1232 1233 (void) usbser_restore_device_state(usp); 1234 } 1235 1236 1237 /* 1238 * restore device state after CPR resume or reconnect 1239 */ 1240 static int 1241 usbser_restore_device_state(usbser_state_t *usp) 1242 { 1243 int new_state, current_state; 1244 1245 /* needed as power up state of dev is "unknown" to system */ 1246 (void) pm_busy_component(usp->us_dip, 0); 1247 (void) pm_raise_power(usp->us_dip, 0, USB_DEV_OS_FULL_PWR); 1248 1249 mutex_enter(&usp->us_mutex); 1250 current_state = usp->us_dev_state; 1251 mutex_exit(&usp->us_mutex); 1252 1253 ASSERT((current_state == USB_DEV_DISCONNECTED) || 1254 (current_state == USB_DEV_SUSPENDED)); 1255 1256 /* 1257 * call DSD to perform device-specific work 1258 */ 1259 if (current_state == USB_DEV_DISCONNECTED) { 1260 new_state = USBSER_DS_RECONNECT(usp); 1261 } else { 1262 new_state = USBSER_DS_RESUME(usp); 1263 } 1264 1265 mutex_enter(&usp->us_mutex); 1266 usp->us_dev_state = new_state; 1267 mutex_exit(&usp->us_mutex); 1268 1269 if (new_state == USB_DEV_ONLINE) { 1270 /* 1271 * restore ports state 1272 */ 1273 usbser_restore_ports_state(usp); 1274 } 1275 1276 (void) pm_idle_component(usp->us_dip, 0); 1277 1278 return (USB_SUCCESS); 1279 } 1280 1281 1282 /* 1283 * restore ports state after device reconnect/resume 1284 */ 1285 static void 1286 usbser_restore_ports_state(usbser_state_t *usp) 1287 { 1288 usbser_port_t *pp; 1289 queue_t *rq; 1290 int i; 1291 1292 for (i = 0; i < usp->us_port_cnt; i++) { 1293 pp = &usp->us_ports[i]; 1294 1295 mutex_enter(&pp->port_mutex); 1296 /* 1297 * only care about ports that are open 1298 */ 1299 if ((pp->port_state != USBSER_PORT_SUSPENDED) && 1300 (pp->port_state != USBSER_PORT_DISCONNECTED)) { 1301 mutex_exit(&pp->port_mutex); 1302 1303 continue; 1304 } 1305 1306 pp->port_state = USBSER_PORT_OPEN; 1307 1308 /* 1309 * if the stream was hung up during disconnect, restore it 1310 */ 1311 if (pp->port_flags & USBSER_FL_HUNGUP) { 1312 pp->port_flags &= ~USBSER_FL_HUNGUP; 1313 rq = pp->port_ttycommon.t_readq; 1314 1315 mutex_exit(&pp->port_mutex); 1316 (void) putnextctl(rq, M_UNHANGUP); 1317 mutex_enter(&pp->port_mutex); 1318 } 1319 1320 /* 1321 * restore serial parameters 1322 */ 1323 (void) usbser_port_program(pp); 1324 1325 /* 1326 * wake anything that might be sleeping 1327 */ 1328 cv_broadcast(&pp->port_state_cv); 1329 cv_broadcast(&pp->port_act_cv); 1330 usbser_thr_wake(&pp->port_wq_thread); 1331 usbser_thr_wake(&pp->port_rq_thread); 1332 mutex_exit(&pp->port_mutex); 1333 } 1334 } 1335 1336 1337 /* 1338 * STREAMS subroutines 1339 * ------------------- 1340 * 1341 * 1342 * port open state machine 1343 * 1344 * here's a list of things that the driver has to do while open; 1345 * because device can be opened any number of times, 1346 * initial open has additional responsibilities: 1347 * 1348 * if (initial_open) { 1349 * initialize soft state; \ 1350 * DSD open; - see usbser_open_init() 1351 * dispatch threads; / 1352 * } 1353 * raise DTR; 1354 * wait for carrier (if necessary); 1355 * 1356 * we should also take into consideration that two threads can try to open 1357 * the same physical port simultaneously (/dev/term/N and /dev/cua/N). 1358 * 1359 * return values: 1360 * 0 - success; 1361 * >0 - fail with this error code; 1362 */ 1363 static int 1364 usbser_open_setup(queue_t *rq, usbser_port_t *pp, int minor, int flag, 1365 cred_t *cr) 1366 { 1367 int rval = USBSER_CONTINUE; 1368 1369 mutex_enter(&pp->port_mutex); 1370 /* 1371 * refer to port state diagram in the header file 1372 */ 1373 loop: 1374 switch (pp->port_state) { 1375 case USBSER_PORT_CLOSED: 1376 /* 1377 * initial open 1378 */ 1379 rval = usbser_open_init(pp, minor); 1380 1381 break; 1382 case USBSER_PORT_OPENING_TTY: 1383 /* 1384 * dial-out thread can overtake the port 1385 * if tty open thread is sleeping waiting for carrier 1386 */ 1387 if ((minor & OUTLINE) && (pp->port_flags & USBSER_FL_WOPEN)) { 1388 pp->port_state = USBSER_PORT_OPENING_OUT; 1389 1390 USB_DPRINTF_L3(DPRINT_OPEN, pp->port_lh, 1391 "usbser_open_state: overtake"); 1392 } 1393 1394 /* FALLTHRU */ 1395 case USBSER_PORT_OPENING_OUT: 1396 /* 1397 * if no other open in progress, setup the line 1398 */ 1399 if (USBSER_NO_OTHER_OPEN(pp, minor)) { 1400 rval = usbser_open_line_setup(pp, minor, flag); 1401 1402 break; 1403 } 1404 1405 /* FALLTHRU */ 1406 case USBSER_PORT_CLOSING: 1407 /* 1408 * wait until close active phase ends 1409 */ 1410 if (cv_wait_sig(&pp->port_state_cv, &pp->port_mutex) == 0) { 1411 rval = EINTR; 1412 } 1413 1414 break; 1415 case USBSER_PORT_OPEN: 1416 if ((pp->port_ttycommon.t_flags & TS_XCLUDE) && 1417 secpolicy_excl_open(cr) != 0) { 1418 /* 1419 * exclusive use 1420 */ 1421 rval = EBUSY; 1422 } else if (USBSER_OPEN_IN_OTHER_MODE(pp, minor)) { 1423 /* 1424 * tty and dial-out modes are mutually exclusive 1425 */ 1426 rval = EBUSY; 1427 } else { 1428 /* 1429 * port is being re-open in the same mode 1430 */ 1431 rval = usbser_open_line_setup(pp, minor, flag); 1432 } 1433 1434 break; 1435 default: 1436 rval = ENXIO; 1437 1438 break; 1439 } 1440 1441 if (rval == USBSER_CONTINUE) { 1442 1443 goto loop; 1444 } 1445 1446 /* 1447 * initial open requires additional handling 1448 */ 1449 if (USBSER_IS_OPENING(pp)) { 1450 if (rval == USBSER_COMPLETE) { 1451 if (pp->port_state == USBSER_PORT_OPENING_OUT) { 1452 pp->port_flags |= USBSER_FL_OUT; 1453 } 1454 pp->port_state = USBSER_PORT_OPEN; 1455 cv_broadcast(&pp->port_state_cv); 1456 1457 usbser_open_queues_init(pp, rq); 1458 } else { 1459 usbser_open_fini(pp); 1460 } 1461 } 1462 mutex_exit(&pp->port_mutex); 1463 1464 return (rval); 1465 } 1466 1467 1468 /* 1469 * initialize the port when opened for the first time 1470 */ 1471 static int 1472 usbser_open_init(usbser_port_t *pp, int minor) 1473 { 1474 usbser_state_t *usp = pp->port_usp; 1475 tty_common_t *tp = &pp->port_ttycommon; 1476 int rval = ENXIO; 1477 1478 ASSERT(pp->port_state == USBSER_PORT_CLOSED); 1479 1480 /* 1481 * init state 1482 */ 1483 pp->port_act = 0; 1484 pp->port_flags &= USBSER_FL_PRESERVE; 1485 pp->port_flowc = '\0'; 1486 pp->port_wq_data_cnt = 0; 1487 1488 if (minor & OUTLINE) { 1489 pp->port_state = USBSER_PORT_OPENING_OUT; 1490 } else { 1491 pp->port_state = USBSER_PORT_OPENING_TTY; 1492 } 1493 1494 /* 1495 * init termios settings 1496 */ 1497 tp->t_iflag = 0; 1498 tp->t_iocpending = NULL; 1499 tp->t_size.ws_row = tp->t_size.ws_col = 0; 1500 tp->t_size.ws_xpixel = tp->t_size.ws_ypixel = 0; 1501 tp->t_startc = CSTART; 1502 tp->t_stopc = CSTOP; 1503 1504 usbser_check_port_props(pp); 1505 1506 /* 1507 * dispatch wq and rq threads: 1508 * although queues are not enabled at this point, 1509 * we will need wq to run status processing callback 1510 */ 1511 usbser_thr_dispatch(&pp->port_wq_thread); 1512 usbser_thr_dispatch(&pp->port_rq_thread); 1513 1514 /* 1515 * open DSD port 1516 */ 1517 mutex_exit(&pp->port_mutex); 1518 rval = USBSER_DS_OPEN_PORT(usp, pp->port_num); 1519 mutex_enter(&pp->port_mutex); 1520 1521 if (rval != USB_SUCCESS) { 1522 1523 return (ENXIO); 1524 } 1525 pp->port_flags |= USBSER_FL_DSD_OPEN; 1526 1527 /* 1528 * program port with default parameters 1529 */ 1530 if ((rval = usbser_port_program(pp)) != 0) { 1531 1532 return (ENXIO); 1533 } 1534 1535 return (USBSER_CONTINUE); 1536 } 1537 1538 1539 /* 1540 * create a pair of minor nodes for the port 1541 */ 1542 static void 1543 usbser_check_port_props(usbser_port_t *pp) 1544 { 1545 dev_info_t *dip = pp->port_usp->us_dip; 1546 tty_common_t *tp = &pp->port_ttycommon; 1547 struct termios *termiosp; 1548 uint_t len; 1549 char name[20]; 1550 1551 /* 1552 * take default modes from "ttymodes" property if it exists 1553 */ 1554 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, ddi_root_node(), 0, 1555 "ttymodes", (uchar_t **)&termiosp, &len) == DDI_PROP_SUCCESS) { 1556 1557 if (len == sizeof (struct termios)) { 1558 tp->t_cflag = termiosp->c_cflag; 1559 1560 if (termiosp->c_iflag & (IXON | IXANY)) { 1561 tp->t_iflag = 1562 termiosp->c_iflag & (IXON | IXANY); 1563 tp->t_startc = termiosp->c_cc[VSTART]; 1564 tp->t_stopc = termiosp->c_cc[VSTOP]; 1565 } 1566 } 1567 ddi_prop_free(termiosp); 1568 } 1569 1570 /* 1571 * look for "ignore-cd" or "port-N-ignore-cd" property 1572 */ 1573 (void) sprintf(name, "port-%d-ignore-cd", pp->port_num); 1574 if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1575 "ignore-cd", 0) || 1576 ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, name, 0)) { 1577 pp->port_flags |= USBSER_FL_IGNORE_CD; 1578 } else { 1579 pp->port_flags &= ~USBSER_FL_IGNORE_CD; 1580 } 1581 } 1582 1583 1584 /* 1585 * undo what was done in usbser_open_init() 1586 */ 1587 static void 1588 usbser_open_fini(usbser_port_t *pp) 1589 { 1590 uint_t port_num = pp->port_num; 1591 usbser_state_t *usp = pp->port_usp; 1592 1593 /* 1594 * close DSD if it is open 1595 */ 1596 if (pp->port_flags & USBSER_FL_DSD_OPEN) { 1597 mutex_exit(&pp->port_mutex); 1598 if (USBSER_DS_CLOSE_PORT(usp, port_num) != USB_SUCCESS) { 1599 USB_DPRINTF_L2(DPRINT_CLOSE, pp->port_lh, 1600 "usbser_open_fini: CLOSE_PORT fail"); 1601 } 1602 mutex_enter(&pp->port_mutex); 1603 } 1604 1605 /* 1606 * cancel threads 1607 */ 1608 usbser_thr_cancel(&pp->port_wq_thread); 1609 usbser_thr_cancel(&pp->port_rq_thread); 1610 1611 /* 1612 * unpdate soft state 1613 */ 1614 pp->port_state = USBSER_PORT_CLOSED; 1615 cv_broadcast(&pp->port_state_cv); 1616 cv_broadcast(&pp->port_car_cv); 1617 } 1618 1619 1620 /* 1621 * setup serial line 1622 */ 1623 static int 1624 usbser_open_line_setup(usbser_port_t *pp, int minor, int flag) 1625 { 1626 int rval; 1627 1628 mutex_exit(&pp->port_mutex); 1629 /* 1630 * prevent opening a disconnected device 1631 */ 1632 if (!usbser_dev_is_online(pp->port_usp)) { 1633 mutex_enter(&pp->port_mutex); 1634 1635 return (ENXIO); 1636 } 1637 1638 /* raise DTR on every open */ 1639 (void) USBSER_DS_SET_MODEM_CTL(pp, TIOCM_DTR, TIOCM_DTR); 1640 1641 mutex_enter(&pp->port_mutex); 1642 /* 1643 * check carrier 1644 */ 1645 rval = usbser_open_carrier_check(pp, minor, flag); 1646 1647 return (rval); 1648 } 1649 1650 1651 /* 1652 * check carrier and wait if needed 1653 */ 1654 static int 1655 usbser_open_carrier_check(usbser_port_t *pp, int minor, int flag) 1656 { 1657 tty_common_t *tp = &pp->port_ttycommon; 1658 int val = 0; 1659 int rval; 1660 1661 if (pp->port_flags & USBSER_FL_IGNORE_CD) { 1662 tp->t_flags |= TS_SOFTCAR; 1663 } 1664 1665 /* 1666 * check carrier 1667 */ 1668 if (tp->t_flags & TS_SOFTCAR) { 1669 pp->port_flags |= USBSER_FL_CARR_ON; 1670 } else if (USBSER_DS_GET_MODEM_CTL(pp, TIOCM_CD, &val) != USB_SUCCESS) { 1671 1672 return (ENXIO); 1673 } else if (val & TIOCM_CD) { 1674 pp->port_flags |= USBSER_FL_CARR_ON; 1675 } else { 1676 pp->port_flags &= ~USBSER_FL_CARR_ON; 1677 } 1678 1679 /* 1680 * don't block if 1) not allowed to, 2) this is a local device, 1681 * 3) opening in dial-out mode, or 4) carrier is already on 1682 */ 1683 if ((flag & (FNDELAY | FNONBLOCK)) || (tp->t_cflag & CLOCAL) || 1684 (minor & OUTLINE) || (pp->port_flags & USBSER_FL_CARR_ON)) { 1685 1686 return (USBSER_COMPLETE); 1687 } 1688 1689 /* 1690 * block until carrier up (only in tty mode) 1691 */ 1692 USB_DPRINTF_L4(DPRINT_OPEN, pp->port_lh, 1693 "usbser_open_carrier_check: waiting for carrier..."); 1694 1695 pp->port_flags |= USBSER_FL_WOPEN; 1696 1697 rval = cv_wait_sig(&pp->port_car_cv, &pp->port_mutex); 1698 1699 pp->port_flags &= ~USBSER_FL_WOPEN; 1700 1701 if (rval == 0) { 1702 /* 1703 * interrupted with a signal 1704 */ 1705 return (EINTR); 1706 } else { 1707 /* 1708 * try again 1709 */ 1710 return (USBSER_CONTINUE); 1711 } 1712 } 1713 1714 1715 /* 1716 * during open, setup queues and message processing 1717 */ 1718 static void 1719 usbser_open_queues_init(usbser_port_t *pp, queue_t *rq) 1720 { 1721 pp->port_ttycommon.t_readq = rq; 1722 pp->port_ttycommon.t_writeq = WR(rq); 1723 rq->q_ptr = WR(rq)->q_ptr = (caddr_t)pp; 1724 1725 qprocson(rq); 1726 } 1727 1728 1729 /* 1730 * clean up queues and message processing 1731 */ 1732 static void 1733 usbser_open_queues_fini(usbser_port_t *pp) 1734 { 1735 queue_t *rq = pp->port_ttycommon.t_readq; 1736 1737 mutex_exit(&pp->port_mutex); 1738 /* 1739 * clean up queues 1740 */ 1741 qprocsoff(rq); 1742 1743 /* 1744 * free unused messages 1745 */ 1746 flushq(rq, FLUSHALL); 1747 flushq(WR(rq), FLUSHALL); 1748 1749 rq->q_ptr = WR(rq)->q_ptr = NULL; 1750 ttycommon_close(&pp->port_ttycommon); 1751 mutex_enter(&pp->port_mutex); 1752 } 1753 1754 1755 /* 1756 * during close, wait until pending data is gone or the signal is sent 1757 */ 1758 static void 1759 usbser_close_drain(usbser_port_t *pp) 1760 { 1761 int need_drain; 1762 clock_t until; 1763 int rval; 1764 1765 /* 1766 * port_wq_data_cnt indicates amount of data on the write queue, 1767 * which becomes zero when all data is submitted to DSD. But usbser 1768 * stays busy until it gets tx callback from DSD, signalling that 1769 * data has been sent over USB. To be continued in the next comment... 1770 */ 1771 until = ddi_get_lbolt() + 1772 drv_usectohz(USBSER_WQ_DRAIN_TIMEOUT * 1000000); 1773 1774 while ((pp->port_wq_data_cnt > 0) && USBSER_PORT_IS_BUSY(pp)) { 1775 if ((rval = cv_timedwait_sig(&pp->port_act_cv, &pp->port_mutex, 1776 until)) <= 0) { 1777 1778 break; 1779 } 1780 } 1781 1782 /* don't drain if timed out or received a signal */ 1783 need_drain = (pp->port_wq_data_cnt == 0) || !USBSER_PORT_IS_BUSY(pp) || 1784 (rval != 0); 1785 1786 mutex_exit(&pp->port_mutex); 1787 /* 1788 * Once the data reaches USB serial box, it may still be stored in its 1789 * internal output buffer (FIFO). We call DSD drain to ensure that all 1790 * the data is transmitted transmitted over the serial line. 1791 */ 1792 if (need_drain) { 1793 rval = USBSER_DS_FIFO_DRAIN(pp, USBSER_TX_FIFO_DRAIN_TIMEOUT); 1794 if (rval != USB_SUCCESS) { 1795 (void) USBSER_DS_FIFO_FLUSH(pp, DS_TX); 1796 } 1797 } else { 1798 (void) USBSER_DS_FIFO_FLUSH(pp, DS_TX); 1799 } 1800 mutex_enter(&pp->port_mutex); 1801 } 1802 1803 1804 /* 1805 * during close, cancel break/delay 1806 */ 1807 static void 1808 usbser_close_cancel_break(usbser_port_t *pp) 1809 { 1810 timeout_id_t delay_id; 1811 1812 if (pp->port_act & USBSER_ACT_BREAK) { 1813 delay_id = pp->port_delay_id; 1814 pp->port_delay_id = 0; 1815 1816 mutex_exit(&pp->port_mutex); 1817 (void) untimeout(delay_id); 1818 (void) USBSER_DS_BREAK_CTL(pp, DS_OFF); 1819 mutex_enter(&pp->port_mutex); 1820 1821 pp->port_act &= ~USBSER_ACT_BREAK; 1822 } 1823 } 1824 1825 1826 /* 1827 * during close, drop RTS/DTR if necessary 1828 */ 1829 static void 1830 usbser_close_hangup(usbser_port_t *pp) 1831 { 1832 /* 1833 * drop DTR and RTS if HUPCL is set 1834 */ 1835 if (pp->port_ttycommon.t_cflag & HUPCL) { 1836 mutex_exit(&pp->port_mutex); 1837 (void) USBSER_DS_SET_MODEM_CTL(pp, TIOCM_RTS | TIOCM_DTR, 0); 1838 mutex_enter(&pp->port_mutex); 1839 } 1840 } 1841 1842 1843 /* 1844 * state cleanup during close 1845 */ 1846 static void 1847 usbser_close_cleanup(usbser_port_t *pp) 1848 { 1849 usbser_open_queues_fini(pp); 1850 1851 usbser_open_fini(pp); 1852 } 1853 1854 1855 /* 1856 * 1857 * thread management 1858 * ----------------- 1859 * 1860 * 1861 * dispatch a thread 1862 */ 1863 static void 1864 usbser_thr_dispatch(usbser_thread_t *thr) 1865 { 1866 usbser_port_t *pp = thr->thr_port; 1867 usbser_state_t *usp = pp->port_usp; 1868 int rval; 1869 1870 ASSERT(mutex_owned(&pp->port_mutex)); 1871 ASSERT((thr->thr_flags & USBSER_THR_RUNNING) == 0); 1872 1873 thr->thr_flags = USBSER_THR_RUNNING; 1874 1875 rval = ddi_taskq_dispatch(usp->us_taskq, thr->thr_func, thr->thr_arg, 1876 DDI_SLEEP); 1877 ASSERT(rval == DDI_SUCCESS); 1878 } 1879 1880 1881 /* 1882 * cancel a thread 1883 */ 1884 static void 1885 usbser_thr_cancel(usbser_thread_t *thr) 1886 { 1887 usbser_port_t *pp = thr->thr_port; 1888 1889 ASSERT(mutex_owned(&pp->port_mutex)); 1890 1891 thr->thr_flags &= ~USBSER_THR_RUNNING; 1892 cv_signal(&thr->thr_cv); 1893 1894 /* wait until the thread actually exits */ 1895 do { 1896 cv_wait(&thr->thr_cv, &pp->port_mutex); 1897 1898 } while ((thr->thr_flags & USBSER_THR_EXITED) == 0); 1899 } 1900 1901 1902 /* 1903 * wake thread 1904 */ 1905 static void 1906 usbser_thr_wake(usbser_thread_t *thr) 1907 { 1908 usbser_port_t *pp = thr->thr_port; 1909 1910 ASSERT(mutex_owned(&pp->port_mutex)); 1911 1912 thr->thr_flags |= USBSER_THR_WAKE; 1913 cv_signal(&thr->thr_cv); 1914 } 1915 1916 1917 /* 1918 * thread handling write queue requests 1919 */ 1920 static void 1921 usbser_wq_thread(void *arg) 1922 { 1923 usbser_thread_t *thr = (usbser_thread_t *)arg; 1924 usbser_port_t *pp = thr->thr_port; 1925 1926 USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wq_thread: enter"); 1927 1928 mutex_enter(&pp->port_mutex); 1929 while (thr->thr_flags & USBSER_THR_RUNNING) { 1930 /* 1931 * when woken, see what we should do 1932 */ 1933 if (thr->thr_flags & USBSER_THR_WAKE) { 1934 thr->thr_flags &= ~USBSER_THR_WAKE; 1935 1936 /* 1937 * status callback pending? 1938 */ 1939 if (pp->port_flags & USBSER_FL_STATUS_CB) { 1940 usbser_status_proc_cb(pp); 1941 } 1942 1943 usbser_wmsg(pp); 1944 } else { 1945 /* 1946 * sleep until woken up to do some work, e.g: 1947 * - new message arrives; 1948 * - data transmit completes; 1949 * - status callback pending; 1950 * - wq thread is cancelled; 1951 */ 1952 cv_wait(&thr->thr_cv, &pp->port_mutex); 1953 USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, 1954 "usbser_wq_thread: wakeup"); 1955 } 1956 } 1957 thr->thr_flags |= USBSER_THR_EXITED; 1958 cv_signal(&thr->thr_cv); 1959 USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wq_thread: exit"); 1960 mutex_exit(&pp->port_mutex); 1961 } 1962 1963 1964 /* 1965 * thread handling read queue requests 1966 */ 1967 static void 1968 usbser_rq_thread(void *arg) 1969 { 1970 usbser_thread_t *thr = (usbser_thread_t *)arg; 1971 usbser_port_t *pp = thr->thr_port; 1972 1973 USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_rq_thread: enter"); 1974 1975 mutex_enter(&pp->port_mutex); 1976 while (thr->thr_flags & USBSER_THR_RUNNING) { 1977 /* 1978 * read service routine will wake us when 1979 * more space is available on the read queue 1980 */ 1981 if (thr->thr_flags & USBSER_THR_WAKE) { 1982 thr->thr_flags &= ~USBSER_THR_WAKE; 1983 1984 /* 1985 * don't process messages until queue is enabled 1986 */ 1987 if (!pp->port_ttycommon.t_readq) { 1988 1989 continue; 1990 } 1991 1992 /* 1993 * check whether we need to resume receive 1994 */ 1995 if (pp->port_flags & USBSER_FL_RX_STOPPED) { 1996 pp->port_flowc = pp->port_ttycommon.t_startc; 1997 usbser_inbound_flow_ctl(pp); 1998 } 1999 2000 /* 2001 * grab more data if available 2002 */ 2003 mutex_exit(&pp->port_mutex); 2004 usbser_rx_cb((caddr_t)pp); 2005 mutex_enter(&pp->port_mutex); 2006 } else { 2007 cv_wait(&thr->thr_cv, &pp->port_mutex); 2008 USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, 2009 "usbser_rq_thread: wakeup"); 2010 } 2011 } 2012 thr->thr_flags |= USBSER_THR_EXITED; 2013 cv_signal(&thr->thr_cv); 2014 USB_DPRINTF_L4(DPRINT_RQ, pp->port_lh, "usbser_rq_thread: exit"); 2015 mutex_exit(&pp->port_mutex); 2016 } 2017 2018 2019 /* 2020 * DSD callbacks 2021 * ------------- 2022 * 2023 * Note: to avoid deadlocks with DSD, these callbacks 2024 * should not call DSD functions that can block. 2025 * 2026 * 2027 * transmit callback 2028 * 2029 * invoked by DSD when the last byte of data is transmitted over USB 2030 */ 2031 static void 2032 usbser_tx_cb(caddr_t arg) 2033 { 2034 usbser_port_t *pp = (usbser_port_t *)arg; 2035 int online; 2036 2037 online = usbser_dev_is_online(pp->port_usp); 2038 2039 mutex_enter(&pp->port_mutex); 2040 USB_DPRINTF_L4(DPRINT_TX_CB, pp->port_lh, 2041 "usbser_tx_cb: act=%x curthread=%p", pp->port_act, 2042 (void *)curthread); 2043 2044 usbser_release_port_act(pp, USBSER_ACT_TX); 2045 2046 if (online && USBSER_PORT_ACCESS_OK(pp) && !USBSER_PORT_IS_BUSY(pp)) { 2047 /* 2048 * wake wq thread for further data/ioctl processing 2049 */ 2050 usbser_thr_wake(&pp->port_wq_thread); 2051 } 2052 mutex_exit(&pp->port_mutex); 2053 } 2054 2055 2056 /* 2057 * receive callback 2058 * 2059 * invoked by DSD when there is more data for us to pick 2060 */ 2061 static void 2062 usbser_rx_cb(caddr_t arg) 2063 { 2064 usbser_port_t *pp = (usbser_port_t *)arg; 2065 queue_t *rq, *wq; 2066 mblk_t *mp; /* current mblk */ 2067 mblk_t *data, *data_tail; /* M_DATA mblk list and its tail */ 2068 mblk_t *emp; /* error (M_BREAK) mblk */ 2069 2070 USB_DPRINTF_L4(DPRINT_RX_CB, pp->port_lh, "usbser_rx_cb"); 2071 2072 if (!usbser_dev_is_online(pp->port_usp)) { 2073 2074 return; 2075 } 2076 2077 /* get data from DSD */ 2078 if ((mp = USBSER_DS_RX(pp)) == NULL) { 2079 2080 return; 2081 } 2082 2083 mutex_enter(&pp->port_mutex); 2084 if ((!USBSER_PORT_ACCESS_OK(pp)) || 2085 ((pp->port_ttycommon.t_cflag & CREAD) == 0)) { 2086 freemsg(mp); 2087 mutex_exit(&pp->port_mutex); 2088 USB_DPRINTF_L3(DPRINT_RX_CB, pp->port_lh, 2089 "usbser_rx_cb: access not ok or receiver disabled"); 2090 2091 return; 2092 } 2093 2094 usbser_serialize_port_act(pp, USBSER_ACT_RX); 2095 2096 rq = pp->port_ttycommon.t_readq; 2097 wq = pp->port_ttycommon.t_writeq; 2098 mutex_exit(&pp->port_mutex); 2099 2100 /* 2101 * DSD data is a b_cont-linked list of M_DATA and M_BREAK blocks. 2102 * M_DATA is correctly received data. 2103 * M_BREAK is a character with either framing or parity error. 2104 * 2105 * this loop runs through the list of mblks. when it meets an M_BREAK, 2106 * it sends all leading M_DATA's in one shot, then sends M_BREAK. 2107 * in the trivial case when list contains only M_DATA's, the loop 2108 * does nothing but set data variable. 2109 */ 2110 data = data_tail = NULL; 2111 while (mp) { 2112 /* 2113 * skip data until we meet M_BREAK or end of list 2114 */ 2115 if (DB_TYPE(mp) == M_DATA) { 2116 if (data == NULL) { 2117 data = mp; 2118 } 2119 data_tail = mp; 2120 mp = mp->b_cont; 2121 2122 continue; 2123 } 2124 2125 /* detach data list from mp */ 2126 if (data_tail) { 2127 data_tail->b_cont = NULL; 2128 } 2129 /* detach emp from the list */ 2130 emp = mp; 2131 mp = mp->b_cont; 2132 emp->b_cont = NULL; 2133 2134 /* DSD shouldn't send anything but M_DATA or M_BREAK */ 2135 if ((DB_TYPE(emp) != M_BREAK) || (MBLKL(emp) != 2)) { 2136 freemsg(emp); 2137 USB_DPRINTF_L2(DPRINT_RX_CB, pp->port_lh, 2138 "usbser_rx_cb: bad message"); 2139 2140 continue; 2141 } 2142 2143 /* 2144 * first tweak and send M_DATA's 2145 */ 2146 if (data) { 2147 usbser_rx_massage_data(pp, data); 2148 usbser_rx_cb_put(pp, rq, wq, data); 2149 data = data_tail = NULL; 2150 } 2151 2152 /* 2153 * now tweak and send M_BREAK 2154 */ 2155 mutex_enter(&pp->port_mutex); 2156 usbser_rx_massage_mbreak(pp, emp); 2157 mutex_exit(&pp->port_mutex); 2158 usbser_rx_cb_put(pp, rq, wq, emp); 2159 } 2160 2161 /* send the rest of the data, if any */ 2162 if (data) { 2163 usbser_rx_massage_data(pp, data); 2164 usbser_rx_cb_put(pp, rq, wq, data); 2165 } 2166 2167 mutex_enter(&pp->port_mutex); 2168 usbser_release_port_act(pp, USBSER_ACT_RX); 2169 mutex_exit(&pp->port_mutex); 2170 } 2171 2172 /* 2173 * the joys of termio -- this is to accomodate Unix98 assertion: 2174 * 2175 * If PARENB is supported and is set, when PARMRK is set, and CSIZE is 2176 * set to CS8, and IGNPAR is clear, and ISTRIP is clear, a valid 2177 * character of '\377' is read as '\377', '\377'. 2178 * 2179 * Posix Ref: Assertion 7.1.2.2-16(C) 2180 * 2181 * this requires the driver to scan every incoming valid character 2182 */ 2183 static void 2184 usbser_rx_massage_data(usbser_port_t *pp, mblk_t *mp) 2185 { 2186 tty_common_t *tp = &pp->port_ttycommon; 2187 uchar_t *p; 2188 mblk_t *newmp; 2189 int tailsz; 2190 2191 /* avoid scanning if possible */ 2192 mutex_enter(&pp->port_mutex); 2193 if (!((tp->t_cflag & PARENB) && (tp->t_iflag & PARMRK) && 2194 ((tp->t_cflag & CSIZE) == CS8) && 2195 ((tp->t_iflag & (IGNPAR|ISTRIP)) == 0))) { 2196 mutex_exit(&pp->port_mutex); 2197 2198 return; 2199 } 2200 mutex_exit(&pp->port_mutex); 2201 2202 while (mp) { 2203 for (p = mp->b_rptr; p < mp->b_wptr; ) { 2204 if (*p++ != 0377) { 2205 2206 continue; 2207 } 2208 USB_DPRINTF_L4(DPRINT_RX_CB, pp->port_lh, 2209 "usbser_rx_massage_data: mp=%p off=%ld(%ld)", 2210 (void *)mp, (long)(p - mp->b_rptr - 1), 2211 (long)MBLKL(mp)); 2212 2213 /* 2214 * insert another 0377 after this one. all data after 2215 * the original 0377 have to be copied to the new mblk 2216 */ 2217 tailsz = mp->b_wptr - p; 2218 if ((newmp = allocb(tailsz + 1, BPRI_HI)) == NULL) { 2219 USB_DPRINTF_L2(DPRINT_RX_CB, pp->port_lh, 2220 "usbser_rx_massage_data: allocb failed"); 2221 2222 continue; 2223 } 2224 2225 /* fill in the new mblk */ 2226 *newmp->b_wptr++ = 0377; 2227 if (tailsz > 0) { 2228 bcopy(p, newmp->b_wptr, tailsz); 2229 newmp->b_wptr += tailsz; 2230 } 2231 /* shrink the original mblk */ 2232 mp->b_wptr = p; 2233 2234 newmp->b_cont = mp->b_cont; 2235 mp->b_cont = newmp; 2236 p = newmp->b_rptr + 1; 2237 mp = newmp; 2238 } 2239 mp = mp->b_cont; 2240 } 2241 } 2242 2243 /* 2244 * more joys of termio 2245 */ 2246 static void 2247 usbser_rx_massage_mbreak(usbser_port_t *pp, mblk_t *mp) 2248 { 2249 tty_common_t *tp = &pp->port_ttycommon; 2250 uchar_t err, c; 2251 2252 err = *mp->b_rptr; 2253 c = *(mp->b_rptr + 1); 2254 2255 if ((err & (DS_FRAMING_ERR | DS_BREAK_ERR)) && (c == 0)) { 2256 /* break */ 2257 mp->b_rptr += 2; 2258 } else if (!(tp->t_iflag & INPCK) && (err & (DS_PARITY_ERR))) { 2259 /* Posix Ref: Assertion 7.1.2.2-20(C) */ 2260 mp->b_rptr++; 2261 DB_TYPE(mp) = M_DATA; 2262 } else { 2263 /* for ldterm to handle */ 2264 mp->b_rptr++; 2265 } 2266 2267 USB_DPRINTF_L4(DPRINT_RX_CB, pp->port_lh, 2268 "usbser_rx_massage_mbreak: type=%x len=%ld [0]=0%o", 2269 DB_TYPE(mp), (long)MBLKL(mp), (MBLKL(mp) > 0) ? *mp->b_rptr : 45); 2270 } 2271 2272 2273 /* 2274 * in rx callback, try to send an mblk upstream 2275 */ 2276 static void 2277 usbser_rx_cb_put(usbser_port_t *pp, queue_t *rq, queue_t *wq, mblk_t *mp) 2278 { 2279 if (canputnext(rq)) { 2280 putnext(rq, mp); 2281 } else if (canput(rq) && putq(rq, mp)) { 2282 /* 2283 * full queue indicates the need for inbound flow control 2284 */ 2285 (void) putctl(wq, M_STOPI); 2286 usbser_st_put_stopi++; 2287 2288 USB_DPRINTF_L3(DPRINT_RX_CB, pp->port_lh, 2289 "usbser_rx_cb: cannot putnext, flow ctl"); 2290 } else { 2291 freemsg(mp); 2292 usbser_st_rx_data_loss++; 2293 (void) putctl(wq, M_STOPI); 2294 usbser_st_put_stopi++; 2295 2296 USB_DPRINTF_L1(DPRINT_RX_CB, pp->port_lh, 2297 "input overrun"); 2298 } 2299 } 2300 2301 2302 /* 2303 * modem status change callback 2304 * 2305 * each time external status lines are changed, DSD calls this routine 2306 */ 2307 static void 2308 usbser_status_cb(caddr_t arg) 2309 { 2310 usbser_port_t *pp = (usbser_port_t *)arg; 2311 2312 USB_DPRINTF_L4(DPRINT_STATUS_CB, pp->port_lh, "usbser_status_cb"); 2313 2314 if (!usbser_dev_is_online(pp->port_usp)) { 2315 2316 return; 2317 } 2318 2319 /* 2320 * actual processing will be done in usbser_status_proc_cb() 2321 * running in wq thread 2322 */ 2323 mutex_enter(&pp->port_mutex); 2324 if (USBSER_PORT_ACCESS_OK(pp) || USBSER_IS_OPENING(pp)) { 2325 pp->port_flags |= USBSER_FL_STATUS_CB; 2326 usbser_thr_wake(&pp->port_wq_thread); 2327 } 2328 mutex_exit(&pp->port_mutex); 2329 } 2330 2331 2332 /* 2333 * modem status change 2334 */ 2335 static void 2336 usbser_status_proc_cb(usbser_port_t *pp) 2337 { 2338 tty_common_t *tp = &pp->port_ttycommon; 2339 queue_t *rq, *wq; 2340 int status; 2341 int drop_dtr = 0; 2342 int rq_msg = 0, wq_msg = 0; 2343 2344 USB_DPRINTF_L4(DPRINT_STATUS_CB, pp->port_lh, "usbser_status_proc_cb"); 2345 2346 pp->port_flags &= ~USBSER_FL_STATUS_CB; 2347 2348 mutex_exit(&pp->port_mutex); 2349 if (!usbser_dev_is_online(pp->port_usp)) { 2350 mutex_enter(&pp->port_mutex); 2351 2352 return; 2353 } 2354 2355 /* get modem status */ 2356 if (USBSER_DS_GET_MODEM_CTL(pp, -1, &status) != USB_SUCCESS) { 2357 mutex_enter(&pp->port_mutex); 2358 2359 return; 2360 } 2361 2362 mutex_enter(&pp->port_mutex); 2363 usbser_serialize_port_act(pp, USBSER_ACT_CTL); 2364 2365 rq = pp->port_ttycommon.t_readq; 2366 wq = pp->port_ttycommon.t_writeq; 2367 2368 /* 2369 * outbound flow control 2370 */ 2371 if (tp->t_cflag & CRTSCTS) { 2372 if (!(status & TIOCM_CTS)) { 2373 /* 2374 * CTS dropped, stop xmit 2375 */ 2376 if (!(pp->port_flags & USBSER_FL_TX_STOPPED)) { 2377 wq_msg = M_STOP; 2378 } 2379 } else if (pp->port_flags & USBSER_FL_TX_STOPPED) { 2380 /* 2381 * CTS raised, resume xmit 2382 */ 2383 wq_msg = M_START; 2384 } 2385 } 2386 2387 /* 2388 * check carrier 2389 */ 2390 if ((status & TIOCM_CD) || (tp->t_flags & TS_SOFTCAR)) { 2391 /* 2392 * carrier present 2393 */ 2394 if ((pp->port_flags & USBSER_FL_CARR_ON) == 0) { 2395 pp->port_flags |= USBSER_FL_CARR_ON; 2396 2397 rq_msg = M_UNHANGUP; 2398 /* 2399 * wake open 2400 */ 2401 if (pp->port_flags & USBSER_FL_WOPEN) { 2402 cv_broadcast(&pp->port_car_cv); 2403 } 2404 2405 USB_DPRINTF_L4(DPRINT_STATUS_CB, pp->port_lh, 2406 "usbser_status_cb: carr on"); 2407 } 2408 } else if (pp->port_flags & USBSER_FL_CARR_ON) { 2409 pp->port_flags &= ~USBSER_FL_CARR_ON; 2410 /* 2411 * carrier went away: if not local line, drop DTR 2412 */ 2413 if (!(tp->t_cflag & CLOCAL)) { 2414 drop_dtr = 1; 2415 rq_msg = M_HANGUP; 2416 } 2417 if ((pp->port_flags & USBSER_FL_TX_STOPPED) && (wq_msg == 0)) { 2418 wq_msg = M_START; 2419 } 2420 2421 USB_DPRINTF_L4(DPRINT_STATUS_CB, pp->port_lh, 2422 "usbser_status_cb: carr off"); 2423 } 2424 mutex_exit(&pp->port_mutex); 2425 2426 USB_DPRINTF_L4(DPRINT_STATUS_CB, pp->port_lh, 2427 "usbser_status_cb: rq_msg=%d wq_msg=%d", rq_msg, wq_msg); 2428 2429 /* 2430 * commit postponed actions now 2431 * do so only if port is fully open (queues are enabled) 2432 */ 2433 if (rq) { 2434 if (rq_msg) { 2435 (void) putnextctl(rq, rq_msg); 2436 } 2437 if (drop_dtr) { 2438 (void) USBSER_DS_SET_MODEM_CTL(pp, TIOCM_DTR, 0); 2439 } 2440 if (wq_msg) { 2441 (void) putctl(wq, wq_msg); 2442 } 2443 } 2444 2445 mutex_enter(&pp->port_mutex); 2446 usbser_release_port_act(pp, USBSER_ACT_CTL); 2447 } 2448 2449 2450 /* 2451 * serial support 2452 * -------------- 2453 * 2454 * 2455 * this routine is run by wq thread every time it's woken, 2456 * i.e. when the queue contains messages to process 2457 */ 2458 static void 2459 usbser_wmsg(usbser_port_t *pp) 2460 { 2461 queue_t *q = pp->port_ttycommon.t_writeq; 2462 mblk_t *mp; 2463 int msgtype; 2464 2465 ASSERT(mutex_owned(&pp->port_mutex)); 2466 2467 if (q == NULL) { 2468 USB_DPRINTF_L3(DPRINT_WQ, pp->port_lh, "usbser_wmsg: q=NULL"); 2469 2470 return; 2471 } 2472 USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wmsg: q=%p act=%x 0x%x", 2473 (void *)q, pp->port_act, q->q_first ? DB_TYPE(q->q_first) : 0xff); 2474 2475 while ((mp = getq(q)) != NULL) { 2476 msgtype = DB_TYPE(mp); 2477 USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wmsg: " 2478 "type=%s (0x%x)", usbser_msgtype2str(msgtype), msgtype); 2479 2480 switch (msgtype) { 2481 /* 2482 * high-priority messages 2483 */ 2484 case M_STOP: 2485 usbser_stop(pp, mp); 2486 2487 break; 2488 case M_START: 2489 usbser_start(pp, mp); 2490 2491 break; 2492 case M_STOPI: 2493 usbser_stopi(pp, mp); 2494 2495 break; 2496 case M_STARTI: 2497 usbser_starti(pp, mp); 2498 2499 break; 2500 case M_IOCDATA: 2501 usbser_iocdata(pp, mp); 2502 2503 break; 2504 case M_FLUSH: 2505 usbser_flush(pp, mp); 2506 2507 break; 2508 /* 2509 * normal-priority messages 2510 */ 2511 case M_BREAK: 2512 usbser_break(pp, mp); 2513 2514 break; 2515 case M_DELAY: 2516 usbser_delay(pp, mp); 2517 2518 break; 2519 case M_DATA: 2520 if (usbser_data(pp, mp) != USB_SUCCESS) { 2521 (void) putbq(q, mp); 2522 2523 return; 2524 } 2525 2526 break; 2527 case M_IOCTL: 2528 if (usbser_ioctl(pp, mp) != USB_SUCCESS) { 2529 (void) putbq(q, mp); 2530 2531 return; 2532 } 2533 2534 break; 2535 default: 2536 freemsg(mp); 2537 2538 break; 2539 } 2540 } 2541 } 2542 2543 2544 /* 2545 * process M_DATA message 2546 */ 2547 static int 2548 usbser_data(usbser_port_t *pp, mblk_t *mp) 2549 { 2550 /* put off until current transfer ends or delay is over */ 2551 if ((pp->port_act & USBSER_ACT_TX) || 2552 (pp->port_act & USBSER_ACT_DELAY)) { 2553 2554 return (USB_FAILURE); 2555 } 2556 if (MBLKL(mp) <= 0) { 2557 freemsg(mp); 2558 2559 return (USB_SUCCESS); 2560 } 2561 2562 pp->port_act |= USBSER_ACT_TX; 2563 pp->port_wq_data_cnt -= msgdsize(mp); 2564 2565 mutex_exit(&pp->port_mutex); 2566 /* DSD is required to accept data block in any case */ 2567 (void) USBSER_DS_TX(pp, mp); 2568 mutex_enter(&pp->port_mutex); 2569 2570 return (USB_SUCCESS); 2571 } 2572 2573 2574 /* 2575 * process an M_IOCTL message 2576 */ 2577 static int 2578 usbser_ioctl(usbser_port_t *pp, mblk_t *mp) 2579 { 2580 tty_common_t *tp = &pp->port_ttycommon; 2581 queue_t *q = tp->t_writeq; 2582 struct iocblk *iocp; 2583 int cmd; 2584 mblk_t *datamp; 2585 int error = 0, rval; 2586 int val; 2587 2588 ASSERT(mutex_owned(&pp->port_mutex)); 2589 ASSERT(DB_TYPE(mp) == M_IOCTL); 2590 2591 iocp = (struct iocblk *)mp->b_rptr; 2592 cmd = iocp->ioc_cmd; 2593 2594 USB_DPRINTF_L4(DPRINT_IOCTL, pp->port_lh, "usbser_ioctl: " 2595 "mp=%p %s (0x%x)", (void *)mp, usbser_ioctl2str(cmd), cmd); 2596 2597 if (tp->t_iocpending != NULL) { 2598 /* 2599 * We were holding an ioctl response pending the 2600 * availability of an mblk to hold data to be passed up; 2601 * another ioctl came through, which means that ioctl 2602 * must have timed out or been aborted. 2603 */ 2604 freemsg(tp->t_iocpending); 2605 tp->t_iocpending = NULL; 2606 } 2607 2608 switch (cmd) { 2609 case TIOCMGET: 2610 case TIOCMBIC: 2611 case TIOCMBIS: 2612 case TIOCMSET: 2613 case CONSOPENPOLLEDIO: 2614 case CONSCLOSEPOLLEDIO: 2615 case CONSSETABORTENABLE: 2616 case CONSGETABORTENABLE: 2617 /* 2618 * For the above ioctls do not call ttycommon_ioctl() because 2619 * this function frees up the message block (mp->b_cont) that 2620 * contains the address of the user variable where we need to 2621 * pass back the bit array. 2622 */ 2623 error = -1; 2624 usbser_serialize_port_act(pp, USBSER_ACT_CTL); 2625 mutex_exit(&pp->port_mutex); 2626 2627 break; 2628 case TCSBRK: 2629 /* serialize breaks */ 2630 if (pp->port_act & USBSER_ACT_BREAK) { 2631 2632 return (USB_FAILURE); 2633 } 2634 default: 2635 usbser_serialize_port_act(pp, USBSER_ACT_CTL); 2636 mutex_exit(&pp->port_mutex); 2637 (void) ttycommon_ioctl(tp, q, mp, &error); 2638 } 2639 2640 if (error == 0) { 2641 /* 2642 * ttycommon_ioctl() did most of the work 2643 * we just use the data it set up 2644 */ 2645 switch (cmd) { 2646 case TCSETSF: 2647 case TCSETSW: 2648 case TCSETA: 2649 case TCSETAW: 2650 case TCSETAF: 2651 (void) USBSER_DS_FIFO_DRAIN(pp, DS_TX); 2652 2653 /* FALLTHRU */ 2654 case TCSETS: 2655 mutex_enter(&pp->port_mutex); 2656 error = usbser_port_program(pp); 2657 mutex_exit(&pp->port_mutex); 2658 2659 break; 2660 } 2661 2662 goto end; 2663 } else if (error > 0) { 2664 USB_DPRINTF_L3(DPRINT_IOCTL, pp->port_lh, "usbser_ioctl: " 2665 "ttycommon_ioctl returned %d", error); 2666 2667 goto end; 2668 } 2669 2670 /* 2671 * error < 0: ttycommon_ioctl() didn't do anything, we process it here 2672 */ 2673 error = 0; 2674 switch (cmd) { 2675 case TCSBRK: 2676 if ((error = miocpullup(mp, sizeof (int))) != 0) { 2677 2678 break; 2679 } 2680 /* drain output */ 2681 (void) USBSER_DS_FIFO_DRAIN(pp, USBSER_TX_FIFO_DRAIN_TIMEOUT); 2682 /* 2683 * if required, set break 2684 */ 2685 if (*(int *)mp->b_cont->b_rptr == 0) { 2686 if (USBSER_DS_BREAK_CTL(pp, DS_ON) != USB_SUCCESS) { 2687 error = EIO; 2688 2689 break; 2690 } 2691 mutex_enter(&pp->port_mutex); 2692 pp->port_act |= USBSER_ACT_BREAK; 2693 pp->port_delay_id = timeout(usbser_restart, pp, 2694 drv_usectohz(250000)); 2695 mutex_exit(&pp->port_mutex); 2696 } 2697 2698 break; 2699 case TIOCSBRK: 2700 /* set break */ 2701 if (USBSER_DS_BREAK_CTL(pp, DS_ON) != USB_SUCCESS) { 2702 error = EIO; 2703 } 2704 2705 break; 2706 case TIOCCBRK: 2707 /* clear break */ 2708 if (USBSER_DS_BREAK_CTL(pp, DS_OFF) != USB_SUCCESS) { 2709 error = EIO; 2710 } 2711 2712 break; 2713 case TIOCMSET: 2714 case TIOCMBIS: 2715 case TIOCMBIC: 2716 if (iocp->ioc_count == TRANSPARENT) { 2717 mcopyin(mp, NULL, sizeof (int), NULL); 2718 2719 break; 2720 } 2721 if ((error = miocpullup(mp, sizeof (int))) != 0) { 2722 2723 break; 2724 } 2725 2726 val = *(int *)mp->b_cont->b_rptr; 2727 if (cmd == TIOCMSET) { 2728 rval = USBSER_DS_SET_MODEM_CTL(pp, -1, val); 2729 } else if (cmd == TIOCMBIS) { 2730 rval = USBSER_DS_SET_MODEM_CTL(pp, val, -1); 2731 } else if (cmd == TIOCMBIC) { 2732 rval = USBSER_DS_SET_MODEM_CTL(pp, val, 0); 2733 } 2734 if (rval != USB_SUCCESS) { 2735 error = EIO; 2736 } 2737 2738 break; 2739 case (tIOC | 109): /* TIOCSILOOP */ 2740 if (USBSER_DS_LOOPBACK_SUPPORTED(pp)) { 2741 if (USBSER_DS_LOOPBACK(pp, DS_ON) != USB_SUCCESS) { 2742 error = EIO; 2743 } else { 2744 iocp->ioc_error = 0; 2745 mp->b_datap->db_type = M_IOCACK; 2746 } 2747 } else { 2748 error = EINVAL; 2749 } 2750 2751 break; 2752 case (tIOC | 108): /* TIOCCILOOP */ 2753 if (USBSER_DS_LOOPBACK_SUPPORTED(pp)) { 2754 if (USBSER_DS_LOOPBACK(pp, DS_OFF) != USB_SUCCESS) { 2755 error = EIO; 2756 } else { 2757 iocp->ioc_error = 0; 2758 mp->b_datap->db_type = M_IOCACK; 2759 } 2760 } else { 2761 error = EINVAL; 2762 } 2763 2764 break; 2765 case TIOCMGET: 2766 datamp = allocb(sizeof (int), BPRI_MED); 2767 if (datamp == NULL) { 2768 error = EAGAIN; 2769 2770 break; 2771 } 2772 2773 rval = USBSER_DS_GET_MODEM_CTL(pp, -1, (int *)datamp->b_rptr); 2774 if (rval != USB_SUCCESS) { 2775 error = EIO; 2776 2777 break; 2778 } 2779 2780 if (iocp->ioc_count == TRANSPARENT) { 2781 mcopyout(mp, NULL, sizeof (int), NULL, datamp); 2782 } else { 2783 if (mp->b_cont != NULL) { 2784 freemsg(mp->b_cont); 2785 } 2786 mp->b_cont = datamp; 2787 mp->b_cont->b_wptr += sizeof (int); 2788 iocp->ioc_count = sizeof (int); 2789 } 2790 2791 break; 2792 case CONSOPENPOLLEDIO: 2793 error = usbser_polledio_init(pp); 2794 if (error != 0) 2795 2796 break; 2797 2798 error = miocpullup(mp, sizeof (struct cons_polledio *)); 2799 if (error != 0) 2800 2801 break; 2802 2803 *(struct cons_polledio **)mp->b_cont->b_rptr = &usbser_polledio; 2804 2805 mp->b_datap->db_type = M_IOCACK; 2806 2807 break; 2808 case CONSCLOSEPOLLEDIO: 2809 usbser_polledio_fini(pp); 2810 mp->b_datap->db_type = M_IOCACK; 2811 mp->b_datap->db_type = M_IOCACK; 2812 iocp->ioc_error = 0; 2813 iocp->ioc_rval = 0; 2814 2815 break; 2816 case CONSSETABORTENABLE: 2817 error = secpolicy_console(iocp->ioc_cr); 2818 if (error != 0) 2819 2820 break; 2821 2822 if (iocp->ioc_count != TRANSPARENT) { 2823 error = EINVAL; 2824 2825 break; 2826 } 2827 2828 /* 2829 * To do: implement console abort support 2830 * This involves adding a console flag to usbser 2831 * state structure. If flag is set, parse input stream 2832 * for abort sequence (see asy for example). 2833 * 2834 * For now, run mdb -K to get kmdb prompt. 2835 */ 2836 if (*(intptr_t *)mp->b_cont->b_rptr) 2837 usbser_console_abort = 1; 2838 else 2839 usbser_console_abort = 0; 2840 2841 mp->b_datap->db_type = M_IOCACK; 2842 iocp->ioc_error = 0; 2843 iocp->ioc_rval = 0; 2844 2845 break; 2846 case CONSGETABORTENABLE: 2847 /*CONSTANTCONDITION*/ 2848 ASSERT(sizeof (boolean_t) <= sizeof (boolean_t *)); 2849 /* 2850 * Store the return value right in the payload 2851 * we were passed. Crude. 2852 */ 2853 mcopyout(mp, NULL, sizeof (boolean_t), NULL, NULL); 2854 *(boolean_t *)mp->b_cont->b_rptr = (usbser_console_abort != 0); 2855 2856 break; 2857 default: 2858 error = EINVAL; 2859 2860 break; 2861 } 2862 end: 2863 if (error != 0) { 2864 iocp->ioc_error = error; 2865 mp->b_datap->db_type = M_IOCNAK; 2866 } 2867 qreply(q, mp); 2868 2869 mutex_enter(&pp->port_mutex); 2870 usbser_release_port_act(pp, USBSER_ACT_CTL); 2871 2872 return (USB_SUCCESS); 2873 } 2874 2875 2876 /* 2877 * process M_IOCDATA message 2878 */ 2879 static void 2880 usbser_iocdata(usbser_port_t *pp, mblk_t *mp) 2881 { 2882 tty_common_t *tp = &pp->port_ttycommon; 2883 queue_t *q = tp->t_writeq; 2884 struct iocblk *ip; 2885 struct copyresp *csp; 2886 int cmd; 2887 int val; 2888 int rval; 2889 2890 ASSERT(mutex_owned(&pp->port_mutex)); 2891 2892 ip = (struct iocblk *)mp->b_rptr; 2893 csp = (struct copyresp *)mp->b_rptr; 2894 cmd = csp->cp_cmd; 2895 2896 if (csp->cp_rval != 0) { 2897 freemsg(mp); 2898 2899 return; 2900 } 2901 2902 switch (cmd) { 2903 case TIOCMSET: 2904 case TIOCMBIS: 2905 case TIOCMBIC: 2906 if ((mp->b_cont == NULL) || 2907 (MBLKL(mp->b_cont) < sizeof (int))) { 2908 miocnak(q, mp, 0, EINVAL); 2909 2910 break; 2911 } 2912 val = *(int *)mp->b_cont->b_rptr; 2913 2914 usbser_serialize_port_act(pp, USBSER_ACT_CTL); 2915 2916 mutex_exit(&pp->port_mutex); 2917 if (cmd == TIOCMSET) { 2918 rval = USBSER_DS_SET_MODEM_CTL(pp, -1, val); 2919 } else if (cmd == TIOCMBIS) { 2920 rval = USBSER_DS_SET_MODEM_CTL(pp, val, -1); 2921 } else if (cmd == TIOCMBIC) { 2922 rval = USBSER_DS_SET_MODEM_CTL(pp, val, 0); 2923 } 2924 2925 if (mp->b_cont) { 2926 freemsg(mp->b_cont); 2927 mp->b_cont = NULL; 2928 } 2929 ip->ioc_rval = 0; 2930 if (rval == USB_SUCCESS) { 2931 miocack(q, mp, 0, 0); 2932 } else { 2933 miocnak(q, mp, 0, EIO); 2934 } 2935 mutex_enter(&pp->port_mutex); 2936 2937 usbser_release_port_act(pp, USBSER_ACT_CTL); 2938 2939 break; 2940 case TIOCMGET: 2941 mutex_exit(&pp->port_mutex); 2942 if (mp->b_cont) { 2943 freemsg(mp->b_cont); 2944 mp->b_cont = NULL; 2945 } 2946 ip->ioc_rval = 0; 2947 miocack(q, mp, 0, 0); 2948 mutex_enter(&pp->port_mutex); 2949 2950 break; 2951 default: 2952 mutex_exit(&pp->port_mutex); 2953 miocnak(q, mp, 0, EINVAL); 2954 mutex_enter(&pp->port_mutex); 2955 2956 break; 2957 } 2958 } 2959 2960 2961 /* 2962 * handle M_START[I]/M_STOP[I] messages 2963 */ 2964 static void 2965 usbser_stop(usbser_port_t *pp, mblk_t *mp) 2966 { 2967 usbser_st_mstop++; 2968 if (!(pp->port_flags & USBSER_FL_TX_STOPPED)) { 2969 usbser_serialize_port_act(pp, USBSER_ACT_CTL); 2970 pp->port_flags |= USBSER_FL_TX_STOPPED; 2971 2972 mutex_exit(&pp->port_mutex); 2973 USBSER_DS_STOP(pp, DS_TX); 2974 mutex_enter(&pp->port_mutex); 2975 2976 usbser_release_port_act(pp, USBSER_ACT_TX); 2977 usbser_release_port_act(pp, USBSER_ACT_CTL); 2978 } 2979 freemsg(mp); 2980 } 2981 2982 2983 static void 2984 usbser_start(usbser_port_t *pp, mblk_t *mp) 2985 { 2986 usbser_st_mstart++; 2987 if (pp->port_flags & USBSER_FL_TX_STOPPED) { 2988 usbser_serialize_port_act(pp, USBSER_ACT_CTL); 2989 pp->port_flags &= ~USBSER_FL_TX_STOPPED; 2990 2991 mutex_exit(&pp->port_mutex); 2992 USBSER_DS_START(pp, DS_TX); 2993 mutex_enter(&pp->port_mutex); 2994 usbser_release_port_act(pp, USBSER_ACT_CTL); 2995 } 2996 freemsg(mp); 2997 } 2998 2999 3000 static void 3001 usbser_stopi(usbser_port_t *pp, mblk_t *mp) 3002 { 3003 usbser_st_mstopi++; 3004 usbser_serialize_port_act(pp, USBSER_ACT_CTL); 3005 pp->port_flowc = pp->port_ttycommon.t_stopc; 3006 usbser_inbound_flow_ctl(pp); 3007 usbser_release_port_act(pp, USBSER_ACT_CTL); 3008 freemsg(mp); 3009 } 3010 3011 static void 3012 usbser_starti(usbser_port_t *pp, mblk_t *mp) 3013 { 3014 usbser_st_mstarti++; 3015 usbser_serialize_port_act(pp, USBSER_ACT_CTL); 3016 pp->port_flowc = pp->port_ttycommon.t_startc; 3017 usbser_inbound_flow_ctl(pp); 3018 usbser_release_port_act(pp, USBSER_ACT_CTL); 3019 freemsg(mp); 3020 } 3021 3022 /* 3023 * process M_FLUSH message 3024 */ 3025 static void 3026 usbser_flush(usbser_port_t *pp, mblk_t *mp) 3027 { 3028 queue_t *q = pp->port_ttycommon.t_writeq; 3029 3030 if (*mp->b_rptr & FLUSHW) { 3031 mutex_exit(&pp->port_mutex); 3032 (void) USBSER_DS_FIFO_FLUSH(pp, DS_TX); /* flush FIFO buffers */ 3033 flushq(q, FLUSHDATA); /* flush write queue */ 3034 mutex_enter(&pp->port_mutex); 3035 3036 usbser_release_port_act(pp, USBSER_ACT_TX); 3037 3038 *mp->b_rptr &= ~FLUSHW; 3039 } 3040 if (*mp->b_rptr & FLUSHR) { 3041 /* 3042 * flush FIFO buffers 3043 */ 3044 mutex_exit(&pp->port_mutex); 3045 (void) USBSER_DS_FIFO_FLUSH(pp, DS_RX); 3046 flushq(RD(q), FLUSHDATA); 3047 qreply(q, mp); 3048 mutex_enter(&pp->port_mutex); 3049 } else { 3050 freemsg(mp); 3051 } 3052 } 3053 3054 /* 3055 * process M_BREAK message 3056 */ 3057 static void 3058 usbser_break(usbser_port_t *pp, mblk_t *mp) 3059 { 3060 int rval; 3061 3062 /* 3063 * set the break and arrange for usbser_restart() to be called in 1/4 s 3064 */ 3065 mutex_exit(&pp->port_mutex); 3066 rval = USBSER_DS_BREAK_CTL(pp, DS_ON); 3067 mutex_enter(&pp->port_mutex); 3068 3069 if (rval == USB_SUCCESS) { 3070 pp->port_act |= USBSER_ACT_BREAK; 3071 pp->port_delay_id = timeout(usbser_restart, pp, 3072 drv_usectohz(250000)); 3073 } 3074 freemsg(mp); 3075 } 3076 3077 3078 /* 3079 * process M_DELAY message 3080 */ 3081 static void 3082 usbser_delay(usbser_port_t *pp, mblk_t *mp) 3083 { 3084 /* 3085 * arrange for usbser_restart() to be called when the delay expires 3086 */ 3087 pp->port_act |= USBSER_ACT_DELAY; 3088 pp->port_delay_id = timeout(usbser_restart, pp, 3089 (clock_t)(*(uchar_t *)mp->b_rptr + 6)); 3090 freemsg(mp); 3091 } 3092 3093 3094 /* 3095 * restart output on a line after a delay or break timer expired 3096 */ 3097 static void 3098 usbser_restart(void *arg) 3099 { 3100 usbser_port_t *pp = (usbser_port_t *)arg; 3101 3102 USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_restart"); 3103 3104 mutex_enter(&pp->port_mutex); 3105 /* if cancelled, return immediately */ 3106 if (pp->port_delay_id == 0) { 3107 mutex_exit(&pp->port_mutex); 3108 3109 return; 3110 } 3111 pp->port_delay_id = 0; 3112 3113 /* clear break if necessary */ 3114 if (pp->port_act & USBSER_ACT_BREAK) { 3115 mutex_exit(&pp->port_mutex); 3116 (void) USBSER_DS_BREAK_CTL(pp, DS_OFF); 3117 mutex_enter(&pp->port_mutex); 3118 } 3119 3120 usbser_release_port_act(pp, USBSER_ACT_BREAK | USBSER_ACT_DELAY); 3121 3122 /* wake wq thread to resume message processing */ 3123 usbser_thr_wake(&pp->port_wq_thread); 3124 mutex_exit(&pp->port_mutex); 3125 } 3126 3127 3128 /* 3129 * program port hardware with the chosen parameters 3130 * most of the operation is based on the values of 'c_iflag' and 'c_cflag' 3131 */ 3132 static int 3133 usbser_port_program(usbser_port_t *pp) 3134 { 3135 tty_common_t *tp = &pp->port_ttycommon; 3136 int baudrate; 3137 int c_flag; 3138 ds_port_param_entry_t pe[6]; 3139 ds_port_params_t params; 3140 int flow_ctl, ctl_val; 3141 int err = 0; 3142 3143 baudrate = tp->t_cflag & CBAUD; 3144 if (tp->t_cflag & CBAUDEXT) { 3145 baudrate += 16; 3146 } 3147 3148 /* 3149 * set input speed same as output, as split speed not supported 3150 */ 3151 if (tp->t_cflag & (CIBAUD|CIBAUDEXT)) { 3152 tp->t_cflag &= ~(CIBAUD); 3153 if (baudrate > CBAUD) { 3154 tp->t_cflag |= CIBAUDEXT; 3155 tp->t_cflag |= 3156 (((baudrate - CBAUD - 1) << IBSHIFT) & CIBAUD); 3157 } else { 3158 tp->t_cflag &= ~CIBAUDEXT; 3159 tp->t_cflag |= ((baudrate << IBSHIFT) & CIBAUD); 3160 } 3161 } 3162 3163 c_flag = tp->t_cflag; 3164 3165 /* 3166 * flow control 3167 */ 3168 flow_ctl = tp->t_iflag & (IXON | IXANY | IXOFF); 3169 if (c_flag & CRTSCTS) { 3170 flow_ctl |= CTSXON; 3171 } 3172 if (c_flag & CRTSXOFF) { 3173 flow_ctl |= RTSXOFF; 3174 } 3175 3176 /* 3177 * fill in port parameters we need to set: 3178 * 3179 * baud rate 3180 */ 3181 pe[0].param = DS_PARAM_BAUD; 3182 pe[0].val.ui = baudrate; 3183 3184 /* stop bits */ 3185 pe[1].param = DS_PARAM_STOPB; 3186 pe[1].val.ui = c_flag & CSTOPB; 3187 3188 /* parity */ 3189 pe[2].param = DS_PARAM_PARITY; 3190 pe[2].val.ui = c_flag & (PARENB | PARODD); 3191 3192 /* char size */ 3193 pe[3].param = DS_PARAM_CHARSZ; 3194 pe[3].val.ui = c_flag & CSIZE; 3195 3196 /* start & stop chars */ 3197 pe[4].param = DS_PARAM_XON_XOFF; 3198 pe[4].val.uc[0] = tp->t_startc; 3199 pe[4].val.uc[1] = tp->t_stopc; 3200 3201 /* flow control */ 3202 pe[5].param = DS_PARAM_FLOW_CTL; 3203 pe[5].val.ui = flow_ctl; 3204 3205 params.tp_entries = &pe[0]; 3206 params.tp_cnt = 6; 3207 3208 /* control signals */ 3209 ctl_val = TIOCM_DTR | TIOCM_RTS; 3210 if (baudrate == 0) { 3211 ctl_val &= ~TIOCM_DTR; /* zero baudrate means drop DTR */ 3212 } 3213 if (pp->port_flags & USBSER_FL_RX_STOPPED) { 3214 ctl_val &= ~TIOCM_RTS; 3215 } 3216 3217 /* submit */ 3218 mutex_exit(&pp->port_mutex); 3219 err = USBSER_DS_SET_PORT_PARAMS(pp, ¶ms); 3220 if (err != USB_SUCCESS) { 3221 mutex_enter(&pp->port_mutex); 3222 3223 return (EINVAL); 3224 } 3225 3226 err = USBSER_DS_SET_MODEM_CTL(pp, TIOCM_DTR | TIOCM_RTS, ctl_val); 3227 mutex_enter(&pp->port_mutex); 3228 3229 return ((err == USB_SUCCESS) ? 0 : EIO); 3230 } 3231 3232 3233 /* 3234 * check if any inbound flow control action needed 3235 */ 3236 static void 3237 usbser_inbound_flow_ctl(usbser_port_t *pp) 3238 { 3239 tcflag_t need_hw; 3240 int rts; 3241 char c = pp->port_flowc; 3242 mblk_t *mp = NULL; 3243 3244 USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, 3245 "usbser_inbound_flow_ctl: c=%x cflag=%x port_flags=%x", 3246 c, pp->port_ttycommon.t_cflag, pp->port_flags); 3247 3248 if (c == '\0') { 3249 3250 return; 3251 } 3252 pp->port_flowc = '\0'; 3253 3254 /* 3255 * if inbound hardware flow control enabled, we need to frob RTS 3256 */ 3257 need_hw = (pp->port_ttycommon.t_cflag & CRTSXOFF); 3258 if (c == pp->port_ttycommon.t_startc) { 3259 rts = TIOCM_RTS; 3260 pp->port_flags &= ~USBSER_FL_RX_STOPPED; 3261 } else { 3262 rts = 0; 3263 pp->port_flags |= USBSER_FL_RX_STOPPED; 3264 } 3265 3266 /* 3267 * if character flow control active, transmit a start or stop char, 3268 */ 3269 if (pp->port_ttycommon.t_iflag & IXOFF) { 3270 if ((mp = allocb(1, BPRI_LO)) == NULL) { 3271 USB_DPRINTF_L2(DPRINT_WQ, pp->port_lh, 3272 "usbser_inbound_flow_ctl: allocb failed"); 3273 } else { 3274 *mp->b_wptr++ = c; 3275 pp->port_flags |= USBSER_ACT_TX; 3276 } 3277 } 3278 3279 mutex_exit(&pp->port_mutex); 3280 if (need_hw) { 3281 (void) USBSER_DS_SET_MODEM_CTL(pp, TIOCM_RTS, rts); 3282 } 3283 if (mp) { 3284 (void) USBSER_DS_TX(pp, mp); 3285 } 3286 mutex_enter(&pp->port_mutex); 3287 } 3288 3289 3290 /* 3291 * misc 3292 * ---- 3293 * 3294 * 3295 * returns !=0 if device is online, 0 otherwise 3296 */ 3297 static int 3298 usbser_dev_is_online(usbser_state_t *usp) 3299 { 3300 int rval; 3301 3302 mutex_enter(&usp->us_mutex); 3303 rval = (usp->us_dev_state == USB_DEV_ONLINE); 3304 mutex_exit(&usp->us_mutex); 3305 3306 return (rval); 3307 } 3308 3309 /* 3310 * serialize port activities defined by 'act' mask 3311 */ 3312 static void 3313 usbser_serialize_port_act(usbser_port_t *pp, int act) 3314 { 3315 while (pp->port_act & act) { 3316 cv_wait(&pp->port_act_cv, &pp->port_mutex); 3317 } 3318 3319 pp->port_act |= act; 3320 } 3321 3322 3323 /* 3324 * indicate that port activity is finished 3325 */ 3326 static void 3327 usbser_release_port_act(usbser_port_t *pp, int act) 3328 { 3329 pp->port_act &= ~act; 3330 cv_broadcast(&pp->port_act_cv); 3331 } 3332 3333 3334 /* 3335 * message type to string and back conversion. 3336 * 3337 * pardon breaks on the same line, but as long as cstyle doesn't 3338 * complain, I'd like to keep this form for trivial cases like this. 3339 * associative arrays in the kernel, anyone? 3340 */ 3341 static char * 3342 usbser_msgtype2str(int type) 3343 { 3344 char *str; 3345 3346 switch (type) { 3347 case M_STOP: str = "M_STOP"; break; 3348 case M_START: str = "M_START"; break; 3349 case M_STOPI: str = "M_STOPI"; break; 3350 case M_STARTI: str = "M_STARTI"; break; 3351 case M_DATA: str = "M_DATA"; break; 3352 case M_DELAY: str = "M_DELAY"; break; 3353 case M_BREAK: str = "M_BREAK"; break; 3354 case M_IOCTL: str = "M_IOCTL"; break; 3355 case M_IOCDATA: str = "M_IOCDATA"; break; 3356 case M_FLUSH: str = "M_FLUSH"; break; 3357 case M_CTL: str = "M_CTL"; break; 3358 case M_READ: str = "M_READ"; break; 3359 default: str = "unknown"; break; 3360 } 3361 3362 return (str); 3363 } 3364 3365 3366 static char * 3367 usbser_ioctl2str(int ioctl) 3368 { 3369 char *str; 3370 3371 switch (ioctl) { 3372 case TCGETA: str = "TCGETA"; break; 3373 case TCSETA: str = "TCSETA"; break; 3374 case TCSETAF: str = "TCSETAF"; break; 3375 case TCSETAW: str = "TCSETAW"; break; 3376 case TCSBRK: str = "TCSBRK"; break; 3377 case TCXONC: str = "TCXONC"; break; 3378 case TCFLSH: str = "TCFLSH"; break; 3379 case TCGETS: str = "TCGETS"; break; 3380 case TCSETS: str = "TCSETS"; break; 3381 case TCSETSF: str = "TCSETSF"; break; 3382 case TCSETSW: str = "TCSETSW"; break; 3383 case TIOCSBRK: str = "TIOCSBRK"; break; 3384 case TIOCCBRK: str = "TIOCCBRK"; break; 3385 case TIOCMSET: str = "TIOCMSET"; break; 3386 case TIOCMBIS: str = "TIOCMBIS"; break; 3387 case TIOCMBIC: str = "TIOCMBIC"; break; 3388 case TIOCMGET: str = "TIOCMGET"; break; 3389 case (tIOC | 109): str = "TIOCSILOOP"; break; 3390 case (tIOC | 108): str = "TIOCCILOOP"; break; 3391 case TCGETX: str = "TCGETX"; break; 3392 case TCSETX: str = "TCGETX"; break; 3393 case TCSETXW: str = "TCGETX"; break; 3394 case TCSETXF: str = "TCGETX"; break; 3395 default: str = "unknown"; break; 3396 } 3397 3398 return (str); 3399 } 3400 3401 /* 3402 * Polled IO support 3403 */ 3404 3405 /* called once by consconfig() when polledio is opened */ 3406 static int 3407 usbser_polledio_init(usbser_port_t *pp) 3408 { 3409 int err; 3410 usb_pipe_handle_t hdl; 3411 ds_ops_t *ds_ops = pp->port_ds_ops; 3412 3413 /* only one serial line console supported */ 3414 if (console_input != NULL) 3415 3416 return (USB_FAILURE); 3417 3418 /* check if underlying driver supports polled io */ 3419 if (ds_ops->ds_version < DS_OPS_VERSION_V1 || 3420 ds_ops->ds_out_pipe == NULL || ds_ops->ds_in_pipe == NULL) 3421 3422 return (USB_FAILURE); 3423 3424 /* init polled input pipe */ 3425 hdl = ds_ops->ds_in_pipe(pp->port_ds_hdl, pp->port_num); 3426 err = usb_console_input_init(pp->port_usp->us_dip, hdl, 3427 &console_input_buf, &console_input); 3428 if (err) 3429 3430 return (USB_FAILURE); 3431 3432 /* init polled output pipe */ 3433 hdl = ds_ops->ds_out_pipe(pp->port_ds_hdl, pp->port_num); 3434 err = usb_console_output_init(pp->port_usp->us_dip, hdl, 3435 &console_output); 3436 if (err) { 3437 (void) usb_console_input_fini(console_input); 3438 console_input = NULL; 3439 3440 return (USB_FAILURE); 3441 } 3442 3443 return (USB_SUCCESS); 3444 } 3445 3446 /* called once by consconfig() when polledio is closed */ 3447 /*ARGSUSED*/ 3448 static void usbser_polledio_fini(usbser_port_t *pp) 3449 { 3450 /* Since we can't move the console, there is nothing to do. */ 3451 } 3452 3453 /*ARGSUSED*/ 3454 static void 3455 usbser_polledio_enter(cons_polledio_arg_t arg) 3456 { 3457 (void) usb_console_input_enter(console_input); 3458 (void) usb_console_output_enter(console_output); 3459 } 3460 3461 /*ARGSUSED*/ 3462 static void 3463 usbser_polledio_exit(cons_polledio_arg_t arg) 3464 { 3465 (void) usb_console_output_exit(console_output); 3466 (void) usb_console_input_exit(console_input); 3467 } 3468 3469 /*ARGSUSED*/ 3470 static void 3471 usbser_putchar(cons_polledio_arg_t arg, uchar_t c) 3472 { 3473 static uchar_t cr[2] = {'\r', '\n'}; 3474 uint_t nout; 3475 3476 if (c == '\n') 3477 (void) usb_console_write(console_output, cr, 2, &nout); 3478 else 3479 (void) usb_console_write(console_output, &c, 1, &nout); 3480 } 3481 3482 /*ARGSUSED*/ 3483 static int 3484 usbser_getchar(cons_polledio_arg_t arg) 3485 { 3486 while (!usbser_ischar(arg)) 3487 ; 3488 3489 return (*console_input_start++); 3490 } 3491 3492 /*ARGSUSED*/ 3493 static boolean_t 3494 usbser_ischar(cons_polledio_arg_t arg) 3495 { 3496 uint_t num_bytes; 3497 3498 if (console_input_start < console_input_end) 3499 3500 return (1); 3501 3502 if (usb_console_read(console_input, &num_bytes) != USB_SUCCESS) 3503 3504 return (0); 3505 3506 console_input_start = console_input_buf; 3507 console_input_end = console_input_buf + num_bytes; 3508 3509 return (num_bytes != 0); 3510 } 3511