1 /* $NetBSD: ucom.c,v 1.113 2016/05/14 10:52:29 mlelstv Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart@augustsson.net) at 9 * Carlstedt Research & Technology. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 /* 33 * This code is very heavily based on the 16550 driver, com.c. 34 */ 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.113 2016/05/14 10:52:29 mlelstv Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/ioctl.h> 43 #include <sys/conf.h> 44 #include <sys/tty.h> 45 #include <sys/file.h> 46 #include <sys/select.h> 47 #include <sys/proc.h> 48 #include <sys/vnode.h> 49 #include <sys/device.h> 50 #include <sys/poll.h> 51 #include <sys/queue.h> 52 #include <sys/kauth.h> 53 #include <sys/sysctl.h> 54 #include <sys/timepps.h> 55 #include <sys/rndsource.h> 56 57 #include <dev/usb/usb.h> 58 59 #include <dev/usb/usbdi.h> 60 #include <dev/usb/usbdi_util.h> 61 #include <dev/usb/usbdevs.h> 62 #include <dev/usb/usb_quirks.h> 63 #include <dev/usb/usbhist.h> 64 65 #include <dev/usb/ucomvar.h> 66 67 #include "ucom.h" 68 69 #include "locators.h" 70 71 #if NUCOM > 0 72 73 #ifdef USB_DEBUG 74 #ifndef UCOM_DEBUG 75 #define ucomdebug 0 76 #else 77 int ucomdebug = 0; 78 79 SYSCTL_SETUP(sysctl_hw_ucom_setup, "sysctl hw.ucom setup") 80 { 81 int err; 82 const struct sysctlnode *rnode; 83 const struct sysctlnode *cnode; 84 85 err = sysctl_createv(clog, 0, NULL, &rnode, 86 CTLFLAG_PERMANENT, CTLTYPE_NODE, "ucom", 87 SYSCTL_DESCR("ucom global controls"), 88 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL); 89 90 if (err) 91 goto fail; 92 93 /* control debugging printfs */ 94 err = sysctl_createv(clog, 0, &rnode, &cnode, 95 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, 96 "debug", SYSCTL_DESCR("Enable debugging output"), 97 NULL, 0, &ucomdebug, sizeof(ucomdebug), CTL_CREATE, CTL_EOL); 98 if (err) 99 goto fail; 100 101 return; 102 fail: 103 aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err); 104 } 105 106 #endif /* UCOM_DEBUG */ 107 #endif /* USB_DEBUG */ 108 109 #define DPRINTF(FMT,A,B,C,D) USBHIST_LOGN(ucomdebug,1,FMT,A,B,C,D) 110 #define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(ucomdebug,N,FMT,A,B,C,D) 111 #define UCOMHIST_FUNC() USBHIST_FUNC() 112 #define UCOMHIST_CALLED(name) USBHIST_CALLED(ucomdebug) 113 114 #define UCOMCALLUNIT_MASK TTCALLUNIT_MASK 115 #define UCOMUNIT_MASK TTUNIT_MASK 116 #define UCOMDIALOUT_MASK TTDIALOUT_MASK 117 118 #define UCOMCALLUNIT(x) TTCALLUNIT(x) 119 #define UCOMUNIT(x) TTUNIT(x) 120 #define UCOMDIALOUT(x) TTDIALOUT(x) 121 122 /* 123 * XXX: We can submit multiple input/output buffers to the usb stack 124 * to improve throughput, but the usb stack is too lame to deal with this 125 * in a number of places. 126 */ 127 #define UCOM_IN_BUFFS 1 128 #define UCOM_OUT_BUFFS 1 129 130 struct ucom_buffer { 131 SIMPLEQ_ENTRY(ucom_buffer) ub_link; 132 struct usbd_xfer *ub_xfer; 133 u_char *ub_data; 134 u_int ub_len; 135 u_int ub_index; 136 }; 137 138 struct ucom_softc { 139 device_t sc_dev; /* base device */ 140 141 struct usbd_device * sc_udev; /* USB device */ 142 143 struct usbd_interface * sc_iface; /* data interface */ 144 145 int sc_bulkin_no; /* bulk in endpoint address */ 146 struct usbd_pipe * sc_bulkin_pipe; /* bulk in pipe */ 147 u_int sc_ibufsize; /* read buffer size */ 148 u_int sc_ibufsizepad; /* read buffer size padded */ 149 struct ucom_buffer sc_ibuff[UCOM_IN_BUFFS]; 150 SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_empty; 151 SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_full; 152 153 int sc_bulkout_no; /* bulk out endpoint address */ 154 struct usbd_pipe * sc_bulkout_pipe;/* bulk out pipe */ 155 u_int sc_obufsize; /* write buffer size */ 156 u_int sc_opkthdrlen; /* header length of */ 157 struct ucom_buffer sc_obuff[UCOM_OUT_BUFFS]; 158 SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_free; 159 SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_full; 160 161 void *sc_si; 162 163 const struct ucom_methods *sc_methods; 164 void *sc_parent; 165 int sc_portno; 166 167 struct tty *sc_tty; /* our tty */ 168 u_char sc_lsr; 169 u_char sc_msr; 170 u_char sc_mcr; 171 volatile u_char sc_rx_stopped; 172 u_char sc_rx_unblock; 173 u_char sc_tx_stopped; 174 int sc_swflags; 175 176 u_char sc_opening; /* lock during open */ 177 u_char sc_closing; /* lock during close */ 178 int sc_refcnt; 179 u_char sc_dying; /* disconnecting */ 180 181 struct pps_state sc_pps_state; /* pps state */ 182 183 krndsource_t sc_rndsource; /* random source */ 184 185 kmutex_t sc_lock; 186 kcondvar_t sc_opencv; 187 kcondvar_t sc_detachcv; 188 }; 189 190 dev_type_open(ucomopen); 191 dev_type_close(ucomclose); 192 dev_type_read(ucomread); 193 dev_type_write(ucomwrite); 194 dev_type_ioctl(ucomioctl); 195 dev_type_stop(ucomstop); 196 dev_type_tty(ucomtty); 197 dev_type_poll(ucompoll); 198 199 const struct cdevsw ucom_cdevsw = { 200 .d_open = ucomopen, 201 .d_close = ucomclose, 202 .d_read = ucomread, 203 .d_write = ucomwrite, 204 .d_ioctl = ucomioctl, 205 .d_stop = ucomstop, 206 .d_tty = ucomtty, 207 .d_poll = ucompoll, 208 .d_mmap = nommap, 209 .d_kqfilter = ttykqfilter, 210 .d_discard = nodiscard, 211 .d_flag = D_TTY | D_MPSAFE 212 }; 213 214 static void ucom_cleanup(struct ucom_softc *); 215 static int ucomparam(struct tty *, struct termios *); 216 static int ucomhwiflow(struct tty *, int); 217 static void ucomstart(struct tty *); 218 static void ucom_shutdown(struct ucom_softc *); 219 static int ucom_do_ioctl(struct ucom_softc *, u_long, void *, 220 int, struct lwp *); 221 static void ucom_dtr(struct ucom_softc *, int); 222 static void ucom_rts(struct ucom_softc *, int); 223 static void ucom_break(struct ucom_softc *, int); 224 static void tiocm_to_ucom(struct ucom_softc *, u_long, int); 225 static int ucom_to_tiocm(struct ucom_softc *); 226 227 static void ucomreadcb(struct usbd_xfer *, void *, usbd_status); 228 static void ucom_submit_write(struct ucom_softc *, struct ucom_buffer *); 229 static void ucom_write_status(struct ucom_softc *, struct ucom_buffer *, 230 usbd_status); 231 232 static void ucomwritecb(struct usbd_xfer *, void *, usbd_status); 233 static void ucom_read_complete(struct ucom_softc *); 234 static usbd_status ucomsubmitread(struct ucom_softc *, struct ucom_buffer *); 235 static void ucom_softintr(void *); 236 237 int ucom_match(device_t, cfdata_t, void *); 238 void ucom_attach(device_t, device_t, void *); 239 int ucom_detach(device_t, int); 240 int ucom_activate(device_t, enum devact); 241 extern struct cfdriver ucom_cd; 242 CFATTACH_DECL_NEW(ucom, sizeof(struct ucom_softc), ucom_match, ucom_attach, 243 ucom_detach, ucom_activate); 244 245 int 246 ucom_match(device_t parent, cfdata_t match, void *aux) 247 { 248 return 1; 249 } 250 251 void 252 ucom_attach(device_t parent, device_t self, void *aux) 253 { 254 struct ucom_softc *sc = device_private(self); 255 struct ucom_attach_args *ucaa = aux; 256 struct tty *tp; 257 258 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 259 260 if (ucaa->ucaa_info != NULL) 261 aprint_normal(": %s", ucaa->ucaa_info); 262 aprint_normal("\n"); 263 264 prop_dictionary_set_int32(device_properties(self), "port", 265 ucaa->ucaa_portno); 266 267 sc->sc_dev = self; 268 sc->sc_udev = ucaa->ucaa_device; 269 sc->sc_iface = ucaa->ucaa_iface; 270 sc->sc_bulkout_no = ucaa->ucaa_bulkout; 271 sc->sc_bulkin_no = ucaa->ucaa_bulkin; 272 sc->sc_ibufsize = ucaa->ucaa_ibufsize; 273 sc->sc_ibufsizepad = ucaa->ucaa_ibufsizepad; 274 sc->sc_obufsize = ucaa->ucaa_obufsize; 275 sc->sc_opkthdrlen = ucaa->ucaa_opkthdrlen; 276 sc->sc_methods = ucaa->ucaa_methods; 277 sc->sc_parent = ucaa->ucaa_arg; 278 sc->sc_portno = ucaa->ucaa_portno; 279 280 sc->sc_lsr = 0; 281 sc->sc_msr = 0; 282 sc->sc_mcr = 0; 283 sc->sc_tx_stopped = 0; 284 sc->sc_swflags = 0; 285 sc->sc_opening = 0; 286 sc->sc_closing = 0; 287 sc->sc_refcnt = 0; 288 sc->sc_dying = 0; 289 290 sc->sc_si = softint_establish(SOFTINT_USB, ucom_softintr, sc); 291 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); 292 cv_init(&sc->sc_opencv, "ucomopen"); 293 cv_init(&sc->sc_detachcv, "ucomdtch"); 294 295 SIMPLEQ_INIT(&sc->sc_ibuff_empty); 296 SIMPLEQ_INIT(&sc->sc_ibuff_full); 297 SIMPLEQ_INIT(&sc->sc_obuff_free); 298 SIMPLEQ_INIT(&sc->sc_obuff_full); 299 300 memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff)); 301 memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff)); 302 303 DPRINTF("open pipes in=%d out=%d", sc->sc_bulkin_no, sc->sc_bulkout_no, 304 0, 0); 305 306 struct ucom_buffer *ub; 307 usbd_status err; 308 int error; 309 310 /* Open the bulk pipes */ 311 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 312 USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe); 313 if (err) { 314 DPRINTF("open bulk in error (addr %d), err=%d", 315 sc->sc_bulkin_no, err, 0, 0); 316 error = EIO; 317 goto fail_0; 318 } 319 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, 320 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); 321 if (err) { 322 DPRINTF("open bulk out error (addr %d), err=%d", 323 sc->sc_bulkout_no, err, 0, 0); 324 error = EIO; 325 goto fail_1; 326 } 327 328 /* Allocate input buffers */ 329 for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS]; 330 ub++) { 331 error = usbd_create_xfer(sc->sc_bulkin_pipe, sc->sc_ibufsizepad, 332 USBD_SHORT_XFER_OK, 0, &ub->ub_xfer); 333 if (error) 334 goto fail_2; 335 ub->ub_data = usbd_get_buffer(ub->ub_xfer); 336 } 337 338 for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS]; 339 ub++) { 340 error = usbd_create_xfer(sc->sc_bulkout_pipe, sc->sc_obufsize, 341 0, 0, &ub->ub_xfer); 342 if (error) 343 goto fail_2; 344 ub->ub_data = usbd_get_buffer(ub->ub_xfer); 345 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link); 346 } 347 348 tp = tty_alloc(); 349 tp->t_oproc = ucomstart; 350 tp->t_param = ucomparam; 351 tp->t_hwiflow = ucomhwiflow; 352 sc->sc_tty = tp; 353 354 DPRINTF("tty_attach %p", tp, 0, 0, 0); 355 tty_attach(tp); 356 357 rnd_attach_source(&sc->sc_rndsource, device_xname(sc->sc_dev), 358 RND_TYPE_TTY, RND_FLAG_DEFAULT); 359 360 if (!pmf_device_register(self, NULL, NULL)) 361 aprint_error_dev(self, "couldn't establish power handler\n"); 362 return; 363 364 fail_2: 365 for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS]; 366 ub++) { 367 if (ub->ub_xfer) 368 usbd_destroy_xfer(ub->ub_xfer); 369 } 370 for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS]; 371 ub++) { 372 if (ub->ub_xfer) 373 usbd_destroy_xfer(ub->ub_xfer); 374 } 375 376 fail_1: 377 usbd_close_pipe(sc->sc_bulkin_pipe); 378 379 fail_0: 380 aprint_error_dev(self, "attach failed, error=%d\n", error); 381 382 return; 383 } 384 385 int 386 ucom_detach(device_t self, int flags) 387 { 388 struct ucom_softc *sc = device_private(self); 389 struct tty *tp = sc->sc_tty; 390 int maj, mn; 391 int i; 392 393 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 394 395 DPRINTF("sc=%p flags=%d tp=%p", sc, flags, tp, 0); 396 DPRINTF("... pipe=%d,%d",sc->sc_bulkin_no, sc->sc_bulkout_no, 0, 0); 397 398 mutex_enter(&sc->sc_lock); 399 sc->sc_dying = 1; 400 mutex_exit(&sc->sc_lock); 401 402 pmf_device_deregister(self); 403 404 if (sc->sc_bulkin_pipe != NULL) 405 usbd_abort_pipe(sc->sc_bulkin_pipe); 406 if (sc->sc_bulkout_pipe != NULL) 407 usbd_abort_pipe(sc->sc_bulkout_pipe); 408 409 mutex_enter(&sc->sc_lock); 410 while (sc->sc_refcnt > 0) { 411 /* Wake up anyone waiting */ 412 if (tp != NULL) { 413 mutex_spin_enter(&tty_lock); 414 CLR(tp->t_state, TS_CARR_ON); 415 CLR(tp->t_cflag, CLOCAL | MDMBUF); 416 ttyflush(tp, FREAD|FWRITE); 417 mutex_spin_exit(&tty_lock); 418 } 419 /* Wait for processes to go away. */ 420 usb_detach_wait(sc->sc_dev, &sc->sc_detachcv, &sc->sc_lock); 421 } 422 423 softint_disestablish(sc->sc_si); 424 mutex_exit(&sc->sc_lock); 425 426 /* locate the major number */ 427 maj = cdevsw_lookup_major(&ucom_cdevsw); 428 429 /* Nuke the vnodes for any open instances. */ 430 mn = device_unit(self); 431 DPRINTF("maj=%d mn=%d\n", maj, mn, 0, 0); 432 vdevgone(maj, mn, mn, VCHR); 433 vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR); 434 vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR); 435 436 /* Detach and free the tty. */ 437 if (tp != NULL) { 438 tty_detach(tp); 439 tty_free(tp); 440 sc->sc_tty = NULL; 441 } 442 443 for (i = 0; i < UCOM_IN_BUFFS; i++) { 444 if (sc->sc_ibuff[i].ub_xfer != NULL) 445 usbd_destroy_xfer(sc->sc_ibuff[i].ub_xfer); 446 } 447 448 for (i = 0; i < UCOM_OUT_BUFFS; i++) { 449 if (sc->sc_obuff[i].ub_xfer != NULL) 450 usbd_destroy_xfer(sc->sc_obuff[i].ub_xfer); 451 } 452 453 if (sc->sc_bulkin_pipe != NULL) { 454 usbd_close_pipe(sc->sc_bulkin_pipe); 455 sc->sc_bulkin_pipe = NULL; 456 } 457 458 if (sc->sc_bulkout_pipe != NULL) { 459 usbd_close_pipe(sc->sc_bulkout_pipe); 460 sc->sc_bulkout_pipe = NULL; 461 } 462 463 /* Detach the random source */ 464 rnd_detach_source(&sc->sc_rndsource); 465 466 mutex_destroy(&sc->sc_lock); 467 cv_destroy(&sc->sc_opencv); 468 cv_destroy(&sc->sc_detachcv); 469 470 return 0; 471 } 472 473 int 474 ucom_activate(device_t self, enum devact act) 475 { 476 struct ucom_softc *sc = device_private(self); 477 478 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 479 480 DPRINTFN(5, "%d", act, 0, 0, 0); 481 482 switch (act) { 483 case DVACT_DEACTIVATE: 484 mutex_enter(&sc->sc_lock); 485 sc->sc_dying = 1; 486 mutex_exit(&sc->sc_lock); 487 return 0; 488 default: 489 return EOPNOTSUPP; 490 } 491 } 492 493 void 494 ucom_shutdown(struct ucom_softc *sc) 495 { 496 struct tty *tp = sc->sc_tty; 497 498 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 499 500 KASSERT(mutex_owned(&sc->sc_lock)); 501 /* 502 * Hang up if necessary. Wait a bit, so the other side has time to 503 * notice even if we immediately open the port again. 504 */ 505 if (ISSET(tp->t_cflag, HUPCL)) { 506 ucom_dtr(sc, 0); 507 /* XXX will only timeout */ 508 (void) kpause(ttclos, false, hz, &sc->sc_lock); 509 } 510 } 511 512 int 513 ucomopen(dev_t dev, int flag, int mode, struct lwp *l) 514 { 515 int unit = UCOMUNIT(dev); 516 struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit); 517 struct ucom_buffer *ub; 518 struct tty *tp; 519 int error; 520 521 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 522 523 if (sc == NULL) 524 return ENXIO; 525 526 mutex_enter(&sc->sc_lock); 527 if (sc->sc_dying) { 528 mutex_exit(&sc->sc_lock); 529 return EIO; 530 } 531 532 if (!device_is_active(sc->sc_dev)) { 533 mutex_exit(&sc->sc_lock); 534 return ENXIO; 535 } 536 537 tp = sc->sc_tty; 538 539 DPRINTF("unit=%d, tp=%p\n", unit, tp, 0, 0); 540 541 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) { 542 mutex_exit(&sc->sc_lock); 543 return EBUSY; 544 } 545 546 /* 547 * Wait while the device is initialized by the 548 * first opener or cleaned up by the last closer. 549 */ 550 while (sc->sc_opening || sc->sc_closing) { 551 error = cv_wait_sig(&sc->sc_opencv, &sc->sc_lock); 552 553 if (error) { 554 mutex_exit(&sc->sc_lock); 555 return error; 556 } 557 } 558 559 sc->sc_opening = 1; 560 561 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 562 struct termios t; 563 564 tp->t_dev = dev; 565 566 if (sc->sc_methods->ucom_open != NULL) { 567 error = sc->sc_methods->ucom_open(sc->sc_parent, 568 sc->sc_portno); 569 if (error) { 570 ucom_cleanup(sc); 571 sc->sc_opening = 0; 572 cv_signal(&sc->sc_opencv); 573 mutex_exit(&sc->sc_lock); 574 return error; 575 } 576 } 577 578 ucom_status_change(sc); 579 580 /* Clear PPS capture state on first open. */ 581 mutex_spin_enter(&timecounter_lock); 582 memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state)); 583 sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; 584 pps_init(&sc->sc_pps_state); 585 mutex_spin_exit(&timecounter_lock); 586 587 /* 588 * Initialize the termios status to the defaults. Add in the 589 * sticky bits from TIOCSFLAGS. 590 */ 591 t.c_ispeed = 0; 592 t.c_ospeed = TTYDEF_SPEED; 593 t.c_cflag = TTYDEF_CFLAG; 594 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 595 SET(t.c_cflag, CLOCAL); 596 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 597 SET(t.c_cflag, CRTSCTS); 598 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 599 SET(t.c_cflag, MDMBUF); 600 /* Make sure ucomparam() will do something. */ 601 tp->t_ospeed = 0; 602 (void) ucomparam(tp, &t); 603 tp->t_iflag = TTYDEF_IFLAG; 604 tp->t_oflag = TTYDEF_OFLAG; 605 tp->t_lflag = TTYDEF_LFLAG; 606 ttychars(tp); 607 ttsetwater(tp); 608 609 /* 610 * Turn on DTR. We must always do this, even if carrier is not 611 * present, because otherwise we'd have to use TIOCSDTR 612 * immediately after setting CLOCAL, which applications do not 613 * expect. We always assert DTR while the device is open 614 * unless explicitly requested to deassert it. Ditto RTS. 615 */ 616 ucom_dtr(sc, 1); 617 ucom_rts(sc, 1); 618 619 sc->sc_rx_unblock = 0; 620 sc->sc_rx_stopped = 0; 621 sc->sc_tx_stopped = 0; 622 623 for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS]; 624 ub++) { 625 if (ucomsubmitread(sc, ub) != USBD_NORMAL_COMPLETION) { 626 error = EIO; 627 goto fail_2; 628 } 629 } 630 } 631 sc->sc_opening = 0; 632 cv_signal(&sc->sc_opencv); 633 mutex_exit(&sc->sc_lock); 634 635 error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); 636 if (error) 637 goto bad; 638 639 error = (*tp->t_linesw->l_open)(dev, tp); 640 if (error) 641 goto bad; 642 643 return 0; 644 645 fail_2: 646 usbd_abort_pipe(sc->sc_bulkin_pipe); 647 usbd_abort_pipe(sc->sc_bulkout_pipe); 648 649 mutex_enter(&sc->sc_lock); 650 sc->sc_opening = 0; 651 cv_signal(&sc->sc_opencv); 652 mutex_exit(&sc->sc_lock); 653 654 return error; 655 656 bad: 657 mutex_spin_enter(&tty_lock); 658 CLR(tp->t_state, TS_BUSY); 659 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 660 /* 661 * We failed to open the device, and nobody else had it opened. 662 * Clean up the state as appropriate. 663 */ 664 ucom_cleanup(sc); 665 } 666 mutex_spin_exit(&tty_lock); 667 668 return error; 669 } 670 671 int 672 ucomclose(dev_t dev, int flag, int mode, struct lwp *l) 673 { 674 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev)); 675 struct tty *tp; 676 677 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 678 679 DPRINTF("unit=%d", UCOMUNIT(dev), 0, 0, 0); 680 681 if (sc == NULL) 682 return 0; 683 684 mutex_enter(&sc->sc_lock); 685 tp = sc->sc_tty; 686 687 while (sc->sc_closing) 688 cv_wait(&sc->sc_opencv, &sc->sc_lock); 689 sc->sc_closing = 1; 690 691 if (!ISSET(tp->t_state, TS_ISOPEN)) { 692 goto out; 693 } 694 695 sc->sc_refcnt++; 696 697 (*tp->t_linesw->l_close)(tp, flag); 698 ttyclose(tp); 699 700 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 701 /* 702 * Although we got a last close, the device may still be in 703 * use; e.g. if this was the dialout node, and there are still 704 * processes waiting for carrier on the non-dialout node. 705 */ 706 ucom_cleanup(sc); 707 } 708 709 if (sc->sc_methods->ucom_close != NULL) 710 sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno); 711 712 if (--sc->sc_refcnt < 0) 713 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv); 714 715 out: 716 sc->sc_closing = 0; 717 cv_signal(&sc->sc_opencv); 718 719 mutex_exit(&sc->sc_lock); 720 721 return 0; 722 } 723 724 int 725 ucomread(dev_t dev, struct uio *uio, int flag) 726 { 727 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev)); 728 struct tty *tp; 729 int error; 730 731 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 732 733 if (sc == NULL) 734 return EIO; 735 736 mutex_enter(&sc->sc_lock); 737 if (sc->sc_dying) { 738 mutex_exit(&sc->sc_lock); 739 return EIO; 740 } 741 742 tp = sc->sc_tty; 743 744 sc->sc_refcnt++; 745 mutex_exit(&sc->sc_lock); 746 error = ((*tp->t_linesw->l_read)(tp, uio, flag)); 747 mutex_enter(&sc->sc_lock); 748 749 if (--sc->sc_refcnt < 0) 750 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv); 751 mutex_exit(&sc->sc_lock); 752 753 return error; 754 } 755 756 int 757 ucomwrite(dev_t dev, struct uio *uio, int flag) 758 { 759 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev)); 760 struct tty *tp; 761 int error; 762 763 if (sc == NULL) 764 return EIO; 765 766 mutex_enter(&sc->sc_lock); 767 if (sc->sc_dying) { 768 mutex_exit(&sc->sc_lock); 769 return EIO; 770 } 771 772 tp = sc->sc_tty; 773 774 sc->sc_refcnt++; 775 mutex_exit(&sc->sc_lock); 776 error = ((*tp->t_linesw->l_write)(tp, uio, flag)); 777 mutex_enter(&sc->sc_lock); 778 if (--sc->sc_refcnt < 0) 779 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv); 780 mutex_exit(&sc->sc_lock); 781 782 return error; 783 } 784 785 int 786 ucompoll(dev_t dev, int events, struct lwp *l) 787 { 788 struct ucom_softc *sc; 789 struct tty *tp; 790 int revents; 791 792 sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev)); 793 if (sc == NULL) 794 return POLLHUP; 795 796 mutex_enter(&sc->sc_lock); 797 if (sc->sc_dying) { 798 mutex_exit(&sc->sc_lock); 799 return POLLHUP; 800 } 801 tp = sc->sc_tty; 802 803 sc->sc_refcnt++; 804 mutex_exit(&sc->sc_lock); 805 revents = ((*tp->t_linesw->l_poll)(tp, events, l)); 806 mutex_enter(&sc->sc_lock); 807 if (--sc->sc_refcnt < 0) 808 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv); 809 mutex_exit(&sc->sc_lock); 810 811 return revents; 812 } 813 814 struct tty * 815 ucomtty(dev_t dev) 816 { 817 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev)); 818 819 return sc != NULL ? sc->sc_tty : NULL; 820 } 821 822 int 823 ucomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 824 { 825 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev)); 826 int error; 827 828 if (sc == NULL) 829 return EIO; 830 831 mutex_enter(&sc->sc_lock); 832 if (sc->sc_dying) { 833 mutex_exit(&sc->sc_lock); 834 return EIO; 835 } 836 837 sc->sc_refcnt++; 838 error = ucom_do_ioctl(sc, cmd, data, flag, l); 839 if (--sc->sc_refcnt < 0) 840 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv); 841 mutex_exit(&sc->sc_lock); 842 return error; 843 } 844 845 static int 846 ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, void *data, 847 int flag, struct lwp *l) 848 { 849 struct tty *tp = sc->sc_tty; 850 int error; 851 852 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 853 854 DPRINTF("cmd=0x%08lx", cmd, 0, 0, 0); 855 856 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 857 if (error != EPASSTHROUGH) 858 return error; 859 860 error = ttioctl(tp, cmd, data, flag, l); 861 if (error != EPASSTHROUGH) 862 return error; 863 864 if (sc->sc_methods->ucom_ioctl != NULL) { 865 error = sc->sc_methods->ucom_ioctl(sc->sc_parent, 866 sc->sc_portno, cmd, data, flag, l->l_proc); 867 if (error != EPASSTHROUGH) 868 return error; 869 } 870 871 error = 0; 872 873 DPRINTF("our cmd=0x%08lx", cmd, 0, 0, 0); 874 //mutex_enter(&tty_lock); 875 876 switch (cmd) { 877 case TIOCSBRK: 878 ucom_break(sc, 1); 879 break; 880 881 case TIOCCBRK: 882 ucom_break(sc, 0); 883 break; 884 885 case TIOCSDTR: 886 ucom_dtr(sc, 1); 887 break; 888 889 case TIOCCDTR: 890 ucom_dtr(sc, 0); 891 break; 892 893 case TIOCGFLAGS: 894 *(int *)data = sc->sc_swflags; 895 break; 896 897 case TIOCSFLAGS: 898 error = kauth_authorize_device_tty(l->l_cred, 899 KAUTH_DEVICE_TTY_PRIVSET, tp); 900 if (error) 901 break; 902 sc->sc_swflags = *(int *)data; 903 break; 904 905 case TIOCMSET: 906 case TIOCMBIS: 907 case TIOCMBIC: 908 tiocm_to_ucom(sc, cmd, *(int *)data); 909 break; 910 911 case TIOCMGET: 912 *(int *)data = ucom_to_tiocm(sc); 913 break; 914 915 case PPS_IOC_CREATE: 916 case PPS_IOC_DESTROY: 917 case PPS_IOC_GETPARAMS: 918 case PPS_IOC_SETPARAMS: 919 case PPS_IOC_GETCAP: 920 case PPS_IOC_FETCH: 921 #ifdef PPS_SYNC 922 case PPS_IOC_KCBIND: 923 #endif 924 mutex_spin_enter(&timecounter_lock); 925 error = pps_ioctl(cmd, data, &sc->sc_pps_state); 926 mutex_spin_exit(&timecounter_lock); 927 break; 928 929 default: 930 error = EPASSTHROUGH; 931 break; 932 } 933 934 //mutex_exit(&tty_lock); 935 936 return error; 937 } 938 939 static void 940 tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits) 941 { 942 u_char combits; 943 944 combits = 0; 945 if (ISSET(ttybits, TIOCM_DTR)) 946 SET(combits, UMCR_DTR); 947 if (ISSET(ttybits, TIOCM_RTS)) 948 SET(combits, UMCR_RTS); 949 950 switch (how) { 951 case TIOCMBIC: 952 CLR(sc->sc_mcr, combits); 953 break; 954 955 case TIOCMBIS: 956 SET(sc->sc_mcr, combits); 957 break; 958 959 case TIOCMSET: 960 CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS); 961 SET(sc->sc_mcr, combits); 962 break; 963 } 964 965 if (how == TIOCMSET || ISSET(combits, UMCR_DTR)) 966 ucom_dtr(sc, (sc->sc_mcr & UMCR_DTR) != 0); 967 if (how == TIOCMSET || ISSET(combits, UMCR_RTS)) 968 ucom_rts(sc, (sc->sc_mcr & UMCR_RTS) != 0); 969 } 970 971 static int 972 ucom_to_tiocm(struct ucom_softc *sc) 973 { 974 u_char combits; 975 int ttybits = 0; 976 977 combits = sc->sc_mcr; 978 if (ISSET(combits, UMCR_DTR)) 979 SET(ttybits, TIOCM_DTR); 980 if (ISSET(combits, UMCR_RTS)) 981 SET(ttybits, TIOCM_RTS); 982 983 combits = sc->sc_msr; 984 if (ISSET(combits, UMSR_DCD)) 985 SET(ttybits, TIOCM_CD); 986 if (ISSET(combits, UMSR_CTS)) 987 SET(ttybits, TIOCM_CTS); 988 if (ISSET(combits, UMSR_DSR)) 989 SET(ttybits, TIOCM_DSR); 990 if (ISSET(combits, UMSR_RI | UMSR_TERI)) 991 SET(ttybits, TIOCM_RI); 992 993 #if 0 994 XXX; 995 if (sc->sc_ier != 0) 996 SET(ttybits, TIOCM_LE); 997 #endif 998 999 return ttybits; 1000 } 1001 1002 static void 1003 ucom_break(struct ucom_softc *sc, int onoff) 1004 { 1005 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1006 1007 DPRINTF("onoff=%d", onoff, 0, 0, 0); 1008 1009 if (sc->sc_methods->ucom_set != NULL) 1010 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 1011 UCOM_SET_BREAK, onoff); 1012 } 1013 1014 static void 1015 ucom_dtr(struct ucom_softc *sc, int onoff) 1016 { 1017 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1018 1019 DPRINTF("onoff=%d", onoff, 0, 0, 0); 1020 1021 if (sc->sc_methods->ucom_set != NULL) 1022 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 1023 UCOM_SET_DTR, onoff); 1024 } 1025 1026 static void 1027 ucom_rts(struct ucom_softc *sc, int onoff) 1028 { 1029 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1030 1031 DPRINTF("onoff=%d", onoff, 0, 0, 0); 1032 1033 if (sc->sc_methods->ucom_set != NULL) 1034 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 1035 UCOM_SET_RTS, onoff); 1036 } 1037 1038 void 1039 ucom_status_change(struct ucom_softc *sc) 1040 { 1041 struct tty *tp = sc->sc_tty; 1042 u_char old_msr; 1043 1044 if (sc->sc_methods->ucom_get_status != NULL) { 1045 old_msr = sc->sc_msr; 1046 sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno, 1047 &sc->sc_lsr, &sc->sc_msr); 1048 if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) { 1049 mutex_spin_enter(&timecounter_lock); 1050 pps_capture(&sc->sc_pps_state); 1051 pps_event(&sc->sc_pps_state, 1052 (sc->sc_msr & UMSR_DCD) ? 1053 PPS_CAPTUREASSERT : 1054 PPS_CAPTURECLEAR); 1055 mutex_spin_exit(&timecounter_lock); 1056 1057 (*tp->t_linesw->l_modem)(tp, 1058 ISSET(sc->sc_msr, UMSR_DCD)); 1059 } 1060 } else { 1061 sc->sc_lsr = 0; 1062 /* Assume DCD is present, if we have no chance to check it. */ 1063 sc->sc_msr = UMSR_DCD; 1064 } 1065 } 1066 1067 static int 1068 ucomparam(struct tty *tp, struct termios *t) 1069 { 1070 struct ucom_softc *sc = device_lookup_private(&ucom_cd, 1071 UCOMUNIT(tp->t_dev)); 1072 int error; 1073 1074 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1075 1076 if (sc == NULL || sc->sc_dying) 1077 return EIO; 1078 1079 /* Check requested parameters. */ 1080 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 1081 return EINVAL; 1082 1083 /* 1084 * For the console, always force CLOCAL and !HUPCL, so that the port 1085 * is always active. 1086 */ 1087 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) { 1088 SET(t->c_cflag, CLOCAL); 1089 CLR(t->c_cflag, HUPCL); 1090 } 1091 1092 /* 1093 * If there were no changes, don't do anything. This avoids dropping 1094 * input and improves performance when all we did was frob things like 1095 * VMIN and VTIME. 1096 */ 1097 if (tp->t_ospeed == t->c_ospeed && 1098 tp->t_cflag == t->c_cflag) 1099 return 0; 1100 1101 /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */ 1102 1103 /* And copy to tty. */ 1104 tp->t_ispeed = 0; 1105 tp->t_ospeed = t->c_ospeed; 1106 tp->t_cflag = t->c_cflag; 1107 1108 if (sc->sc_methods->ucom_param != NULL) { 1109 error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno, 1110 t); 1111 if (error) 1112 return error; 1113 } 1114 1115 /* XXX worry about CHWFLOW */ 1116 1117 /* 1118 * Update the tty layer's idea of the carrier bit, in case we changed 1119 * CLOCAL or MDMBUF. We don't hang up here; we only do that by 1120 * explicit request. 1121 */ 1122 DPRINTF("l_modem", 0, 0, 0, 0); 1123 (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD)); 1124 1125 #if 0 1126 XXX what if the hardware is not open 1127 if (!ISSET(t->c_cflag, CHWFLOW)) { 1128 if (sc->sc_tx_stopped) { 1129 sc->sc_tx_stopped = 0; 1130 ucomstart(tp); 1131 } 1132 } 1133 #endif 1134 1135 return 0; 1136 } 1137 1138 static int 1139 ucomhwiflow(struct tty *tp, int block) 1140 { 1141 struct ucom_softc *sc = device_lookup_private(&ucom_cd, 1142 UCOMUNIT(tp->t_dev)); 1143 int old; 1144 1145 if (sc == NULL) 1146 return 0; 1147 1148 mutex_enter(&sc->sc_lock); 1149 old = sc->sc_rx_stopped; 1150 sc->sc_rx_stopped = (u_char)block; 1151 1152 if (old && !block) { 1153 sc->sc_rx_unblock = 1; 1154 softint_schedule(sc->sc_si); 1155 } 1156 mutex_exit(&sc->sc_lock); 1157 1158 return 1; 1159 } 1160 1161 static void 1162 ucomstart(struct tty *tp) 1163 { 1164 struct ucom_softc *sc = device_lookup_private(&ucom_cd, 1165 UCOMUNIT(tp->t_dev)); 1166 struct ucom_buffer *ub; 1167 u_char *data; 1168 int cnt; 1169 1170 if (sc == NULL) 1171 return; 1172 1173 KASSERT(&sc->sc_lock); 1174 KASSERT(mutex_owned(&tty_lock)); 1175 if (sc->sc_dying) { 1176 return; 1177 } 1178 1179 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 1180 goto out; 1181 if (sc->sc_tx_stopped) 1182 goto out; 1183 1184 if (!ttypull(tp)) 1185 goto out; 1186 1187 /* Grab the first contiguous region of buffer space. */ 1188 data = tp->t_outq.c_cf; 1189 cnt = ndqb(&tp->t_outq, 0); 1190 1191 if (cnt == 0) 1192 goto out; 1193 1194 ub = SIMPLEQ_FIRST(&sc->sc_obuff_free); 1195 if (ub == NULL) { 1196 SET(tp->t_state, TS_BUSY); 1197 goto out; 1198 } 1199 1200 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_free, ub_link); 1201 1202 if (SIMPLEQ_FIRST(&sc->sc_obuff_free) == NULL) 1203 SET(tp->t_state, TS_BUSY); 1204 1205 if (cnt > sc->sc_obufsize) 1206 cnt = sc->sc_obufsize; 1207 1208 if (sc->sc_methods->ucom_write != NULL) 1209 sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno, 1210 ub->ub_data, data, &cnt); 1211 else 1212 memcpy(ub->ub_data, data, cnt); 1213 1214 ub->ub_len = cnt; 1215 ub->ub_index = 0; 1216 1217 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_full, ub, ub_link); 1218 1219 softint_schedule(sc->sc_si); 1220 1221 out: 1222 return; 1223 } 1224 1225 void 1226 ucomstop(struct tty *tp, int flag) 1227 { 1228 #if 0 1229 struct ucom_softc *sc = 1230 device_lookup_private(&ucom_cd, UCOMUNIT(tp->t_dev)); 1231 1232 mutex_enter(&sc->sc_lock); 1233 mutex_spin_enter(&tty_lock); 1234 if (ISSET(tp->t_state, TS_BUSY)) { 1235 /* obuff_full -> obuff_free? */ 1236 /* sc->sc_tx_stopped = 1; */ 1237 if (!ISSET(tp->t_state, TS_TTSTOP)) 1238 SET(tp->t_state, TS_FLUSH); 1239 } 1240 mutex_spin_exit(&tty_lock); 1241 mutex_exit(&sc->sc_lock); 1242 #endif 1243 } 1244 1245 static void 1246 ucom_write_status(struct ucom_softc *sc, struct ucom_buffer *ub, 1247 usbd_status err) 1248 { 1249 struct tty *tp = sc->sc_tty; 1250 uint32_t cc = ub->ub_len; 1251 1252 KASSERT(mutex_owned(&sc->sc_lock)); 1253 1254 switch (err) { 1255 case USBD_IN_PROGRESS: 1256 ub->ub_index = ub->ub_len; 1257 break; 1258 case USBD_STALLED: 1259 ub->ub_index = 0; 1260 softint_schedule(sc->sc_si); 1261 break; 1262 case USBD_NORMAL_COMPLETION: 1263 usbd_get_xfer_status(ub->ub_xfer, NULL, NULL, &cc, NULL); 1264 rnd_add_uint32(&sc->sc_rndsource, cc); 1265 /*FALLTHROUGH*/ 1266 default: 1267 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_full, ub_link); 1268 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link); 1269 cc -= sc->sc_opkthdrlen; 1270 1271 mutex_spin_enter(&tty_lock); 1272 CLR(tp->t_state, TS_BUSY); 1273 if (ISSET(tp->t_state, TS_FLUSH)) 1274 CLR(tp->t_state, TS_FLUSH); 1275 else 1276 ndflush(&tp->t_outq, cc); 1277 mutex_spin_exit(&tty_lock); 1278 1279 if (err != USBD_CANCELLED && err != USBD_IOERROR && 1280 !sc->sc_dying) { 1281 if ((ub = SIMPLEQ_FIRST(&sc->sc_obuff_full)) != NULL) 1282 ucom_submit_write(sc, ub); 1283 1284 mutex_spin_enter(&tty_lock); 1285 (*tp->t_linesw->l_start)(tp); 1286 mutex_spin_exit(&tty_lock); 1287 } 1288 break; 1289 } 1290 } 1291 1292 static void 1293 ucom_submit_write(struct ucom_softc *sc, struct ucom_buffer *ub) 1294 { 1295 1296 KASSERT(mutex_owned(&sc->sc_lock)); 1297 1298 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, ub->ub_len, 1299 0, USBD_NO_TIMEOUT, ucomwritecb); 1300 1301 ucom_write_status(sc, ub, usbd_transfer(ub->ub_xfer)); 1302 } 1303 1304 static void 1305 ucomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status) 1306 { 1307 struct ucom_softc *sc = (struct ucom_softc *)p; 1308 1309 mutex_enter(&sc->sc_lock); 1310 ucom_write_status(sc, SIMPLEQ_FIRST(&sc->sc_obuff_full), status); 1311 mutex_exit(&sc->sc_lock); 1312 1313 } 1314 1315 static void 1316 ucom_softintr(void *arg) 1317 { 1318 struct ucom_softc *sc = arg; 1319 struct tty *tp = sc->sc_tty; 1320 struct ucom_buffer *ub; 1321 1322 mutex_enter(&sc->sc_lock); 1323 mutex_enter(&tty_lock); 1324 if (!ISSET(tp->t_state, TS_ISOPEN)) { 1325 mutex_exit(&tty_lock); 1326 mutex_exit(&sc->sc_lock); 1327 return; 1328 } 1329 mutex_exit(&tty_lock); 1330 1331 ub = SIMPLEQ_FIRST(&sc->sc_obuff_full); 1332 1333 if (ub != NULL && ub->ub_index == 0) 1334 ucom_submit_write(sc, ub); 1335 1336 if (sc->sc_rx_unblock) 1337 ucom_read_complete(sc); 1338 1339 mutex_exit(&sc->sc_lock); 1340 } 1341 1342 static void 1343 ucom_read_complete(struct ucom_softc *sc) 1344 { 1345 int (*rint)(int, struct tty *); 1346 struct ucom_buffer *ub; 1347 struct tty *tp; 1348 1349 KASSERT(mutex_owned(&sc->sc_lock)); 1350 1351 tp = sc->sc_tty; 1352 rint = tp->t_linesw->l_rint; 1353 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full); 1354 1355 while (ub != NULL && !sc->sc_rx_stopped) { 1356 1357 /* XXX ttyinput takes tty_lock */ 1358 while (ub->ub_index < ub->ub_len && !sc->sc_rx_stopped) { 1359 /* Give characters to tty layer. */ 1360 if ((*rint)(ub->ub_data[ub->ub_index], tp) == -1) { 1361 /* Overflow: drop remainder */ 1362 ub->ub_index = ub->ub_len; 1363 } else 1364 ub->ub_index++; 1365 } 1366 1367 if (ub->ub_index == ub->ub_len) { 1368 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_full, ub_link); 1369 1370 ucomsubmitread(sc, ub); 1371 1372 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full); 1373 } 1374 } 1375 1376 sc->sc_rx_unblock = (ub != NULL); 1377 } 1378 1379 static usbd_status 1380 ucomsubmitread(struct ucom_softc *sc, struct ucom_buffer *ub) 1381 { 1382 usbd_status err; 1383 1384 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, sc->sc_ibufsize, 1385 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ucomreadcb); 1386 1387 if ((err = usbd_transfer(ub->ub_xfer)) != USBD_IN_PROGRESS) { 1388 /* XXX: Recover from this, please! */ 1389 printf("ucomsubmitread: err=%s\n", usbd_errstr(err)); 1390 return err; 1391 } 1392 1393 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_empty, ub, ub_link); 1394 1395 return USBD_NORMAL_COMPLETION; 1396 } 1397 1398 static void 1399 ucomreadcb(struct usbd_xfer *xfer, void *p, usbd_status status) 1400 { 1401 struct ucom_softc *sc = (struct ucom_softc *)p; 1402 struct tty *tp = sc->sc_tty; 1403 struct ucom_buffer *ub; 1404 uint32_t cc; 1405 u_char *cp; 1406 1407 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1408 1409 if (status == USBD_CANCELLED) 1410 return; 1411 1412 mutex_enter(&sc->sc_lock); 1413 if (status == USBD_IOERROR || 1414 sc->sc_dying) { 1415 DPRINTF("dying", 0, 0, 0, 0); 1416 /* Send something to wake upper layer */ 1417 (tp->t_linesw->l_rint)('\n', tp); 1418 mutex_spin_enter(&tty_lock); /* XXX */ 1419 ttwakeup(tp); 1420 mutex_spin_exit(&tty_lock); /* XXX */ 1421 mutex_exit(&sc->sc_lock); 1422 return; 1423 } 1424 1425 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_empty); 1426 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_empty, ub_link); 1427 1428 if (status == USBD_STALLED) { 1429 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); 1430 ucomsubmitread(sc, ub); 1431 mutex_exit(&sc->sc_lock); 1432 return; 1433 } 1434 1435 if (status != USBD_NORMAL_COMPLETION) { 1436 printf("ucomreadcb: wonky status=%s\n", usbd_errstr(status)); 1437 mutex_exit(&sc->sc_lock); 1438 return; 1439 } 1440 1441 usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL); 1442 1443 #ifdef UCOM_DEBUG 1444 /* This is triggered by uslsa(4) occasionally. */ 1445 if ((ucomdebug > 0) && (cc == 0)) { 1446 device_printf(sc->sc_dev, "ucomreadcb: zero length xfer!\n"); 1447 } 1448 #endif 1449 1450 KDASSERT(cp == ub->ub_data); 1451 1452 rnd_add_uint32(&sc->sc_rndsource, cc); 1453 1454 if (sc->sc_opening) { 1455 ucomsubmitread(sc, ub); 1456 mutex_exit(&sc->sc_lock); 1457 return; 1458 } 1459 1460 if (sc->sc_methods->ucom_read != NULL) { 1461 sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno, 1462 &cp, &cc); 1463 ub->ub_index = (u_int)(cp - ub->ub_data); 1464 } else 1465 ub->ub_index = 0; 1466 1467 ub->ub_len = cc; 1468 1469 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_full, ub, ub_link); 1470 1471 ucom_read_complete(sc); 1472 mutex_exit(&sc->sc_lock); 1473 } 1474 1475 static void 1476 ucom_cleanup(struct ucom_softc *sc) 1477 { 1478 1479 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1480 1481 DPRINTF("aborting pipes", 0, 0, 0, 0); 1482 1483 KASSERT(mutex_owned(&sc->sc_lock)); 1484 1485 ucom_shutdown(sc); 1486 if (sc->sc_bulkin_pipe != NULL) { 1487 usbd_abort_pipe(sc->sc_bulkin_pipe); 1488 } 1489 if (sc->sc_bulkout_pipe != NULL) { 1490 usbd_abort_pipe(sc->sc_bulkout_pipe); 1491 } 1492 } 1493 1494 #endif /* NUCOM > 0 */ 1495 1496 int 1497 ucomprint(void *aux, const char *pnp) 1498 { 1499 struct ucom_attach_args *ucaa = aux; 1500 1501 if (pnp) 1502 aprint_normal("ucom at %s", pnp); 1503 if (ucaa->ucaa_portno != UCOM_UNK_PORTNO) 1504 aprint_normal(" portno %d", ucaa->ucaa_portno); 1505 return UNCONF; 1506 } 1507 1508 int 1509 ucomsubmatch(device_t parent, cfdata_t cf, 1510 const int *ldesc, void *aux) 1511 { 1512 struct ucom_attach_args *ucaa = aux; 1513 1514 if (ucaa->ucaa_portno != UCOM_UNK_PORTNO && 1515 cf->cf_loc[UCOMBUSCF_PORTNO] != UCOMBUSCF_PORTNO_DEFAULT && 1516 cf->cf_loc[UCOMBUSCF_PORTNO] != ucaa->ucaa_portno) 1517 return 0; 1518 return config_match(parent, cf, aux); 1519 } 1520