1 /* $NetBSD: ucom.c,v 1.134 2022/10/26 23:48:43 riastradh 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.134 2022/10/26 23:48:43 riastradh 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 #define ucom_unit tty_unit 126 127 /* 128 * XXX: We can submit multiple input/output buffers to the usb stack 129 * to improve throughput, but the usb stack is too lame to deal with this 130 * in a number of places. 131 */ 132 #define UCOM_IN_BUFFS 1 133 #define UCOM_OUT_BUFFS 1 134 135 struct ucom_buffer { 136 SIMPLEQ_ENTRY(ucom_buffer) ub_link; 137 struct usbd_xfer *ub_xfer; 138 u_char *ub_data; 139 u_int ub_len; 140 u_int ub_index; 141 }; 142 143 struct ucom_softc { 144 device_t sc_dev; /* base device */ 145 146 struct usbd_device * sc_udev; /* USB device */ 147 struct usbd_interface * sc_iface; /* data interface */ 148 149 int sc_bulkin_no; /* bulk in endpoint address */ 150 struct usbd_pipe * sc_bulkin_pipe;/* bulk in pipe */ 151 u_int sc_ibufsize; /* read buffer size */ 152 u_int sc_ibufsizepad; /* read buffer size padded */ 153 struct ucom_buffer sc_ibuff[UCOM_IN_BUFFS]; 154 SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_empty; 155 SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_full; 156 157 int sc_bulkout_no; /* bulk out endpoint address */ 158 struct usbd_pipe * sc_bulkout_pipe;/* bulk out pipe */ 159 u_int sc_obufsize; /* write buffer size */ 160 u_int sc_opkthdrlen; /* header length of */ 161 struct ucom_buffer sc_obuff[UCOM_OUT_BUFFS]; 162 SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_free; 163 SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_full; 164 165 void *sc_si; 166 167 const struct ucom_methods *sc_methods; 168 void *sc_parent; 169 int sc_portno; 170 171 struct tty *sc_tty; /* our tty */ 172 u_char sc_lsr; 173 u_char sc_msr; 174 u_char sc_mcr; 175 volatile u_char sc_rx_stopped; 176 u_char sc_rx_unblock; 177 u_char sc_tx_stopped; 178 int sc_swflags; 179 180 enum ucom_state { 181 UCOM_DEAD, 182 UCOM_ATTACHED, 183 UCOM_OPENING, 184 UCOM_OPEN 185 } sc_state; 186 bool sc_closing; /* software is closing */ 187 bool sc_dying; /* hardware is gone */ 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 196 struct timeval sc_hup_time; 197 }; 198 199 dev_type_open(ucomopen); 200 dev_type_cancel(ucomcancel); 201 dev_type_close(ucomclose); 202 dev_type_read(ucomread); 203 dev_type_write(ucomwrite); 204 dev_type_ioctl(ucomioctl); 205 dev_type_stop(ucomstop); 206 dev_type_tty(ucomtty); 207 dev_type_poll(ucompoll); 208 209 const struct cdevsw ucom_cdevsw = { 210 .d_open = ucomopen, 211 .d_cancel = ucomcancel, 212 .d_close = ucomclose, 213 .d_read = ucomread, 214 .d_write = ucomwrite, 215 .d_ioctl = ucomioctl, 216 .d_stop = ucomstop, 217 .d_tty = ucomtty, 218 .d_poll = ucompoll, 219 .d_mmap = nommap, 220 .d_kqfilter = ttykqfilter, 221 .d_discard = nodiscard, 222 .d_cfdriver = &ucom_cd, 223 .d_devtounit = ucom_unit, 224 .d_flag = D_TTY | D_MPSAFE 225 }; 226 227 static void ucom_cleanup(struct ucom_softc *, int); 228 static int ucomparam(struct tty *, struct termios *); 229 static int ucomhwiflow(struct tty *, int); 230 static void ucomstart(struct tty *); 231 static void ucom_shutdown(struct ucom_softc *); 232 static void ucom_dtr(struct ucom_softc *, int); 233 static void ucom_rts(struct ucom_softc *, int); 234 static void ucom_break(struct ucom_softc *, int); 235 static void tiocm_to_ucom(struct ucom_softc *, u_long, int); 236 static int ucom_to_tiocm(struct ucom_softc *); 237 238 static void ucomreadcb(struct usbd_xfer *, void *, usbd_status); 239 static void ucom_submit_write(struct ucom_softc *, struct ucom_buffer *); 240 static void ucom_write_status(struct ucom_softc *, struct ucom_buffer *, 241 usbd_status); 242 243 static void ucomwritecb(struct usbd_xfer *, void *, usbd_status); 244 static void ucom_read_complete(struct ucom_softc *); 245 static int ucomsubmitread(struct ucom_softc *, struct ucom_buffer *); 246 static void ucom_softintr(void *); 247 248 int ucom_match(device_t, cfdata_t, void *); 249 void ucom_attach(device_t, device_t, void *); 250 int ucom_detach(device_t, int); 251 252 CFATTACH_DECL_NEW(ucom, sizeof(struct ucom_softc), ucom_match, ucom_attach, 253 ucom_detach, NULL); 254 255 int 256 ucom_match(device_t parent, cfdata_t match, void *aux) 257 { 258 return 1; 259 } 260 261 void 262 ucom_attach(device_t parent, device_t self, void *aux) 263 { 264 struct ucom_softc *sc = device_private(self); 265 struct ucom_attach_args *ucaa = aux; 266 267 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 268 269 if (ucaa->ucaa_info != NULL) 270 aprint_normal(": %s", ucaa->ucaa_info); 271 aprint_normal("\n"); 272 273 prop_dictionary_set_int32(device_properties(self), "port", 274 ucaa->ucaa_portno); 275 276 sc->sc_dev = self; 277 sc->sc_udev = ucaa->ucaa_device; 278 sc->sc_iface = ucaa->ucaa_iface; 279 sc->sc_bulkout_no = ucaa->ucaa_bulkout; 280 sc->sc_bulkin_no = ucaa->ucaa_bulkin; 281 sc->sc_ibufsize = ucaa->ucaa_ibufsize; 282 sc->sc_ibufsizepad = ucaa->ucaa_ibufsizepad; 283 sc->sc_obufsize = ucaa->ucaa_obufsize; 284 sc->sc_opkthdrlen = ucaa->ucaa_opkthdrlen; 285 sc->sc_methods = ucaa->ucaa_methods; 286 sc->sc_parent = ucaa->ucaa_arg; 287 sc->sc_portno = ucaa->ucaa_portno; 288 289 sc->sc_lsr = 0; 290 sc->sc_msr = 0; 291 sc->sc_mcr = 0; 292 sc->sc_tx_stopped = 0; 293 sc->sc_swflags = 0; 294 sc->sc_closing = false; 295 sc->sc_dying = false; 296 sc->sc_state = UCOM_DEAD; 297 298 sc->sc_si = softint_establish(SOFTINT_USB, ucom_softintr, sc); 299 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); 300 cv_init(&sc->sc_statecv, "ucomstate"); 301 302 rnd_attach_source(&sc->sc_rndsource, device_xname(sc->sc_dev), 303 RND_TYPE_TTY, RND_FLAG_DEFAULT); 304 305 SIMPLEQ_INIT(&sc->sc_ibuff_empty); 306 SIMPLEQ_INIT(&sc->sc_ibuff_full); 307 SIMPLEQ_INIT(&sc->sc_obuff_free); 308 SIMPLEQ_INIT(&sc->sc_obuff_full); 309 310 memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff)); 311 memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff)); 312 313 DPRINTF("open pipes in=%jd out=%jd", 314 sc->sc_bulkin_no, sc->sc_bulkout_no, 0, 0); 315 316 struct ucom_buffer *ub; 317 usbd_status err; 318 int error; 319 320 /* Open the bulk pipes */ 321 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 322 USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe); 323 if (err) { 324 DPRINTF("open bulk in error (addr %jd), err=%jd", 325 sc->sc_bulkin_no, err, 0, 0); 326 error = EIO; 327 goto fail_0; 328 } 329 /* Allocate input buffers */ 330 for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS]; 331 ub++) { 332 error = usbd_create_xfer(sc->sc_bulkin_pipe, 333 sc->sc_ibufsizepad, 0, 0, 334 &ub->ub_xfer); 335 if (error) 336 goto fail_1; 337 ub->ub_data = usbd_get_buffer(ub->ub_xfer); 338 } 339 340 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, 341 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); 342 if (err) { 343 DPRINTF("open bulk out error (addr %jd), err=%jd", 344 sc->sc_bulkout_no, err, 0, 0); 345 error = EIO; 346 goto fail_1; 347 } 348 for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS]; 349 ub++) { 350 error = usbd_create_xfer(sc->sc_bulkout_pipe, 351 sc->sc_obufsize, 0, 0, &ub->ub_xfer); 352 if (error) 353 goto fail_2; 354 ub->ub_data = usbd_get_buffer(ub->ub_xfer); 355 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link); 356 } 357 358 struct tty *tp = tty_alloc(); 359 tp->t_oproc = ucomstart; 360 tp->t_param = ucomparam; 361 tp->t_hwiflow = ucomhwiflow; 362 sc->sc_tty = tp; 363 364 DPRINTF("tty_attach %#jx", (uintptr_t)tp, 0, 0, 0); 365 tty_attach(tp); 366 367 if (!pmf_device_register(self, NULL, NULL)) 368 aprint_error_dev(self, "couldn't establish power handler\n"); 369 370 sc->sc_state = UCOM_ATTACHED; 371 return; 372 373 fail_2: 374 for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS]; 375 ub++) { 376 if (ub->ub_xfer) 377 usbd_destroy_xfer(ub->ub_xfer); 378 } 379 usbd_close_pipe(sc->sc_bulkout_pipe); 380 sc->sc_bulkout_pipe = NULL; 381 382 fail_1: 383 for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS]; 384 ub++) { 385 if (ub->ub_xfer) 386 usbd_destroy_xfer(ub->ub_xfer); 387 } 388 usbd_close_pipe(sc->sc_bulkin_pipe); 389 sc->sc_bulkin_pipe = NULL; 390 391 fail_0: 392 aprint_error_dev(self, "attach failed, error=%d\n", error); 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 /* Prevent new opens from hanging. */ 410 mutex_enter(&sc->sc_lock); 411 sc->sc_dying = true; 412 mutex_exit(&sc->sc_lock); 413 414 pmf_device_deregister(self); 415 416 /* tty is now off. */ 417 if (tp != NULL) { 418 ttylock(tp); 419 CLR(tp->t_state, TS_CARR_ON); 420 CLR(tp->t_cflag, CLOCAL | MDMBUF); 421 ttyunlock(tp); 422 } 423 424 /* locate the major number */ 425 maj = cdevsw_lookup_major(&ucom_cdevsw); 426 427 /* Nuke the vnodes for any open instances. */ 428 mn = device_unit(self); 429 DPRINTF("maj=%jd mn=%jd", maj, mn, 0, 0); 430 vdevgone(maj, mn, mn, VCHR); 431 vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR); 432 vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR); 433 434 softint_disestablish(sc->sc_si); 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_statecv); 468 469 return 0; 470 } 471 472 void 473 ucom_shutdown(struct ucom_softc *sc) 474 { 475 struct tty *tp = sc->sc_tty; 476 477 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 478 479 /* 480 * Hang up if necessary. Wait a bit, so the other side has time to 481 * notice even if we immediately open the port again. 482 */ 483 if (ISSET(tp->t_cflag, HUPCL)) { 484 ucom_dtr(sc, 0); 485 mutex_enter(&sc->sc_lock); 486 microuptime(&sc->sc_hup_time); 487 sc->sc_hup_time.tv_sec++; 488 mutex_exit(&sc->sc_lock); 489 } 490 } 491 492 /* 493 * ucomopen(dev, flag, mode, l) 494 * 495 * Called when anyone tries to open /dev/ttyU? for an existing 496 * ucom? instance that has completed attach. The attach may have 497 * failed, though, or there may be concurrent detach or close in 498 * progress, so fail if attach failed (no sc_tty) or detach has 499 * begun (sc_dying), or wait if there's a concurrent close in 500 * progress before reopening. 501 */ 502 int 503 ucomopen(dev_t dev, int flag, int mode, struct lwp *l) 504 { 505 const int unit = UCOMUNIT(dev); 506 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 507 int error = 0; 508 509 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 510 511 mutex_enter(&sc->sc_lock); 512 if (sc->sc_dying) { 513 DPRINTF("... dying", 0, 0, 0, 0); 514 mutex_exit(&sc->sc_lock); 515 return ENXIO; 516 } 517 518 if (!device_is_active(sc->sc_dev)) { 519 mutex_exit(&sc->sc_lock); 520 return ENXIO; 521 } 522 523 struct tty *tp = sc->sc_tty; 524 if (tp == NULL) { 525 DPRINTF("... not attached", 0, 0, 0, 0); 526 mutex_exit(&sc->sc_lock); 527 return ENXIO; 528 } 529 530 DPRINTF("unit=%jd, tp=%#jx", unit, (uintptr_t)tp, 0, 0); 531 532 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) { 533 mutex_exit(&sc->sc_lock); 534 return EBUSY; 535 } 536 537 /* 538 * If the previous use had set DTR on close, wait up to one 539 * second for the other side to notice we hung up. After 540 * sleeping, the tty may have been revoked, so restart the 541 * whole operation. 542 * 543 * XXX The wchan is not ttclose but maybe should be. 544 */ 545 if (timerisset(&sc->sc_hup_time)) { 546 struct timeval now, delta; 547 int ms, ticks; 548 549 microuptime(&now); 550 if (timercmp(&now, &sc->sc_hup_time, <)) { 551 timersub(&sc->sc_hup_time, &now, &delta); 552 ms = MIN(INT_MAX - 1000, delta.tv_sec*1000); 553 ms += howmany(delta.tv_usec, 1000); 554 ticks = MAX(1, MIN(INT_MAX, mstohz(ms))); 555 error = cv_timedwait_sig(&sc->sc_statecv, &sc->sc_lock, 556 ticks); 557 mutex_exit(&sc->sc_lock); 558 return error ? error : ERESTART; 559 } 560 } 561 562 /* 563 * Wait while the device is initialized by the 564 * first opener or cleaned up by the last closer. 565 */ 566 enum ucom_state state = sc->sc_state; 567 if (state == UCOM_OPENING || sc->sc_closing) { 568 if (flag & FNONBLOCK) 569 error = EWOULDBLOCK; 570 else 571 error = cv_wait_sig(&sc->sc_statecv, &sc->sc_lock); 572 mutex_exit(&sc->sc_lock); 573 return error ? error : ERESTART; 574 } 575 KASSERTMSG(state == UCOM_OPEN || state == UCOM_ATTACHED, 576 "state is %d", state); 577 578 /* 579 * If this is the first open, then make sure the pipes are 580 * running and perform any initialization needed. 581 */ 582 bool firstopen = (state == UCOM_ATTACHED); 583 if (firstopen) { 584 KASSERT(!ISSET(tp->t_state, TS_ISOPEN)); 585 KASSERT(tp->t_wopen == 0); 586 587 tp->t_dev = dev; 588 sc->sc_state = UCOM_OPENING; 589 mutex_exit(&sc->sc_lock); 590 591 if (sc->sc_methods->ucom_open != NULL) { 592 error = sc->sc_methods->ucom_open(sc->sc_parent, 593 sc->sc_portno); 594 if (error) 595 goto bad; 596 } 597 598 ucom_status_change(sc); 599 600 /* Clear PPS capture state on first open. */ 601 mutex_spin_enter(&timecounter_lock); 602 memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state)); 603 sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; 604 pps_init(&sc->sc_pps_state); 605 mutex_spin_exit(&timecounter_lock); 606 607 /* 608 * Initialize the termios status to the defaults. Add in the 609 * sticky bits from TIOCSFLAGS. 610 */ 611 struct termios t; 612 613 t.c_ispeed = 0; 614 t.c_ospeed = TTYDEF_SPEED; 615 t.c_cflag = TTYDEF_CFLAG; 616 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 617 SET(t.c_cflag, CLOCAL); 618 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 619 SET(t.c_cflag, CRTSCTS); 620 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 621 SET(t.c_cflag, MDMBUF); 622 /* Make sure ucomparam() will do something. */ 623 tp->t_ospeed = 0; 624 (void) ucomparam(tp, &t); 625 tp->t_iflag = TTYDEF_IFLAG; 626 tp->t_oflag = TTYDEF_OFLAG; 627 tp->t_lflag = TTYDEF_LFLAG; 628 ttychars(tp); 629 ttsetwater(tp); 630 631 /* 632 * Turn on DTR. We must always do this, even if carrier is not 633 * present, because otherwise we'd have to use TIOCSDTR 634 * immediately after setting CLOCAL, which applications do not 635 * expect. We always assert DTR while the device is open 636 * unless explicitly requested to deassert it. Ditto RTS. 637 */ 638 ucom_dtr(sc, 1); 639 ucom_rts(sc, 1); 640 641 mutex_enter(&sc->sc_lock); 642 sc->sc_rx_unblock = 0; 643 sc->sc_rx_stopped = 0; 644 sc->sc_tx_stopped = 0; 645 646 for (size_t i = 0; i < UCOM_IN_BUFFS; i++) { 647 struct ucom_buffer *ub = &sc->sc_ibuff[i]; 648 error = ucomsubmitread(sc, ub); 649 if (error) { 650 mutex_exit(&sc->sc_lock); 651 goto bad; 652 } 653 } 654 } 655 mutex_exit(&sc->sc_lock); 656 657 DPRINTF("unit=%jd, tp=%#jx dialout %jd nonblock %jd", unit, 658 (uintptr_t)tp, !!UCOMDIALOUT(dev), !!ISSET(flag, O_NONBLOCK)); 659 error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); 660 if (error) 661 goto bad; 662 663 error = (*tp->t_linesw->l_open)(dev, tp); 664 if (error) 665 goto bad; 666 667 /* 668 * Success! If this was the first open, notify waiters that 669 * the tty is open for business. 670 */ 671 if (firstopen) { 672 mutex_enter(&sc->sc_lock); 673 KASSERT(sc->sc_state == UCOM_OPENING); 674 sc->sc_state = UCOM_OPEN; 675 cv_broadcast(&sc->sc_statecv); 676 mutex_exit(&sc->sc_lock); 677 } 678 return 0; 679 680 bad: 681 /* 682 * Failure! If this was the first open, hang up, abort pipes, 683 * and notify waiters that we're not opening after all. 684 */ 685 if (firstopen) { 686 ucom_cleanup(sc, flag); 687 688 mutex_enter(&sc->sc_lock); 689 KASSERT(sc->sc_state == UCOM_OPENING); 690 sc->sc_state = UCOM_ATTACHED; 691 cv_broadcast(&sc->sc_statecv); 692 mutex_exit(&sc->sc_lock); 693 } 694 return error; 695 } 696 697 /* 698 * ucomcancel(dev, flag, mode, l) 699 * 700 * Called on revoke or last close. Must interrupt any pending I/O 701 * operations and make them fail promptly; once they have all 702 * finished (except possibly new opens), ucomclose will be called. 703 * We set sc_closing to block new opens until ucomclose runs. 704 */ 705 int 706 ucomcancel(dev_t dev, int flag, int mode, struct lwp *l) 707 { 708 const int unit = UCOMUNIT(dev); 709 struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit); 710 711 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 712 713 DPRINTF("unit=%jd", UCOMUNIT(dev), 0, 0, 0); 714 715 /* 716 * This can run at any time before ucomclose on any device 717 * node, even if never attached or if attach failed, so we may 718 * not have a softc or a tty. 719 */ 720 if (sc == NULL) 721 return 0; 722 struct tty *tp = sc->sc_tty; 723 if (tp == NULL) 724 return 0; 725 726 /* 727 * Mark the device closing so opens block until we're done 728 * closing. Wake them up so they start over at the top -- if 729 * we're closing because we're detaching, they need to wake up 730 * and notice it's time to fail. 731 */ 732 mutex_enter(&sc->sc_lock); 733 sc->sc_closing = true; 734 cv_broadcast(&sc->sc_statecv); 735 mutex_exit(&sc->sc_lock); 736 737 /* 738 * Cancel any pending tty I/O operations, causing them to wake 739 * up and fail promptly, and preventing any new ones from 740 * starting to wait until we have finished closing. 741 */ 742 ttycancel(tp); 743 744 return 0; 745 } 746 747 /* 748 * ucomclose(dev, flag, mode, l) 749 * 750 * Called after ucomcancel, when all prior operations on the /dev 751 * node have completed. Only new opens may be in progress at this 752 * point, but they will block until sc_closing is set to false. 753 */ 754 int 755 ucomclose(dev_t dev, int flag, int mode, struct lwp *l) 756 { 757 const int unit = UCOMUNIT(dev); 758 struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit); 759 int error = 0; 760 761 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 762 763 DPRINTF("unit=%jd", UCOMUNIT(dev), 0, 0, 0); 764 765 /* 766 * This can run at any time after ucomcancel on any device 767 * node, even if never attached or if attach failed, so we may 768 * not have a softc or a tty. 769 */ 770 if (sc == NULL) 771 return 0; 772 struct tty *tp = sc->sc_tty; 773 if (tp == NULL) 774 return 0; 775 776 /* 777 * Close the tty, causing anyone waiting for it to wake, and 778 * hang up the phone. 779 */ 780 ucom_cleanup(sc, flag); 781 782 /* 783 * ttyclose should have cleared TS_ISOPEN and interrupted all 784 * pending opens, which should have completed by now. 785 */ 786 ttylock(tp); 787 KASSERT(!ISSET(tp->t_state, TS_ISOPEN)); 788 KASSERT(tp->t_wopen == 0); 789 ttyunlock(tp); 790 791 /* 792 * Close any device-specific state. 793 */ 794 if (sc->sc_methods->ucom_close != NULL) { 795 sc->sc_methods->ucom_close(sc->sc_parent, 796 sc->sc_portno); 797 } 798 799 /* 800 * We're now closed. Can reopen after this point, so resume 801 * transfers, mark us no longer closing, and notify anyone 802 * waiting in open. The state may be OPEN or ATTACHED at this 803 * point -- OPEN if the device was already open when we closed 804 * it, ATTACHED if we interrupted it in the process of opening. 805 */ 806 mutex_enter(&sc->sc_lock); 807 KASSERTMSG(sc->sc_state == UCOM_ATTACHED || sc->sc_state == UCOM_OPEN, 808 "%s sc=%p state=%d", device_xname(sc->sc_dev), sc, sc->sc_state); 809 KASSERT(sc->sc_closing); 810 sc->sc_state = UCOM_ATTACHED; 811 sc->sc_closing = false; 812 cv_broadcast(&sc->sc_statecv); 813 mutex_exit(&sc->sc_lock); 814 815 return error; 816 } 817 818 int 819 ucomread(dev_t dev, struct uio *uio, int flag) 820 { 821 const int unit = UCOMUNIT(dev); 822 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 823 struct tty *tp = sc->sc_tty; 824 825 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 826 827 return (*tp->t_linesw->l_read)(tp, uio, flag); 828 } 829 830 int 831 ucomwrite(dev_t dev, struct uio *uio, int flag) 832 { 833 const int unit = UCOMUNIT(dev); 834 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 835 struct tty *tp = sc->sc_tty; 836 837 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 838 839 return (*tp->t_linesw->l_write)(tp, uio, flag); 840 } 841 842 int 843 ucompoll(dev_t dev, int events, struct lwp *l) 844 { 845 const int unit = UCOMUNIT(dev); 846 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 847 struct tty *tp = sc->sc_tty; 848 849 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 850 851 return (*tp->t_linesw->l_poll)(tp, events, l); 852 } 853 854 struct tty * 855 ucomtty(dev_t dev) 856 { 857 const int unit = UCOMUNIT(dev); 858 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 859 860 return sc->sc_tty; 861 } 862 863 int 864 ucomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 865 { 866 const int unit = UCOMUNIT(dev); 867 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 868 struct tty *tp = sc->sc_tty; 869 int error; 870 871 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 872 873 DPRINTF("cmd=0x%08jx", cmd, 0, 0, 0); 874 875 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 876 if (error != EPASSTHROUGH) 877 return error; 878 879 error = ttioctl(tp, cmd, data, flag, l); 880 if (error != EPASSTHROUGH) 881 return error; 882 883 if (sc->sc_methods->ucom_ioctl != NULL) { 884 error = sc->sc_methods->ucom_ioctl(sc->sc_parent, 885 sc->sc_portno, cmd, data, flag, l->l_proc); 886 if (error != EPASSTHROUGH) 887 return error; 888 } 889 890 error = 0; 891 892 DPRINTF("our cmd=0x%08jx", cmd, 0, 0, 0); 893 894 switch (cmd) { 895 case TIOCSBRK: 896 ucom_break(sc, 1); 897 break; 898 899 case TIOCCBRK: 900 ucom_break(sc, 0); 901 break; 902 903 case TIOCSDTR: 904 ucom_dtr(sc, 1); 905 break; 906 907 case TIOCCDTR: 908 ucom_dtr(sc, 0); 909 break; 910 911 case TIOCGFLAGS: 912 mutex_enter(&sc->sc_lock); 913 *(int *)data = sc->sc_swflags; 914 mutex_exit(&sc->sc_lock); 915 break; 916 917 case TIOCSFLAGS: 918 error = kauth_authorize_device_tty(l->l_cred, 919 KAUTH_DEVICE_TTY_PRIVSET, tp); 920 if (error) 921 break; 922 mutex_enter(&sc->sc_lock); 923 sc->sc_swflags = *(int *)data; 924 mutex_exit(&sc->sc_lock); 925 break; 926 927 case TIOCMSET: 928 case TIOCMBIS: 929 case TIOCMBIC: 930 tiocm_to_ucom(sc, cmd, *(int *)data); 931 break; 932 933 case TIOCMGET: 934 *(int *)data = ucom_to_tiocm(sc); 935 break; 936 937 case PPS_IOC_CREATE: 938 case PPS_IOC_DESTROY: 939 case PPS_IOC_GETPARAMS: 940 case PPS_IOC_SETPARAMS: 941 case PPS_IOC_GETCAP: 942 case PPS_IOC_FETCH: 943 #ifdef PPS_SYNC 944 case PPS_IOC_KCBIND: 945 #endif 946 mutex_spin_enter(&timecounter_lock); 947 error = pps_ioctl(cmd, data, &sc->sc_pps_state); 948 mutex_spin_exit(&timecounter_lock); 949 break; 950 951 default: 952 error = EPASSTHROUGH; 953 break; 954 } 955 956 return error; 957 } 958 959 static void 960 tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits) 961 { 962 u_char combits; 963 964 combits = 0; 965 if (ISSET(ttybits, TIOCM_DTR)) 966 SET(combits, UMCR_DTR); 967 if (ISSET(ttybits, TIOCM_RTS)) 968 SET(combits, UMCR_RTS); 969 970 mutex_enter(&sc->sc_lock); 971 switch (how) { 972 case TIOCMBIC: 973 CLR(sc->sc_mcr, combits); 974 break; 975 976 case TIOCMBIS: 977 SET(sc->sc_mcr, combits); 978 break; 979 980 case TIOCMSET: 981 CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS); 982 SET(sc->sc_mcr, combits); 983 break; 984 } 985 u_char mcr = sc->sc_mcr; 986 mutex_exit(&sc->sc_lock); 987 988 if (how == TIOCMSET || ISSET(combits, UMCR_DTR)) 989 ucom_dtr(sc, (mcr & UMCR_DTR) != 0); 990 if (how == TIOCMSET || ISSET(combits, UMCR_RTS)) 991 ucom_rts(sc, (mcr & UMCR_RTS) != 0); 992 } 993 994 static int 995 ucom_to_tiocm(struct ucom_softc *sc) 996 { 997 u_char combits; 998 int ttybits = 0; 999 1000 mutex_enter(&sc->sc_lock); 1001 combits = sc->sc_mcr; 1002 if (ISSET(combits, UMCR_DTR)) 1003 SET(ttybits, TIOCM_DTR); 1004 if (ISSET(combits, UMCR_RTS)) 1005 SET(ttybits, TIOCM_RTS); 1006 1007 combits = sc->sc_msr; 1008 if (ISSET(combits, UMSR_DCD)) 1009 SET(ttybits, TIOCM_CD); 1010 if (ISSET(combits, UMSR_CTS)) 1011 SET(ttybits, TIOCM_CTS); 1012 if (ISSET(combits, UMSR_DSR)) 1013 SET(ttybits, TIOCM_DSR); 1014 if (ISSET(combits, UMSR_RI | UMSR_TERI)) 1015 SET(ttybits, TIOCM_RI); 1016 1017 #if 0 1018 XXX; 1019 if (sc->sc_ier != 0) 1020 SET(ttybits, TIOCM_LE); 1021 #endif 1022 mutex_exit(&sc->sc_lock); 1023 1024 return ttybits; 1025 } 1026 1027 static void 1028 ucom_break(struct ucom_softc *sc, int onoff) 1029 { 1030 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1031 1032 DPRINTF("onoff=%jd", onoff, 0, 0, 0); 1033 1034 if (sc->sc_methods->ucom_set != NULL) 1035 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 1036 UCOM_SET_BREAK, onoff); 1037 } 1038 1039 static void 1040 ucom_dtr(struct ucom_softc *sc, int onoff) 1041 { 1042 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1043 1044 DPRINTF("onoff=%jd", onoff, 0, 0, 0); 1045 1046 if (sc->sc_methods->ucom_set != NULL) 1047 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 1048 UCOM_SET_DTR, onoff); 1049 } 1050 1051 static void 1052 ucom_rts(struct ucom_softc *sc, int onoff) 1053 { 1054 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1055 1056 DPRINTF("onoff=%jd", onoff, 0, 0, 0); 1057 1058 if (sc->sc_methods->ucom_set != NULL) 1059 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 1060 UCOM_SET_RTS, onoff); 1061 } 1062 1063 void 1064 ucom_status_change(struct ucom_softc *sc) 1065 { 1066 struct tty *tp = sc->sc_tty; 1067 1068 if (sc->sc_methods->ucom_get_status != NULL) { 1069 u_char msr, lsr; 1070 1071 sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno, 1072 &lsr, &msr); 1073 mutex_enter(&sc->sc_lock); 1074 u_char old_msr = sc->sc_msr; 1075 1076 sc->sc_lsr = lsr; 1077 sc->sc_msr = msr; 1078 mutex_exit(&sc->sc_lock); 1079 1080 if (ISSET((msr ^ old_msr), UMSR_DCD)) { 1081 mutex_spin_enter(&timecounter_lock); 1082 pps_capture(&sc->sc_pps_state); 1083 pps_event(&sc->sc_pps_state, 1084 (sc->sc_msr & UMSR_DCD) ? 1085 PPS_CAPTUREASSERT : 1086 PPS_CAPTURECLEAR); 1087 mutex_spin_exit(&timecounter_lock); 1088 1089 (*tp->t_linesw->l_modem)(tp, ISSET(msr, UMSR_DCD)); 1090 } 1091 } else { 1092 mutex_enter(&sc->sc_lock); 1093 sc->sc_lsr = 0; 1094 /* Assume DCD is present, if we have no chance to check it. */ 1095 sc->sc_msr = UMSR_DCD; 1096 mutex_exit(&sc->sc_lock); 1097 } 1098 } 1099 1100 static int 1101 ucomparam(struct tty *tp, struct termios *t) 1102 { 1103 const int unit = UCOMUNIT(tp->t_dev); 1104 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 1105 int error = 0; 1106 1107 /* XXX should take tty lock around touching tp */ 1108 1109 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1110 1111 /* Check requested parameters. */ 1112 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) { 1113 error = EINVAL; 1114 goto out; 1115 } 1116 1117 /* 1118 * For the console, always force CLOCAL and !HUPCL, so that the port 1119 * is always active. 1120 */ 1121 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) { 1122 SET(t->c_cflag, CLOCAL); 1123 CLR(t->c_cflag, HUPCL); 1124 } 1125 1126 /* 1127 * If there were no changes, don't do anything. This avoids dropping 1128 * input and improves performance when all we did was frob things like 1129 * VMIN and VTIME. 1130 */ 1131 if (tp->t_ospeed == t->c_ospeed && 1132 tp->t_cflag == t->c_cflag) { 1133 goto out; 1134 } 1135 1136 /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */ 1137 1138 /* And copy to tty. */ 1139 tp->t_ispeed = 0; 1140 tp->t_ospeed = t->c_ospeed; 1141 tp->t_cflag = t->c_cflag; 1142 1143 if (sc->sc_methods->ucom_param != NULL) { 1144 error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno, 1145 t); 1146 if (error) 1147 goto out; 1148 } 1149 1150 /* XXX worry about CHWFLOW */ 1151 1152 /* 1153 * Update the tty layer's idea of the carrier bit, in case we changed 1154 * CLOCAL or MDMBUF. We don't hang up here; we only do that by 1155 * explicit request. 1156 */ 1157 DPRINTF("l_modem", 0, 0, 0, 0); 1158 (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD)); 1159 1160 #if 0 1161 XXX what if the hardware is not open 1162 if (!ISSET(t->c_cflag, CHWFLOW)) { 1163 if (sc->sc_tx_stopped) { 1164 sc->sc_tx_stopped = 0; 1165 ucomstart(tp); 1166 } 1167 } 1168 #endif 1169 out: 1170 return error; 1171 } 1172 1173 static int 1174 ucomhwiflow(struct tty *tp, int block) 1175 { 1176 const int unit = UCOMUNIT(tp->t_dev); 1177 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 1178 int old; 1179 1180 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1181 1182 KASSERT(&sc->sc_lock); 1183 KASSERT(ttylocked(tp)); 1184 1185 old = sc->sc_rx_stopped; 1186 sc->sc_rx_stopped = (u_char)block; 1187 1188 if (old && !block) { 1189 sc->sc_rx_unblock = 1; 1190 kpreempt_disable(); 1191 softint_schedule(sc->sc_si); 1192 kpreempt_enable(); 1193 } 1194 1195 return 1; 1196 } 1197 1198 static void 1199 ucomstart(struct tty *tp) 1200 { 1201 const int unit = UCOMUNIT(tp->t_dev); 1202 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 1203 struct ucom_buffer *ub; 1204 u_char *data; 1205 int cnt; 1206 1207 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1208 1209 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 1210 goto out; 1211 if (sc->sc_tx_stopped) 1212 goto out; 1213 1214 if (!ttypull(tp)) 1215 goto out; 1216 1217 /* Grab the first contiguous region of buffer space. */ 1218 data = tp->t_outq.c_cf; 1219 cnt = ndqb(&tp->t_outq, 0); 1220 1221 if (cnt == 0) 1222 goto out; 1223 1224 ub = SIMPLEQ_FIRST(&sc->sc_obuff_free); 1225 if (ub == NULL) { 1226 SET(tp->t_state, TS_BUSY); 1227 goto out; 1228 } 1229 1230 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_free, ub_link); 1231 1232 if (SIMPLEQ_FIRST(&sc->sc_obuff_free) == NULL) 1233 SET(tp->t_state, TS_BUSY); 1234 1235 if (cnt > sc->sc_obufsize) 1236 cnt = sc->sc_obufsize; 1237 1238 if (sc->sc_methods->ucom_write != NULL) 1239 sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno, 1240 ub->ub_data, data, &cnt); 1241 else 1242 memcpy(ub->ub_data, data, cnt); 1243 1244 ub->ub_len = cnt; 1245 ub->ub_index = 0; 1246 1247 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_full, ub, ub_link); 1248 1249 kpreempt_disable(); 1250 softint_schedule(sc->sc_si); 1251 kpreempt_enable(); 1252 1253 out: 1254 DPRINTF("... done", 0, 0, 0, 0); 1255 return; 1256 } 1257 1258 void 1259 ucomstop(struct tty *tp, int flag) 1260 { 1261 #if 0 1262 const int unit = UCOMUNIT(tp->t_dev); 1263 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 1264 1265 mutex_enter(&sc->sc_lock); 1266 ttylock(tp); 1267 if (ISSET(tp->t_state, TS_BUSY)) { 1268 /* obuff_full -> obuff_free? */ 1269 /* sc->sc_tx_stopped = 1; */ 1270 if (!ISSET(tp->t_state, TS_TTSTOP)) 1271 SET(tp->t_state, TS_FLUSH); 1272 } 1273 ttyunlock(tp); 1274 mutex_exit(&sc->sc_lock); 1275 #endif 1276 } 1277 1278 static void 1279 ucom_write_status(struct ucom_softc *sc, struct ucom_buffer *ub, 1280 usbd_status err) 1281 { 1282 struct tty *tp = sc->sc_tty; 1283 uint32_t cc = ub->ub_len; 1284 1285 KASSERT(mutex_owned(&sc->sc_lock)); 1286 1287 switch (err) { 1288 case USBD_IN_PROGRESS: 1289 ub->ub_index = ub->ub_len; 1290 break; 1291 case USBD_STALLED: 1292 ub->ub_index = 0; 1293 kpreempt_disable(); 1294 softint_schedule(sc->sc_si); 1295 kpreempt_enable(); 1296 break; 1297 case USBD_NORMAL_COMPLETION: 1298 usbd_get_xfer_status(ub->ub_xfer, NULL, NULL, &cc, NULL); 1299 rnd_add_uint32(&sc->sc_rndsource, cc); 1300 /*FALLTHROUGH*/ 1301 default: 1302 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_full, ub_link); 1303 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link); 1304 cc -= sc->sc_opkthdrlen; 1305 1306 ttylock(tp); 1307 CLR(tp->t_state, TS_BUSY); 1308 if (ISSET(tp->t_state, TS_FLUSH)) 1309 CLR(tp->t_state, TS_FLUSH); 1310 else 1311 ndflush(&tp->t_outq, cc); 1312 ttyunlock(tp); 1313 1314 if (err != USBD_CANCELLED && err != USBD_IOERROR && 1315 !sc->sc_closing) { 1316 if ((ub = SIMPLEQ_FIRST(&sc->sc_obuff_full)) != NULL) 1317 ucom_submit_write(sc, ub); 1318 1319 ttylock(tp); 1320 (*tp->t_linesw->l_start)(tp); 1321 ttyunlock(tp); 1322 } 1323 break; 1324 } 1325 } 1326 1327 static void 1328 ucom_submit_write(struct ucom_softc *sc, struct ucom_buffer *ub) 1329 { 1330 1331 KASSERT(mutex_owned(&sc->sc_lock)); 1332 1333 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, ub->ub_len, 1334 0, USBD_NO_TIMEOUT, ucomwritecb); 1335 1336 ucom_write_status(sc, ub, usbd_transfer(ub->ub_xfer)); 1337 } 1338 1339 static void 1340 ucomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status) 1341 { 1342 struct ucom_softc *sc = (struct ucom_softc *)p; 1343 1344 mutex_enter(&sc->sc_lock); 1345 ucom_write_status(sc, SIMPLEQ_FIRST(&sc->sc_obuff_full), status); 1346 mutex_exit(&sc->sc_lock); 1347 1348 } 1349 1350 static void 1351 ucom_softintr(void *arg) 1352 { 1353 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1354 1355 struct ucom_softc *sc = arg; 1356 struct tty *tp = sc->sc_tty; 1357 1358 mutex_enter(&sc->sc_lock); 1359 ttylock(tp); 1360 if (!ISSET(tp->t_state, TS_ISOPEN)) { 1361 ttyunlock(tp); 1362 mutex_exit(&sc->sc_lock); 1363 return; 1364 } 1365 ttyunlock(tp); 1366 1367 struct ucom_buffer *ub = SIMPLEQ_FIRST(&sc->sc_obuff_full); 1368 1369 if (ub != NULL && ub->ub_index == 0) 1370 ucom_submit_write(sc, ub); 1371 1372 if (sc->sc_rx_unblock) 1373 ucom_read_complete(sc); 1374 1375 mutex_exit(&sc->sc_lock); 1376 } 1377 1378 static void 1379 ucom_read_complete(struct ucom_softc *sc) 1380 { 1381 int (*rint)(int, struct tty *); 1382 struct ucom_buffer *ub; 1383 struct tty *tp; 1384 1385 KASSERT(mutex_owned(&sc->sc_lock)); 1386 1387 tp = sc->sc_tty; 1388 rint = tp->t_linesw->l_rint; 1389 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full); 1390 1391 while (ub != NULL && !sc->sc_rx_stopped) { 1392 1393 /* XXX ttyinput takes ttylock */ 1394 while (ub->ub_index < ub->ub_len && !sc->sc_rx_stopped) { 1395 /* Give characters to tty layer. */ 1396 if ((*rint)(ub->ub_data[ub->ub_index], tp) == -1) { 1397 /* Overflow: drop remainder */ 1398 ub->ub_index = ub->ub_len; 1399 } else 1400 ub->ub_index++; 1401 } 1402 1403 if (ub->ub_index == ub->ub_len) { 1404 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_full, ub_link); 1405 ucomsubmitread(sc, ub); 1406 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full); 1407 } 1408 } 1409 1410 sc->sc_rx_unblock = (ub != NULL); 1411 } 1412 1413 static int 1414 ucomsubmitread(struct ucom_softc *sc, struct ucom_buffer *ub) 1415 { 1416 usbd_status err; 1417 1418 KASSERT(mutex_owned(&sc->sc_lock)); 1419 1420 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, sc->sc_ibufsize, 1421 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ucomreadcb); 1422 1423 if ((err = usbd_transfer(ub->ub_xfer)) != USBD_IN_PROGRESS) { 1424 /* XXX: Recover from this, please! */ 1425 printf("%s: err=%s\n", __func__, usbd_errstr(err)); 1426 return EIO; 1427 } 1428 1429 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_empty, ub, ub_link); 1430 1431 return 0; 1432 } 1433 1434 static void 1435 ucomreadcb(struct usbd_xfer *xfer, void *p, usbd_status status) 1436 { 1437 struct ucom_softc *sc = (struct ucom_softc *)p; 1438 struct tty *tp = sc->sc_tty; 1439 struct ucom_buffer *ub; 1440 uint32_t cc; 1441 u_char *cp; 1442 1443 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1444 1445 mutex_enter(&sc->sc_lock); 1446 1447 if (status == USBD_CANCELLED || status == USBD_IOERROR || 1448 sc->sc_closing) { 1449 1450 DPRINTF("... done (status %jd closing %jd)", 1451 status, sc->sc_closing, 0, 0); 1452 1453 if (status == USBD_IOERROR || sc->sc_closing) { 1454 /* Send something to wake upper layer */ 1455 (tp->t_linesw->l_rint)('\n', tp); 1456 ttylock(tp); /* XXX */ 1457 ttwakeup(tp); 1458 ttyunlock(tp); /* XXX */ 1459 } 1460 1461 mutex_exit(&sc->sc_lock); 1462 return; 1463 } 1464 1465 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_empty); 1466 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_empty, ub_link); 1467 1468 if (status != USBD_NORMAL_COMPLETION) { 1469 if (status == USBD_STALLED) { 1470 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); 1471 } else { 1472 printf("ucomreadcb: wonky status=%s\n", 1473 usbd_errstr(status)); 1474 } 1475 1476 DPRINTF("... done (status %jd)", status, 0, 0, 0); 1477 /* re-adds ub to sc_ibuff_empty */ 1478 ucomsubmitread(sc, ub); 1479 mutex_exit(&sc->sc_lock); 1480 return; 1481 } 1482 1483 usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL); 1484 1485 #ifdef UCOM_DEBUG 1486 /* This is triggered by uslsa(4) occasionally. */ 1487 if ((ucomdebug > 0) && (cc == 0)) { 1488 device_printf(sc->sc_dev, "ucomreadcb: zero length xfer!\n"); 1489 } 1490 #endif 1491 KDASSERT(cp == ub->ub_data); 1492 1493 rnd_add_uint32(&sc->sc_rndsource, cc); 1494 1495 if (sc->sc_state != UCOM_OPEN) { 1496 /* Go around again - we're not quite ready */ 1497 /* re-adds ub to sc_ibuff_empty */ 1498 ucomsubmitread(sc, ub); 1499 mutex_exit(&sc->sc_lock); 1500 DPRINTF("... done (not open)", 0, 0, 0, 0); 1501 return; 1502 } 1503 1504 mutex_exit(&sc->sc_lock); 1505 if (sc->sc_methods->ucom_read != NULL) { 1506 sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno, 1507 &cp, &cc); 1508 ub->ub_index = (u_int)(cp - ub->ub_data); 1509 } else 1510 ub->ub_index = 0; 1511 1512 ub->ub_len = cc; 1513 1514 mutex_enter(&sc->sc_lock); 1515 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_full, ub, ub_link); 1516 ucom_read_complete(sc); 1517 mutex_exit(&sc->sc_lock); 1518 1519 DPRINTF("... done", 0, 0, 0, 0); 1520 } 1521 1522 static void 1523 ucom_cleanup(struct ucom_softc *sc, int flag) 1524 { 1525 struct tty *tp = sc->sc_tty; 1526 1527 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1528 1529 DPRINTF("closing pipes", 0, 0, 0, 0); 1530 1531 /* 1532 * Close the tty and interrupt any pending opens waiting for 1533 * carrier so they restart or give up. This may flush data. 1534 */ 1535 (*tp->t_linesw->l_close)(tp, flag); 1536 ttyclose(tp); 1537 1538 /* 1539 * Interrupt any pending xfers and cause them to fail promptly. 1540 * New xfers will only be submitted under the lock after 1541 * sc_closing is cleared. 1542 */ 1543 usbd_abort_pipe(sc->sc_bulkin_pipe); 1544 usbd_abort_pipe(sc->sc_bulkout_pipe); 1545 1546 /* 1547 * Hang up the phone and start the timer before we can make a 1548 * call again, if necessary. 1549 */ 1550 ucom_shutdown(sc); 1551 } 1552 1553 #endif /* NUCOM > 0 */ 1554 1555 int 1556 ucomprint(void *aux, const char *pnp) 1557 { 1558 struct ucom_attach_args *ucaa = aux; 1559 1560 if (pnp) 1561 aprint_normal("ucom at %s", pnp); 1562 if (ucaa->ucaa_portno != UCOM_UNK_PORTNO) 1563 aprint_normal(" portno %d", ucaa->ucaa_portno); 1564 return UNCONF; 1565 } 1566 1567 int 1568 ucomsubmatch(device_t parent, cfdata_t cf, 1569 const int *ldesc, void *aux) 1570 { 1571 struct ucom_attach_args *ucaa = aux; 1572 1573 if (ucaa->ucaa_portno != UCOM_UNK_PORTNO && 1574 cf->cf_loc[UCOMBUSCF_PORTNO] != UCOMBUSCF_PORTNO_DEFAULT && 1575 cf->cf_loc[UCOMBUSCF_PORTNO] != ucaa->ucaa_portno) 1576 return 0; 1577 return config_match(parent, cf, aux); 1578 } 1579