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