ucom.c revision 1.129
1/* $NetBSD: ucom.c,v 1.129 2021/06/24 08:20:42 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.129 2021/06/24 08:20:42 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 81int ucomdebug = 0; 82 83SYSCTL_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; 106fail: 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 134struct 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 142struct 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 198dev_type_open(ucomopen); 199dev_type_close(ucomclose); 200dev_type_read(ucomread); 201dev_type_write(ucomwrite); 202dev_type_ioctl(ucomioctl); 203dev_type_stop(ucomstop); 204dev_type_tty(ucomtty); 205dev_type_poll(ucompoll); 206 207const 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 222static void ucom_cleanup(struct ucom_softc *); 223static int ucomparam(struct tty *, struct termios *); 224static int ucomhwiflow(struct tty *, int); 225static void ucomstart(struct tty *); 226static void ucom_shutdown(struct ucom_softc *); 227static int ucom_do_ioctl(struct ucom_softc *, u_long, void *, 228 int, struct lwp *); 229static void ucom_dtr(struct ucom_softc *, int); 230static void ucom_rts(struct ucom_softc *, int); 231static void ucom_break(struct ucom_softc *, int); 232static void tiocm_to_ucom(struct ucom_softc *, u_long, int); 233static int ucom_to_tiocm(struct ucom_softc *); 234 235static void ucomreadcb(struct usbd_xfer *, void *, usbd_status); 236static void ucom_submit_write(struct ucom_softc *, struct ucom_buffer *); 237static void ucom_write_status(struct ucom_softc *, struct ucom_buffer *, 238 usbd_status); 239 240static void ucomwritecb(struct usbd_xfer *, void *, usbd_status); 241static void ucom_read_complete(struct ucom_softc *); 242static int ucomsubmitread(struct ucom_softc *, struct ucom_buffer *); 243static void ucom_softintr(void *); 244 245int ucom_match(device_t, cfdata_t, void *); 246void ucom_attach(device_t, device_t, void *); 247int ucom_detach(device_t, int); 248 249CFATTACH_DECL_NEW(ucom, sizeof(struct ucom_softc), ucom_match, ucom_attach, 250 ucom_detach, NULL); 251 252int 253ucom_match(device_t parent, cfdata_t match, void *aux) 254{ 255 return 1; 256} 257 258void 259ucom_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 372fail_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 381fail_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 389fail_0: 390 aprint_error_dev(self, "attach failed, error=%d\n", error); 391 392 return; 393} 394 395int 396ucom_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 } 418 if (sc->sc_bulkout_pipe != NULL) { 419 usbd_abort_pipe(sc->sc_bulkout_pipe); 420 } 421 422 mutex_enter(&sc->sc_lock); 423 424 /* wait for open/close to finish */ 425 while (sc->sc_state == UCOM_OPENING || sc->sc_state == UCOM_CLOSING) { 426 int error = cv_wait_sig(&sc->sc_statecv, &sc->sc_lock); 427 428 if (error) { 429 mutex_exit(&sc->sc_lock); 430 return error; 431 } 432 } 433 434 sc->sc_refcnt--; 435 while (sc->sc_refcnt >= 0) { 436 /* Wake up anyone waiting */ 437 if (tp != NULL) { 438 mutex_spin_enter(&tty_lock); 439 CLR(tp->t_state, TS_CARR_ON); 440 CLR(tp->t_cflag, CLOCAL | MDMBUF); 441 ttyflush(tp, FREAD|FWRITE); 442 mutex_spin_exit(&tty_lock); 443 } 444 /* Wait for processes to go away. */ 445 if (cv_timedwait(&sc->sc_detachcv, &sc->sc_lock, hz * 60)) 446 aprint_error_dev(self, ": didn't detach\n"); 447 } 448 449 softint_disestablish(sc->sc_si); 450 mutex_exit(&sc->sc_lock); 451 452 /* locate the major number */ 453 maj = cdevsw_lookup_major(&ucom_cdevsw); 454 455 /* Nuke the vnodes for any open instances. */ 456 mn = device_unit(self); 457 DPRINTF("maj=%jd mn=%jd", maj, mn, 0, 0); 458 vdevgone(maj, mn, mn, VCHR); 459 vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR); 460 vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR); 461 462 /* Detach and free the tty. */ 463 if (tp != NULL) { 464 tty_detach(tp); 465 tty_free(tp); 466 sc->sc_tty = NULL; 467 } 468 469 for (i = 0; i < UCOM_IN_BUFFS; i++) { 470 if (sc->sc_ibuff[i].ub_xfer != NULL) 471 usbd_destroy_xfer(sc->sc_ibuff[i].ub_xfer); 472 } 473 474 for (i = 0; i < UCOM_OUT_BUFFS; i++) { 475 if (sc->sc_obuff[i].ub_xfer != NULL) 476 usbd_destroy_xfer(sc->sc_obuff[i].ub_xfer); 477 } 478 479 if (sc->sc_bulkin_pipe != NULL) { 480 usbd_close_pipe(sc->sc_bulkin_pipe); 481 sc->sc_bulkin_pipe = NULL; 482 } 483 484 if (sc->sc_bulkout_pipe != NULL) { 485 usbd_close_pipe(sc->sc_bulkout_pipe); 486 sc->sc_bulkout_pipe = NULL; 487 } 488 489 /* Detach the random source */ 490 rnd_detach_source(&sc->sc_rndsource); 491 492 mutex_destroy(&sc->sc_lock); 493 cv_destroy(&sc->sc_statecv); 494 cv_destroy(&sc->sc_detachcv); 495 496 return 0; 497} 498 499void 500ucom_shutdown(struct ucom_softc *sc) 501{ 502 struct tty *tp = sc->sc_tty; 503 504 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 505 506 /* 507 * Hang up if necessary. Wait a bit, so the other side has time to 508 * notice even if we immediately open the port again. 509 */ 510 if (ISSET(tp->t_cflag, HUPCL)) { 511 ucom_dtr(sc, 0); 512 /* XXX will only timeout */ 513 (void) kpause(ttclos, false, hz, NULL); 514 } 515} 516 517int 518ucomopen(dev_t dev, int flag, int mode, struct lwp *l) 519{ 520 const int unit = UCOMUNIT(dev); 521 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 522 int error = 0; 523 524 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 525 526 if (sc == NULL) 527 return ENXIO; 528 529 mutex_enter(&sc->sc_lock); 530 if (sc->sc_dying) { 531 DPRINTF("... dying", 0, 0, 0, 0); 532 mutex_exit(&sc->sc_lock); 533 return EIO; 534 } 535 536 if (!device_is_active(sc->sc_dev)) { 537 mutex_exit(&sc->sc_lock); 538 return ENXIO; 539 } 540 541 struct tty *tp = sc->sc_tty; 542 543 DPRINTF("unit=%jd, tp=%#jx", unit, (uintptr_t)tp, 0, 0); 544 545 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) { 546 mutex_exit(&sc->sc_lock); 547 return EBUSY; 548 } 549 550 /* 551 * Wait while the device is initialized by the 552 * first opener or cleaned up by the last closer. 553 */ 554 while (sc->sc_state == UCOM_OPENING || sc->sc_state == UCOM_CLOSING) { 555 error = cv_wait_sig(&sc->sc_statecv, &sc->sc_lock); 556 557 if (sc->sc_dying) 558 error = EIO; 559 560 if (error) { 561 mutex_exit(&sc->sc_lock); 562 return error; 563 } 564 } 565 enum ucom_state state = sc->sc_state; 566 567 KASSERTMSG(state == UCOM_OPEN || state == UCOM_ATTACHED, 568 "state is %d", state); 569 570 bool cleanup = false; 571 /* If this is the first open then perform the initialisation */ 572 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 573 KASSERT(state == UCOM_ATTACHED); 574 tp->t_dev = dev; 575 cleanup = true; 576 sc->sc_state = UCOM_OPENING; 577 578 mutex_exit(&sc->sc_lock); 579 if (sc->sc_methods->ucom_open != NULL) { 580 error = sc->sc_methods->ucom_open(sc->sc_parent, 581 sc->sc_portno); 582 if (error) { 583 goto fail_2; 584 } 585 } 586 587 ucom_status_change(sc); 588 589 /* Clear PPS capture state on first open. */ 590 mutex_spin_enter(&timecounter_lock); 591 memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state)); 592 sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; 593 pps_init(&sc->sc_pps_state); 594 mutex_spin_exit(&timecounter_lock); 595 596 /* 597 * Initialize the termios status to the defaults. Add in the 598 * sticky bits from TIOCSFLAGS. 599 */ 600 struct termios t; 601 602 t.c_ispeed = 0; 603 t.c_ospeed = TTYDEF_SPEED; 604 t.c_cflag = TTYDEF_CFLAG; 605 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 606 SET(t.c_cflag, CLOCAL); 607 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 608 SET(t.c_cflag, CRTSCTS); 609 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 610 SET(t.c_cflag, MDMBUF); 611 /* Make sure ucomparam() will do something. */ 612 tp->t_ospeed = 0; 613 (void) ucomparam(tp, &t); 614 tp->t_iflag = TTYDEF_IFLAG; 615 tp->t_oflag = TTYDEF_OFLAG; 616 tp->t_lflag = TTYDEF_LFLAG; 617 ttychars(tp); 618 ttsetwater(tp); 619 620 /* 621 * Turn on DTR. We must always do this, even if carrier is not 622 * present, because otherwise we'd have to use TIOCSDTR 623 * immediately after setting CLOCAL, which applications do not 624 * expect. We always assert DTR while the device is open 625 * unless explicitly requested to deassert it. Ditto RTS. 626 */ 627 ucom_dtr(sc, 1); 628 ucom_rts(sc, 1); 629 630 mutex_enter(&sc->sc_lock); 631 if (sc->sc_dying) { 632 DPRINTF("... dying", 0, 0, 0, 0); 633 error = EIO; 634 goto fail_1; 635 } 636 637 sc->sc_rx_unblock = 0; 638 sc->sc_rx_stopped = 0; 639 sc->sc_tx_stopped = 0; 640 641 for (size_t i = 0; i < UCOM_IN_BUFFS; i++) { 642 struct ucom_buffer *ub = &sc->sc_ibuff[i]; 643 error = ucomsubmitread(sc, ub); 644 if (error) { 645 mutex_exit(&sc->sc_lock); 646 goto fail_2; 647 } 648 } 649 } 650 sc->sc_state = UCOM_OPEN; 651 cv_signal(&sc->sc_statecv); 652 mutex_exit(&sc->sc_lock); 653 654 DPRINTF("unit=%jd, tp=%#jx dialout %jd nonblock %jd", unit, 655 (uintptr_t)tp, !!UCOMDIALOUT(dev), !!ISSET(flag, O_NONBLOCK)); 656 error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); 657 if (error) 658 goto bad; 659 660 error = (*tp->t_linesw->l_open)(dev, tp); 661 if (error) 662 goto bad; 663 664 return 0; 665 666bad: 667 cleanup = !ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0; 668 669fail_2: 670 if (cleanup) { 671 /* 672 * We failed to open the device, and nobody else had 673 * it opened. Clean up the state as appropriate. 674 */ 675 ucom_cleanup(sc); 676 } 677 678 mutex_enter(&sc->sc_lock); 679 680fail_1: 681 sc->sc_state = state; 682 cv_signal(&sc->sc_statecv); 683 mutex_exit(&sc->sc_lock); 684 685 return error; 686} 687 688int 689ucomclose(dev_t dev, int flag, int mode, struct lwp *l) 690{ 691 const int unit = UCOMUNIT(dev); 692 struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit); 693 int error = 0; 694 695 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 696 697 DPRINTF("unit=%jd", UCOMUNIT(dev), 0, 0, 0); 698 699 if (sc == NULL) 700 return 0; 701 702 mutex_enter(&sc->sc_lock); 703 if (sc->sc_dying) { 704 DPRINTF("... dying", 0, 0, 0, 0); 705 mutex_exit(&sc->sc_lock); 706 return ENXIO; 707 } 708 709 /* 710 * Wait until any opens/closes have finished 711 */ 712 while (sc->sc_state == UCOM_OPENING || sc->sc_state == UCOM_CLOSING) { 713 error = cv_wait_sig(&sc->sc_statecv, &sc->sc_lock); 714 715 if (sc->sc_dying) 716 error = EIO; 717 718 if (error) { 719 mutex_exit(&sc->sc_lock); 720 return error; 721 } 722 } 723 724 struct tty *tp = sc->sc_tty; 725 726 if (!ISSET(tp->t_state, TS_ISOPEN)) { 727 KASSERT(sc->sc_state == UCOM_ATTACHED); 728 mutex_exit(&sc->sc_lock); 729 return 0; 730 } 731 732 KASSERT(sc->sc_state == UCOM_OPEN); 733 sc->sc_state = UCOM_CLOSING; 734 mutex_exit(&sc->sc_lock); 735 736 (*tp->t_linesw->l_close)(tp, flag); 737 ttyclose(tp); 738 739 /* state when we're done - default to open */ 740 enum ucom_state state = UCOM_OPEN; 741 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 742 /* 743 * Although we got a last close, the device may still be in 744 * use; e.g. if this was the dialout node, and there are still 745 * processes waiting for carrier on the non-dialout node. 746 */ 747 ucom_cleanup(sc); 748 if (sc->sc_methods->ucom_close != NULL) 749 sc->sc_methods->ucom_close(sc->sc_parent, 750 sc->sc_portno); 751 state = UCOM_ATTACHED; 752 } 753 754 mutex_enter(&sc->sc_lock); 755 sc->sc_state = state; 756 cv_signal(&sc->sc_statecv); 757 mutex_exit(&sc->sc_lock); 758 759 return error; 760} 761 762int 763ucomread(dev_t dev, struct uio *uio, int flag) 764{ 765 const int unit = UCOMUNIT(dev); 766 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 767 int error; 768 769 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 770 771 if (sc == NULL) 772 return EIO; 773 774 mutex_enter(&sc->sc_lock); 775 if (sc->sc_dying) { 776 DPRINTF("... dying", 0, 0, 0, 0); 777 mutex_exit(&sc->sc_lock); 778 return EIO; 779 } 780 781 struct tty *tp = sc->sc_tty; 782 783 sc->sc_refcnt++; 784 mutex_exit(&sc->sc_lock); 785 786 error = ((*tp->t_linesw->l_read)(tp, uio, flag)); 787 788 mutex_enter(&sc->sc_lock); 789 if (--sc->sc_refcnt < 0) 790 cv_broadcast(&sc->sc_detachcv); 791 DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0); 792 mutex_exit(&sc->sc_lock); 793 794 return error; 795} 796 797int 798ucomwrite(dev_t dev, struct uio *uio, int flag) 799{ 800 const int unit = UCOMUNIT(dev); 801 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 802 int error; 803 804 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 805 806 if (sc == NULL) 807 return EIO; 808 809 mutex_enter(&sc->sc_lock); 810 if (sc->sc_dying) { 811 DPRINTF("... dying", 0, 0, 0, 0); 812 mutex_exit(&sc->sc_lock); 813 return EIO; 814 } 815 816 struct tty *tp = sc->sc_tty; 817 818 sc->sc_refcnt++; 819 mutex_exit(&sc->sc_lock); 820 821 error = ((*tp->t_linesw->l_write)(tp, uio, flag)); 822 823 mutex_enter(&sc->sc_lock); 824 if (--sc->sc_refcnt < 0) 825 cv_broadcast(&sc->sc_detachcv); 826 DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0); 827 mutex_exit(&sc->sc_lock); 828 829 return error; 830} 831 832int 833ucompoll(dev_t dev, int events, struct lwp *l) 834{ 835 const int unit = UCOMUNIT(dev); 836 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 837 838 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 839 840 if (sc == NULL) 841 return POLLHUP; 842 843 mutex_enter(&sc->sc_lock); 844 if (sc->sc_dying) { 845 DPRINTF("... dying", 0, 0, 0, 0); 846 mutex_exit(&sc->sc_lock); 847 return POLLHUP; 848 } 849 struct tty *tp = sc->sc_tty; 850 851 sc->sc_refcnt++; 852 mutex_exit(&sc->sc_lock); 853 854 int revents = ((*tp->t_linesw->l_poll)(tp, events, l)); 855 856 mutex_enter(&sc->sc_lock); 857 if (--sc->sc_refcnt < 0) 858 cv_broadcast(&sc->sc_detachcv); 859 DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0); 860 mutex_exit(&sc->sc_lock); 861 862 return revents; 863} 864 865struct tty * 866ucomtty(dev_t dev) 867{ 868 const int unit = UCOMUNIT(dev); 869 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 870 871 return sc != NULL ? sc->sc_tty : NULL; 872} 873 874int 875ucomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 876{ 877 const int unit = UCOMUNIT(dev); 878 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 879 int error; 880 881 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 882 883 if (sc == NULL) 884 return EIO; 885 886 mutex_enter(&sc->sc_lock); 887 if (sc->sc_dying) { 888 DPRINTF("... dying", 0, 0, 0, 0); 889 mutex_exit(&sc->sc_lock); 890 return EIO; 891 } 892 893 sc->sc_refcnt++; 894 mutex_exit(&sc->sc_lock); 895 896 error = ucom_do_ioctl(sc, cmd, data, flag, l); 897 898 mutex_enter(&sc->sc_lock); 899 if (--sc->sc_refcnt < 0) 900 cv_broadcast(&sc->sc_detachcv); 901 DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0); 902 mutex_exit(&sc->sc_lock); 903 904 return error; 905} 906 907static int 908ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, void *data, int flag, 909 struct lwp *l) 910{ 911 struct tty *tp = sc->sc_tty; 912 int error; 913 914 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 915 916 DPRINTF("cmd=0x%08jx", cmd, 0, 0, 0); 917 918 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 919 if (error != EPASSTHROUGH) 920 return error; 921 922 error = ttioctl(tp, cmd, data, flag, l); 923 if (error != EPASSTHROUGH) 924 return error; 925 926 if (sc->sc_methods->ucom_ioctl != NULL) { 927 error = sc->sc_methods->ucom_ioctl(sc->sc_parent, 928 sc->sc_portno, cmd, data, flag, l->l_proc); 929 if (error != EPASSTHROUGH) 930 return error; 931 } 932 933 error = 0; 934 935 DPRINTF("our cmd=0x%08jx", cmd, 0, 0, 0); 936 937 switch (cmd) { 938 case TIOCSBRK: 939 ucom_break(sc, 1); 940 break; 941 942 case TIOCCBRK: 943 ucom_break(sc, 0); 944 break; 945 946 case TIOCSDTR: 947 ucom_dtr(sc, 1); 948 break; 949 950 case TIOCCDTR: 951 ucom_dtr(sc, 0); 952 break; 953 954 case TIOCGFLAGS: 955 mutex_enter(&sc->sc_lock); 956 *(int *)data = sc->sc_swflags; 957 mutex_exit(&sc->sc_lock); 958 break; 959 960 case TIOCSFLAGS: 961 error = kauth_authorize_device_tty(l->l_cred, 962 KAUTH_DEVICE_TTY_PRIVSET, tp); 963 if (error) 964 break; 965 mutex_enter(&sc->sc_lock); 966 sc->sc_swflags = *(int *)data; 967 mutex_exit(&sc->sc_lock); 968 break; 969 970 case TIOCMSET: 971 case TIOCMBIS: 972 case TIOCMBIC: 973 tiocm_to_ucom(sc, cmd, *(int *)data); 974 break; 975 976 case TIOCMGET: 977 *(int *)data = ucom_to_tiocm(sc); 978 break; 979 980 case PPS_IOC_CREATE: 981 case PPS_IOC_DESTROY: 982 case PPS_IOC_GETPARAMS: 983 case PPS_IOC_SETPARAMS: 984 case PPS_IOC_GETCAP: 985 case PPS_IOC_FETCH: 986#ifdef PPS_SYNC 987 case PPS_IOC_KCBIND: 988#endif 989 mutex_spin_enter(&timecounter_lock); 990 error = pps_ioctl(cmd, data, &sc->sc_pps_state); 991 mutex_spin_exit(&timecounter_lock); 992 break; 993 994 default: 995 error = EPASSTHROUGH; 996 break; 997 } 998 999 return error; 1000} 1001 1002static void 1003tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits) 1004{ 1005 u_char combits; 1006 1007 combits = 0; 1008 if (ISSET(ttybits, TIOCM_DTR)) 1009 SET(combits, UMCR_DTR); 1010 if (ISSET(ttybits, TIOCM_RTS)) 1011 SET(combits, UMCR_RTS); 1012 1013 mutex_enter(&sc->sc_lock); 1014 switch (how) { 1015 case TIOCMBIC: 1016 CLR(sc->sc_mcr, combits); 1017 break; 1018 1019 case TIOCMBIS: 1020 SET(sc->sc_mcr, combits); 1021 break; 1022 1023 case TIOCMSET: 1024 CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS); 1025 SET(sc->sc_mcr, combits); 1026 break; 1027 } 1028 u_char mcr = sc->sc_mcr; 1029 mutex_exit(&sc->sc_lock); 1030 1031 if (how == TIOCMSET || ISSET(combits, UMCR_DTR)) 1032 ucom_dtr(sc, (mcr & UMCR_DTR) != 0); 1033 if (how == TIOCMSET || ISSET(combits, UMCR_RTS)) 1034 ucom_rts(sc, (mcr & UMCR_RTS) != 0); 1035} 1036 1037static int 1038ucom_to_tiocm(struct ucom_softc *sc) 1039{ 1040 u_char combits; 1041 int ttybits = 0; 1042 1043 mutex_enter(&sc->sc_lock); 1044 combits = sc->sc_mcr; 1045 if (ISSET(combits, UMCR_DTR)) 1046 SET(ttybits, TIOCM_DTR); 1047 if (ISSET(combits, UMCR_RTS)) 1048 SET(ttybits, TIOCM_RTS); 1049 1050 combits = sc->sc_msr; 1051 if (ISSET(combits, UMSR_DCD)) 1052 SET(ttybits, TIOCM_CD); 1053 if (ISSET(combits, UMSR_CTS)) 1054 SET(ttybits, TIOCM_CTS); 1055 if (ISSET(combits, UMSR_DSR)) 1056 SET(ttybits, TIOCM_DSR); 1057 if (ISSET(combits, UMSR_RI | UMSR_TERI)) 1058 SET(ttybits, TIOCM_RI); 1059 1060#if 0 1061XXX; 1062 if (sc->sc_ier != 0) 1063 SET(ttybits, TIOCM_LE); 1064#endif 1065 mutex_exit(&sc->sc_lock); 1066 1067 return ttybits; 1068} 1069 1070static void 1071ucom_break(struct ucom_softc *sc, int onoff) 1072{ 1073 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1074 1075 DPRINTF("onoff=%jd", onoff, 0, 0, 0); 1076 1077 if (sc->sc_methods->ucom_set != NULL) 1078 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 1079 UCOM_SET_BREAK, onoff); 1080} 1081 1082static void 1083ucom_dtr(struct ucom_softc *sc, int onoff) 1084{ 1085 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1086 1087 DPRINTF("onoff=%jd", onoff, 0, 0, 0); 1088 1089 if (sc->sc_methods->ucom_set != NULL) 1090 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 1091 UCOM_SET_DTR, onoff); 1092} 1093 1094static void 1095ucom_rts(struct ucom_softc *sc, int onoff) 1096{ 1097 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1098 1099 DPRINTF("onoff=%jd", onoff, 0, 0, 0); 1100 1101 if (sc->sc_methods->ucom_set != NULL) 1102 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 1103 UCOM_SET_RTS, onoff); 1104} 1105 1106void 1107ucom_status_change(struct ucom_softc *sc) 1108{ 1109 struct tty *tp = sc->sc_tty; 1110 1111 if (sc->sc_methods->ucom_get_status != NULL) { 1112 u_char msr, lsr; 1113 1114 sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno, 1115 &lsr, &msr); 1116 mutex_enter(&sc->sc_lock); 1117 u_char old_msr = sc->sc_msr; 1118 1119 sc->sc_lsr = lsr; 1120 sc->sc_msr = msr; 1121 mutex_exit(&sc->sc_lock); 1122 1123 if (ISSET((msr ^ old_msr), UMSR_DCD)) { 1124 mutex_spin_enter(&timecounter_lock); 1125 pps_capture(&sc->sc_pps_state); 1126 pps_event(&sc->sc_pps_state, 1127 (sc->sc_msr & UMSR_DCD) ? 1128 PPS_CAPTUREASSERT : 1129 PPS_CAPTURECLEAR); 1130 mutex_spin_exit(&timecounter_lock); 1131 1132 (*tp->t_linesw->l_modem)(tp, ISSET(msr, UMSR_DCD)); 1133 } 1134 } else { 1135 mutex_enter(&sc->sc_lock); 1136 sc->sc_lsr = 0; 1137 /* Assume DCD is present, if we have no chance to check it. */ 1138 sc->sc_msr = UMSR_DCD; 1139 mutex_exit(&sc->sc_lock); 1140 } 1141} 1142 1143static int 1144ucomparam(struct tty *tp, struct termios *t) 1145{ 1146 const int unit = UCOMUNIT(tp->t_dev); 1147 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 1148 int error = 0; 1149 1150 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1151 1152 if (sc == NULL) 1153 return EIO; 1154 1155 mutex_enter(&sc->sc_lock); 1156 if (sc->sc_dying) { 1157 DPRINTF("... dying", 0, 0, 0, 0); 1158 mutex_exit(&sc->sc_lock); 1159 return EIO; 1160 } 1161 1162 sc->sc_refcnt++; 1163 mutex_exit(&sc->sc_lock); 1164 1165 /* Check requested parameters. */ 1166 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) { 1167 error = EINVAL; 1168 goto out; 1169 } 1170 1171 /* 1172 * For the console, always force CLOCAL and !HUPCL, so that the port 1173 * is always active. 1174 */ 1175 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) { 1176 SET(t->c_cflag, CLOCAL); 1177 CLR(t->c_cflag, HUPCL); 1178 } 1179 1180 /* 1181 * If there were no changes, don't do anything. This avoids dropping 1182 * input and improves performance when all we did was frob things like 1183 * VMIN and VTIME. 1184 */ 1185 if (tp->t_ospeed == t->c_ospeed && 1186 tp->t_cflag == t->c_cflag) { 1187 goto out; 1188 } 1189 1190 /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */ 1191 1192 /* And copy to tty. */ 1193 tp->t_ispeed = 0; 1194 tp->t_ospeed = t->c_ospeed; 1195 tp->t_cflag = t->c_cflag; 1196 1197 if (sc->sc_methods->ucom_param != NULL) { 1198 error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno, 1199 t); 1200 if (error) 1201 goto out; 1202 } 1203 1204 /* XXX worry about CHWFLOW */ 1205 1206 /* 1207 * Update the tty layer's idea of the carrier bit, in case we changed 1208 * CLOCAL or MDMBUF. We don't hang up here; we only do that by 1209 * explicit request. 1210 */ 1211 DPRINTF("l_modem", 0, 0, 0, 0); 1212 (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD)); 1213 1214#if 0 1215XXX what if the hardware is not open 1216 if (!ISSET(t->c_cflag, CHWFLOW)) { 1217 if (sc->sc_tx_stopped) { 1218 sc->sc_tx_stopped = 0; 1219 ucomstart(tp); 1220 } 1221 } 1222#endif 1223out: 1224 mutex_enter(&sc->sc_lock); 1225 if (--sc->sc_refcnt < 0) 1226 cv_broadcast(&sc->sc_detachcv); 1227 DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(tp->t_dev), sc->sc_refcnt, 1228 0, 0); 1229 1230 mutex_exit(&sc->sc_lock); 1231 1232 return error; 1233} 1234 1235static int 1236ucomhwiflow(struct tty *tp, int block) 1237{ 1238 const int unit = UCOMUNIT(tp->t_dev); 1239 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 1240 int old; 1241 1242 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1243 1244 if (sc == NULL) 1245 return 0; 1246 1247 KASSERT(&sc->sc_lock); 1248 KASSERT(mutex_owned(&tty_lock)); 1249 1250 old = sc->sc_rx_stopped; 1251 sc->sc_rx_stopped = (u_char)block; 1252 1253 if (old && !block) { 1254 sc->sc_rx_unblock = 1; 1255 kpreempt_disable(); 1256 softint_schedule(sc->sc_si); 1257 kpreempt_enable(); 1258 } 1259 1260 return 1; 1261} 1262 1263static void 1264ucomstart(struct tty *tp) 1265{ 1266 const int unit = UCOMUNIT(tp->t_dev); 1267 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 1268 struct ucom_buffer *ub; 1269 u_char *data; 1270 int cnt; 1271 1272 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1273 1274 if (sc == NULL) 1275 return; 1276 1277 KASSERT(&sc->sc_lock); 1278 KASSERT(mutex_owned(&tty_lock)); 1279 if (sc->sc_dying) { 1280 DPRINTF("... dying", 0, 0, 0, 0); 1281 return; 1282 } 1283 1284 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 1285 goto out; 1286 if (sc->sc_tx_stopped) 1287 goto out; 1288 1289 if (!ttypull(tp)) 1290 goto out; 1291 1292 /* Grab the first contiguous region of buffer space. */ 1293 data = tp->t_outq.c_cf; 1294 cnt = ndqb(&tp->t_outq, 0); 1295 1296 if (cnt == 0) 1297 goto out; 1298 1299 ub = SIMPLEQ_FIRST(&sc->sc_obuff_free); 1300 if (ub == NULL) { 1301 SET(tp->t_state, TS_BUSY); 1302 goto out; 1303 } 1304 1305 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_free, ub_link); 1306 1307 if (SIMPLEQ_FIRST(&sc->sc_obuff_free) == NULL) 1308 SET(tp->t_state, TS_BUSY); 1309 1310 if (cnt > sc->sc_obufsize) 1311 cnt = sc->sc_obufsize; 1312 1313 if (sc->sc_methods->ucom_write != NULL) 1314 sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno, 1315 ub->ub_data, data, &cnt); 1316 else 1317 memcpy(ub->ub_data, data, cnt); 1318 1319 ub->ub_len = cnt; 1320 ub->ub_index = 0; 1321 1322 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_full, ub, ub_link); 1323 1324 kpreempt_disable(); 1325 softint_schedule(sc->sc_si); 1326 kpreempt_enable(); 1327 1328 out: 1329 DPRINTF("... done", 0, 0, 0, 0); 1330 return; 1331} 1332 1333void 1334ucomstop(struct tty *tp, int flag) 1335{ 1336#if 0 1337 const int unit = UCOMUNIT(tp->t_dev); 1338 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit); 1339 1340 mutex_enter(&sc->sc_lock); 1341 mutex_spin_enter(&tty_lock); 1342 if (ISSET(tp->t_state, TS_BUSY)) { 1343 /* obuff_full -> obuff_free? */ 1344 /* sc->sc_tx_stopped = 1; */ 1345 if (!ISSET(tp->t_state, TS_TTSTOP)) 1346 SET(tp->t_state, TS_FLUSH); 1347 } 1348 mutex_spin_exit(&tty_lock); 1349 mutex_exit(&sc->sc_lock); 1350#endif 1351} 1352 1353static void 1354ucom_write_status(struct ucom_softc *sc, struct ucom_buffer *ub, 1355 usbd_status err) 1356{ 1357 struct tty *tp = sc->sc_tty; 1358 uint32_t cc = ub->ub_len; 1359 1360 KASSERT(mutex_owned(&sc->sc_lock)); 1361 1362 switch (err) { 1363 case USBD_IN_PROGRESS: 1364 ub->ub_index = ub->ub_len; 1365 break; 1366 case USBD_STALLED: 1367 ub->ub_index = 0; 1368 kpreempt_disable(); 1369 softint_schedule(sc->sc_si); 1370 kpreempt_enable(); 1371 break; 1372 case USBD_NORMAL_COMPLETION: 1373 usbd_get_xfer_status(ub->ub_xfer, NULL, NULL, &cc, NULL); 1374 rnd_add_uint32(&sc->sc_rndsource, cc); 1375 /*FALLTHROUGH*/ 1376 default: 1377 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_full, ub_link); 1378 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link); 1379 cc -= sc->sc_opkthdrlen; 1380 1381 mutex_spin_enter(&tty_lock); 1382 CLR(tp->t_state, TS_BUSY); 1383 if (ISSET(tp->t_state, TS_FLUSH)) 1384 CLR(tp->t_state, TS_FLUSH); 1385 else 1386 ndflush(&tp->t_outq, cc); 1387 mutex_spin_exit(&tty_lock); 1388 1389 if (err != USBD_CANCELLED && err != USBD_IOERROR && 1390 !sc->sc_dying) { 1391 if ((ub = SIMPLEQ_FIRST(&sc->sc_obuff_full)) != NULL) 1392 ucom_submit_write(sc, ub); 1393 1394 mutex_spin_enter(&tty_lock); 1395 (*tp->t_linesw->l_start)(tp); 1396 mutex_spin_exit(&tty_lock); 1397 } 1398 break; 1399 } 1400} 1401 1402static void 1403ucom_submit_write(struct ucom_softc *sc, struct ucom_buffer *ub) 1404{ 1405 1406 KASSERT(mutex_owned(&sc->sc_lock)); 1407 1408 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, ub->ub_len, 1409 0, USBD_NO_TIMEOUT, ucomwritecb); 1410 1411 ucom_write_status(sc, ub, usbd_transfer(ub->ub_xfer)); 1412} 1413 1414static void 1415ucomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status) 1416{ 1417 struct ucom_softc *sc = (struct ucom_softc *)p; 1418 1419 mutex_enter(&sc->sc_lock); 1420 ucom_write_status(sc, SIMPLEQ_FIRST(&sc->sc_obuff_full), status); 1421 mutex_exit(&sc->sc_lock); 1422 1423} 1424 1425static void 1426ucom_softintr(void *arg) 1427{ 1428 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1429 1430 struct ucom_softc *sc = arg; 1431 1432 mutex_enter(&sc->sc_lock); 1433 if (sc->sc_dying) { 1434 DPRINTF("... dying", 0, 0, 0, 0); 1435 mutex_exit(&sc->sc_lock); 1436 return; 1437 } 1438 1439 struct tty *tp = sc->sc_tty; 1440 mutex_enter(&tty_lock); 1441 if (!ISSET(tp->t_state, TS_ISOPEN)) { 1442 mutex_exit(&tty_lock); 1443 mutex_exit(&sc->sc_lock); 1444 return; 1445 } 1446 mutex_exit(&tty_lock); 1447 1448 struct ucom_buffer *ub = SIMPLEQ_FIRST(&sc->sc_obuff_full); 1449 1450 if (ub != NULL && ub->ub_index == 0) 1451 ucom_submit_write(sc, ub); 1452 1453 if (sc->sc_rx_unblock) 1454 ucom_read_complete(sc); 1455 1456 mutex_exit(&sc->sc_lock); 1457} 1458 1459static void 1460ucom_read_complete(struct ucom_softc *sc) 1461{ 1462 int (*rint)(int, struct tty *); 1463 struct ucom_buffer *ub; 1464 struct tty *tp; 1465 1466 KASSERT(mutex_owned(&sc->sc_lock)); 1467 1468 tp = sc->sc_tty; 1469 rint = tp->t_linesw->l_rint; 1470 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full); 1471 1472 while (ub != NULL && !sc->sc_rx_stopped) { 1473 1474 /* XXX ttyinput takes tty_lock */ 1475 while (ub->ub_index < ub->ub_len && !sc->sc_rx_stopped) { 1476 /* Give characters to tty layer. */ 1477 if ((*rint)(ub->ub_data[ub->ub_index], tp) == -1) { 1478 /* Overflow: drop remainder */ 1479 ub->ub_index = ub->ub_len; 1480 } else 1481 ub->ub_index++; 1482 } 1483 1484 if (ub->ub_index == ub->ub_len) { 1485 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_full, ub_link); 1486 1487 sc->sc_refcnt--; 1488 /* increments sc_refcnt */ 1489 ucomsubmitread(sc, ub); 1490 1491 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full); 1492 } 1493 } 1494 1495 sc->sc_rx_unblock = (ub != NULL); 1496} 1497 1498static int 1499ucomsubmitread(struct ucom_softc *sc, struct ucom_buffer *ub) 1500{ 1501 usbd_status err; 1502 1503 KASSERT(mutex_owned(&sc->sc_lock)); 1504 1505 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, sc->sc_ibufsize, 1506 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ucomreadcb); 1507 1508 if ((err = usbd_transfer(ub->ub_xfer)) != USBD_IN_PROGRESS) { 1509 /* XXX: Recover from this, please! */ 1510 printf("%s: err=%s\n", __func__, usbd_errstr(err)); 1511 return EIO; 1512 } 1513 1514 sc->sc_refcnt++; 1515 1516 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_empty, ub, ub_link); 1517 1518 return 0; 1519} 1520 1521static void 1522ucomreadcb(struct usbd_xfer *xfer, void *p, usbd_status status) 1523{ 1524 struct ucom_softc *sc = (struct ucom_softc *)p; 1525 struct ucom_buffer *ub; 1526 uint32_t cc; 1527 u_char *cp; 1528 1529 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1530 1531 mutex_enter(&sc->sc_lock); 1532 1533 struct tty *tp = sc->sc_tty; 1534 1535 if (status == USBD_CANCELLED || status == USBD_IOERROR || 1536 sc->sc_dying) { 1537 1538 DPRINTF("... done (status %jd dying %jd)", status, sc->sc_dying, 1539 0, 0); 1540 1541 if (status == USBD_IOERROR || sc->sc_dying) { 1542 /* Send something to wake upper layer */ 1543 (tp->t_linesw->l_rint)('\n', tp); 1544 mutex_spin_enter(&tty_lock); /* XXX */ 1545 ttwakeup(tp); 1546 mutex_spin_exit(&tty_lock); /* XXX */ 1547 } 1548 1549 if (--sc->sc_refcnt < 0) 1550 cv_broadcast(&sc->sc_detachcv); 1551 DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(tp->t_dev), 1552 sc->sc_refcnt, 0, 0); 1553 mutex_exit(&sc->sc_lock); 1554 1555 return; 1556 } 1557 1558 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_empty); 1559 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_empty, ub_link); 1560 1561 if (status != USBD_NORMAL_COMPLETION) { 1562 if (status == USBD_STALLED) { 1563 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); 1564 } else { 1565 printf("ucomreadcb: wonky status=%s\n", 1566 usbd_errstr(status)); 1567 } 1568 1569 DPRINTF("... done (status %jd)", status, 0, 0, 0); 1570 sc->sc_refcnt--; 1571 /* re-adds ub to sc_ibuff_empty and increments sc_refcnt */ 1572 ucomsubmitread(sc, ub); 1573 mutex_exit(&sc->sc_lock); 1574 return; 1575 } 1576 1577 usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL); 1578 1579#ifdef UCOM_DEBUG 1580 /* This is triggered by uslsa(4) occasionally. */ 1581 if ((ucomdebug > 0) && (cc == 0)) { 1582 device_printf(sc->sc_dev, "ucomreadcb: zero length xfer!\n"); 1583 } 1584#endif 1585 KDASSERT(cp == ub->ub_data); 1586 1587 rnd_add_uint32(&sc->sc_rndsource, cc); 1588 1589 if (sc->sc_state != UCOM_OPEN) { 1590 /* Go around again - we're not quite ready */ 1591 sc->sc_refcnt--; 1592 /* re-adds ub to sc_ibuff_empty and increments sc_refcnt */ 1593 ucomsubmitread(sc, ub); 1594 mutex_exit(&sc->sc_lock); 1595 DPRINTF("... done (not open)", 0, 0, 0, 0); 1596 return; 1597 } 1598 1599 mutex_exit(&sc->sc_lock); 1600 if (sc->sc_methods->ucom_read != NULL) { 1601 sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno, 1602 &cp, &cc); 1603 ub->ub_index = (u_int)(cp - ub->ub_data); 1604 } else 1605 ub->ub_index = 0; 1606 1607 ub->ub_len = cc; 1608 1609 mutex_enter(&sc->sc_lock); 1610 if (sc->sc_dying) { 1611 if (--sc->sc_refcnt < 0) 1612 cv_broadcast(&sc->sc_detachcv); 1613 mutex_exit(&sc->sc_lock); 1614 DPRINTF("... dying", 0, 0, 0, 0); 1615 return; 1616 } 1617 1618 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_full, ub, ub_link); 1619 1620 ucom_read_complete(sc); 1621 mutex_exit(&sc->sc_lock); 1622 1623 DPRINTF("... done", 0, 0, 0, 0); 1624} 1625 1626static void 1627ucom_cleanup(struct ucom_softc *sc) 1628{ 1629 1630 UCOMHIST_FUNC(); UCOMHIST_CALLED(); 1631 1632 DPRINTF("aborting pipes", 0, 0, 0, 0); 1633 1634 mutex_enter(&sc->sc_lock); 1635 1636 /* If we're dying then the detach routine will abort our pipes, etc */ 1637 if (sc->sc_dying) { 1638 DPRINTF("... dying", 0, 0, 0, 0); 1639 1640 mutex_exit(&sc->sc_lock); 1641 return; 1642 } 1643 1644 mutex_exit(&sc->sc_lock); 1645 1646 ucom_shutdown(sc); 1647 1648 if (sc->sc_bulkin_pipe != NULL) { 1649 usbd_abort_pipe(sc->sc_bulkin_pipe); 1650 } 1651 if (sc->sc_bulkout_pipe != NULL) { 1652 usbd_abort_pipe(sc->sc_bulkout_pipe); 1653 } 1654} 1655 1656#endif /* NUCOM > 0 */ 1657 1658int 1659ucomprint(void *aux, const char *pnp) 1660{ 1661 struct ucom_attach_args *ucaa = aux; 1662 1663 if (pnp) 1664 aprint_normal("ucom at %s", pnp); 1665 if (ucaa->ucaa_portno != UCOM_UNK_PORTNO) 1666 aprint_normal(" portno %d", ucaa->ucaa_portno); 1667 return UNCONF; 1668} 1669 1670int 1671ucomsubmatch(device_t parent, cfdata_t cf, 1672 const int *ldesc, void *aux) 1673{ 1674 struct ucom_attach_args *ucaa = aux; 1675 1676 if (ucaa->ucaa_portno != UCOM_UNK_PORTNO && 1677 cf->cf_loc[UCOMBUSCF_PORTNO] != UCOMBUSCF_PORTNO_DEFAULT && 1678 cf->cf_loc[UCOMBUSCF_PORTNO] != ucaa->ucaa_portno) 1679 return 0; 1680 return config_match(parent, cf, aux); 1681} 1682