1 /* $NetBSD: ucom.c,v 1.40 2001/11/13 06:24:54 lukem Exp $ */ 2 3 /*- 4 * Copyright (c) 2001-2003, 2005, 2008 5 * Shunsuke Akiyama <akiyama@jp.FreeBSD.org>. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /*- 31 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. 32 * All rights reserved. 33 * 34 * This code is derived from software contributed to The NetBSD Foundation 35 * by Lennart Augustsson (lennart@augustsson.net) at 36 * Carlstedt Research & Technology. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by the NetBSD 49 * Foundation, Inc. and its contributors. 50 * 4. Neither the name of The NetBSD Foundation nor the names of its 51 * contributors may be used to endorse or promote products derived 52 * from this software without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 55 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 64 * POSSIBILITY OF SUCH DAMAGE. 65 */ 66 67 /* 68 * XXX profmakx 69 * This is a Frankenstein of FreeBSD's usb4bsd ucom and Dragonfly's old ucom 70 * module. There might be bugs lurking everywhere still 71 * 72 * In particular serial console on ucom is completely untested and likely broken 73 * as well as anyting that requires the modem control lines. 74 */ 75 76 #include <sys/stdint.h> 77 #include <sys/param.h> 78 #include <sys/queue.h> 79 #include <sys/types.h> 80 #include <sys/systm.h> 81 #include <sys/kernel.h> 82 #include <sys/bus.h> 83 #include <sys/module.h> 84 #include <sys/lock.h> 85 #include <sys/condvar.h> 86 #include <sys/sysctl.h> 87 #include <sys/unistd.h> 88 #include <sys/callout.h> 89 #include <sys/malloc.h> 90 #include <sys/caps.h> 91 #include <sys/cons.h> 92 #include <sys/serial.h> 93 #include <sys/thread2.h> 94 #include <sys/conf.h> 95 96 #include <bus/u4b/usb.h> 97 #include <bus/u4b/usbdi.h> 98 #include <bus/u4b/usbdi_util.h> 99 100 #define USB_DEBUG_VAR ucom_debug 101 #include <bus/u4b/usb_debug.h> 102 #include <bus/u4b/usb_busdma.h> 103 #include <bus/u4b/usb_process.h> 104 105 #include <bus/u4b/serial/usb_serial.h> 106 107 /* #include "opt_gdb.h" */ 108 109 static SYSCTL_NODE(_hw_usb, OID_AUTO, ucom, CTLFLAG_RW, 0, "USB ucom"); 110 111 static int ucom_pps_mode; 112 113 SYSCTL_INT(_hw_usb_ucom, OID_AUTO, pps_mode, CTLFLAG_RW, 114 &ucom_pps_mode, 0, "pulse capturing mode - 0/1/2 - disabled/CTS/DCD"); 115 TUNABLE_INT("hw.usb.ucom.pss_mode", &ucom_pps_mode); 116 117 118 #ifdef USB_DEBUG 119 static int ucom_debug = 0; 120 121 SYSCTL_INT(_hw_usb_ucom, OID_AUTO, debug, CTLFLAG_RW, 122 &ucom_debug, 0, "ucom debug level"); 123 #endif 124 125 #define UCOM_CONS_BUFSIZE 1024 126 127 static uint8_t ucom_cons_rx_buf[UCOM_CONS_BUFSIZE]; 128 static uint8_t ucom_cons_tx_buf[UCOM_CONS_BUFSIZE]; 129 130 static unsigned int ucom_cons_rx_low = 0; 131 static unsigned int ucom_cons_rx_high = 0; 132 133 static unsigned int ucom_cons_tx_low = 0; 134 static unsigned int ucom_cons_tx_high = 0; 135 136 static int ucom_cons_unit = -1; 137 static int ucom_cons_subunit = 0; 138 static int ucom_cons_baud = 9600; 139 static struct ucom_softc *ucom_cons_softc = NULL; 140 141 TUNABLE_INT("hw.usb.ucom.cons_unit", &ucom_cons_unit); 142 SYSCTL_INT(_hw_usb_ucom, OID_AUTO, cons_unit, CTLFLAG_RW, 143 &ucom_cons_unit, 0, "console unit number"); 144 TUNABLE_INT("hw.usb.ucom.cons_subunit", &ucom_cons_subunit); 145 SYSCTL_INT(_hw_usb_ucom, OID_AUTO, cons_subunit, CTLFLAG_RW, 146 &ucom_cons_subunit, 0, "console subunit number"); 147 TUNABLE_INT("hw.usb.ucom.cons_baud", &ucom_cons_baud); 148 SYSCTL_INT(_hw_usb_ucom, OID_AUTO, cons_baud, CTLFLAG_RW, 149 &ucom_cons_baud, 0, "console baud rate"); 150 151 static usb_proc_callback_t ucom_cfg_start_transfers; 152 static usb_proc_callback_t ucom_cfg_open; 153 static usb_proc_callback_t ucom_cfg_close; 154 static usb_proc_callback_t ucom_cfg_line_state; 155 static usb_proc_callback_t ucom_cfg_status_change; 156 static usb_proc_callback_t ucom_cfg_param; 157 158 static int ucom_unit_alloc(void); 159 static void ucom_unit_free(int); 160 static int ucom_attach_tty(struct ucom_super_softc *, struct ucom_softc *); 161 static void ucom_detach_tty(struct ucom_super_softc *, struct ucom_softc *); 162 static void ucom_queue_command(struct ucom_softc *, 163 usb_proc_callback_t *, struct termios *pt, 164 struct usb_proc_msg *t0, struct usb_proc_msg *t1); 165 static void ucom_shutdown(struct ucom_softc *); 166 static void ucom_ring(struct ucom_softc *, uint8_t); 167 static void ucom_break(struct ucom_softc *, uint8_t); 168 static void ucom_dtr(struct ucom_softc *, uint8_t); 169 static void ucom_rts(struct ucom_softc *, uint8_t); 170 171 static int ucom_open(struct ucom_softc *sc); 172 static int ucom_close(struct ucom_softc *sc); 173 static void ucom_start(struct tty *tp); 174 static void ucom_stop(struct tty *tp, int); 175 static int ucom_param(struct tty *tp, struct termios *t); 176 static int ucom_modem(struct tty *tp, int sigon, int sigoff); 177 178 static int ucom_fromtio(int); 179 static int ucom_totio(int); 180 181 static void disc_optim(struct tty *, struct termios *, struct ucom_softc *); 182 183 static d_open_t ucom_dev_open; 184 static d_close_t ucom_dev_close; 185 static d_read_t ucom_dev_read; 186 static d_write_t ucom_dev_write; 187 static d_ioctl_t ucom_dev_ioctl; 188 189 static struct dev_ops ucom_ops = { 190 { "ucom", 0, D_MPSAFE | D_TTY }, 191 .d_open = ucom_dev_open, 192 .d_close = ucom_dev_close, 193 .d_read = ucom_dev_read, 194 .d_write = ucom_dev_write, 195 .d_ioctl = ucom_dev_ioctl, 196 .d_kqfilter = ttykqfilter, 197 .d_revoke = ttyrevoke 198 }; 199 200 static moduledata_t ucom_mod = { 201 "ucom", 202 NULL, 203 NULL 204 }; 205 206 DECLARE_MODULE(ucom, ucom_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); 207 MODULE_DEPEND(ucom, usb, 1, 1, 1); 208 MODULE_VERSION(ucom, UCOM_MODVER); 209 210 /* XXXDF */ 211 #define tty_gone(tp) ((tp->t_state) & (TS_ZOMBIE)) 212 213 #define UCOM_UNIT_MAX 128 /* maximum number of units */ 214 #define UCOM_TTY_PREFIX "ucom" 215 216 217 #define CALLOUT_MASK 0x80 218 #define CONTROL_MASK 0x60 219 #define CONTROL_INIT_STATE 0x20 220 #define CONTROL_LOCK_STATE 0x40 221 222 static struct unrhdr *ucom_unrhdr; 223 static struct lock ucom_lock; 224 static int ucom_close_refs; 225 226 static void 227 ucom_init(void *arg) 228 { 229 DPRINTF("\n"); 230 ucom_unrhdr = new_unrhdr(0, UCOM_UNIT_MAX - 1, NULL); 231 lockinit(&ucom_lock, "UCOM LOCK", 0, 0); 232 } 233 SYSINIT(ucom_init, SI_BOOT2_KLD - 1, SI_ORDER_ANY, ucom_init, NULL); 234 235 static void 236 ucom_uninit(void *arg) 237 { 238 struct unrhdr *hdr; 239 hdr = ucom_unrhdr; 240 ucom_unrhdr = NULL; 241 242 DPRINTF("\n"); 243 244 if (hdr != NULL) 245 delete_unrhdr(hdr); 246 247 lockuninit(&ucom_lock); 248 } 249 SYSUNINIT(ucom_uninit, SI_BOOT2_KLD - 2, SI_ORDER_ANY, ucom_uninit, NULL); 250 251 /* 252 * Mark a unit number (the X in cuaUX) as in use. 253 * 254 * Note that devices using a different naming scheme (see ucom_tty_name() 255 * callback) still use this unit allocation. 256 */ 257 static int 258 ucom_unit_alloc(void) 259 { 260 int unit; 261 262 /* sanity checks */ 263 if (ucom_unrhdr == NULL) { 264 DPRINTF("ucom_unrhdr is NULL\n"); 265 return (-1); 266 } 267 unit = alloc_unr(ucom_unrhdr); 268 DPRINTF("unit %d is allocated\n", unit); 269 return (unit); 270 } 271 272 /* 273 * Mark the unit number as not in use. 274 */ 275 static void 276 ucom_unit_free(int unit) 277 { 278 /* sanity checks */ 279 if (unit < 0 || unit >= UCOM_UNIT_MAX || ucom_unrhdr == NULL) { 280 DPRINTF("cannot free unit number\n"); 281 return; 282 } 283 DPRINTF("unit %d is freed\n", unit); 284 free_unr(ucom_unrhdr, unit); 285 } 286 287 /* 288 * Setup a group of one or more serial ports. 289 * 290 * The lock pointed to by "lock" is applied before all 291 * callbacks are called back. Also "lock" must be applied 292 * before calling into the ucom-layer! 293 */ 294 int 295 ucom_attach(struct ucom_super_softc *ssc, struct ucom_softc *sc, 296 int subunits, void *parent, 297 const struct ucom_callback *callback, struct lock *lock) 298 { 299 int subunit; 300 int error = 0; 301 302 if ((sc == NULL) || 303 (subunits <= 0) || 304 (callback == NULL) || 305 (lock == NULL)) { 306 return (EINVAL); 307 } 308 309 /* XXX Do we want our own lock here maybe */ 310 sc->sc_lock = lock; 311 312 /* allocate a uniq unit number */ 313 ssc->sc_unit = ucom_unit_alloc(); 314 if (ssc->sc_unit == -1) 315 return (ENOMEM); 316 317 /* generate TTY name string */ 318 ksnprintf(ssc->sc_ttyname, sizeof(ssc->sc_ttyname), 319 UCOM_TTY_PREFIX "%d", ssc->sc_unit); 320 321 /* create USB request handling process */ 322 error = usb_proc_create(&ssc->sc_tq, lock, "ucom", USB_PRI_MED); 323 if (error) { 324 ucom_unit_free(ssc->sc_unit); 325 return (error); 326 } 327 ssc->sc_subunits = subunits; 328 ssc->sc_flag = UCOM_FLAG_ATTACHED | 329 UCOM_FLAG_FREE_UNIT; 330 331 if (callback->ucom_free == NULL) 332 ssc->sc_flag |= UCOM_FLAG_WAIT_REFS; 333 334 /* increment reference count */ 335 ucom_ref(ssc); 336 337 for (subunit = 0; subunit < ssc->sc_subunits; subunit++) { 338 sc[subunit].sc_subunit = subunit; 339 sc[subunit].sc_super = ssc; 340 sc[subunit].sc_lock = lock; 341 sc[subunit].sc_parent = parent; 342 sc[subunit].sc_callback = callback; 343 344 error = ucom_attach_tty(ssc, &sc[subunit]); 345 if (error) { 346 ucom_detach(ssc, &sc[0]); 347 return (error); 348 } 349 /* increment reference count */ 350 ucom_ref(ssc); 351 352 /* set subunit attached */ 353 sc[subunit].sc_flag |= UCOM_FLAG_ATTACHED; 354 } 355 356 DPRINTF("tp = %p, unit = %d, subunits = %d\n", 357 sc->sc_tty, ssc->sc_unit, ssc->sc_subunits); 358 359 return (0); 360 } 361 362 /* 363 * The following function will do nothing if the structure pointed to 364 * by "ssc" and "sc" is zero or has already been detached. 365 */ 366 void 367 ucom_detach(struct ucom_super_softc *ssc, struct ucom_softc *sc) 368 { 369 int subunit; 370 371 if (!(ssc->sc_flag & UCOM_FLAG_ATTACHED)) 372 return; /* not initialized */ 373 374 destroy_dev(sc->sc_cdev); 375 destroy_dev(sc->sc_cdev_init); 376 destroy_dev(sc->sc_cdev_lock); 377 destroy_dev(sc->sc_cdev2); 378 destroy_dev(sc->sc_cdev2_init); 379 destroy_dev(sc->sc_cdev2_lock); 380 381 if (sc->sc_tty) 382 lwkt_gettoken(&sc->sc_tty->t_token); 383 384 if (ssc->sc_sysctl_ttyname != NULL) { 385 sysctl_remove_oid(ssc->sc_sysctl_ttyname, 1, 0); 386 ssc->sc_sysctl_ttyname = NULL; 387 } 388 389 if (ssc->sc_sysctl_ttyports != NULL) { 390 sysctl_remove_oid(ssc->sc_sysctl_ttyports, 1, 0); 391 ssc->sc_sysctl_ttyports = NULL; 392 } 393 394 usb_proc_drain(&ssc->sc_tq); 395 396 for (subunit = 0; subunit < ssc->sc_subunits; subunit++) { 397 if (sc[subunit].sc_flag & UCOM_FLAG_ATTACHED) { 398 399 ucom_detach_tty(ssc, &sc[subunit]); 400 401 /* avoid duplicate detach */ 402 sc[subunit].sc_flag &= ~UCOM_FLAG_ATTACHED; 403 } 404 } 405 usb_proc_free(&ssc->sc_tq); 406 407 ucom_unref(ssc); 408 409 if (ssc->sc_flag & UCOM_FLAG_WAIT_REFS) 410 ucom_drain(ssc); 411 412 /* make sure we don't detach twice */ 413 ssc->sc_flag &= ~UCOM_FLAG_ATTACHED; 414 415 if (sc->sc_tty) 416 lwkt_reltoken(&sc->sc_tty->t_token); 417 } 418 419 void 420 ucom_drain(struct ucom_super_softc *ssc) 421 { 422 lockmgr(&ucom_lock, LK_EXCLUSIVE); 423 while (ssc->sc_refs > 0) { 424 kprintf("ucom: Waiting for a TTY device to close.\n"); 425 usb_pause_mtx(&ucom_lock, hz); 426 } 427 lockmgr(&ucom_lock, LK_RELEASE); 428 } 429 430 void 431 ucom_drain_all(void *arg) 432 { 433 lockmgr(&ucom_lock, LK_EXCLUSIVE); 434 while (ucom_close_refs > 0) { 435 kprintf("ucom: Waiting for all detached TTY " 436 "devices to have open fds closed.\n"); 437 usb_pause_mtx(&ucom_lock, hz); 438 } 439 lockmgr(&ucom_lock, LK_RELEASE); 440 } 441 442 static int 443 ucom_attach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) 444 { 445 struct tty *tp; 446 char buf[32]; /* temporary TTY device name buffer */ 447 448 tp = ttymalloc(&sc->sc_tty); 449 450 lwkt_gettoken(&tp->t_token); 451 452 tp->t_sc = (void *)sc; 453 454 tp->t_oproc = ucom_start; 455 tp->t_param = ucom_param; 456 tp->t_stop = ucom_stop; 457 458 /* Check if the client has a custom TTY name */ 459 buf[0] = '\0'; 460 if (sc->sc_callback->ucom_tty_name) { 461 sc->sc_callback->ucom_tty_name(sc, buf, 462 sizeof(buf), ssc->sc_unit, sc->sc_subunit); 463 } 464 if (buf[0] == 0) { 465 /* Use default TTY name */ 466 if (ssc->sc_subunits > 1) { 467 /* multiple modems in one */ 468 ksnprintf(buf, sizeof(buf), "%u.%u", 469 ssc->sc_unit, sc->sc_subunit); 470 } else { 471 /* single modem */ 472 ksnprintf(buf, sizeof(buf), "%u", 473 ssc->sc_unit); 474 } 475 } 476 477 sc->sc_cdev = make_dev(&ucom_ops, ssc->sc_unit, 478 UID_ROOT, GID_WHEEL, 0600, "ttyU%s", buf); 479 sc->sc_cdev_init = make_dev(&ucom_ops, ssc->sc_unit | CONTROL_INIT_STATE, 480 UID_ROOT, GID_WHEEL, 0600, "ttyiU%s", buf); 481 sc->sc_cdev_lock = make_dev(&ucom_ops, ssc->sc_unit | CONTROL_LOCK_STATE, 482 UID_ROOT, GID_WHEEL, 0600, "ttylU%s", buf); 483 sc->sc_cdev2 = make_dev(&ucom_ops, ssc->sc_unit | CALLOUT_MASK, 484 UID_UUCP, GID_DIALER, 0660, "cuaU%s", buf); 485 sc->sc_cdev2_init = make_dev(&ucom_ops, ssc->sc_unit | CALLOUT_MASK | CONTROL_INIT_STATE, 486 UID_UUCP, GID_DIALER, 0660, "cuaiU%s", buf); 487 sc->sc_cdev2_lock = make_dev(&ucom_ops, ssc->sc_unit | CALLOUT_MASK | CONTROL_LOCK_STATE, 488 UID_UUCP, GID_DIALER, 0660, "cualU%s", buf); 489 490 sc->sc_cdev->si_tty = tp; 491 sc->sc_cdev_init->si_tty = tp; 492 sc->sc_cdev_lock->si_tty = tp; 493 494 sc->sc_cdev->si_drv1 = sc; 495 sc->sc_cdev_init->si_drv1 = sc; 496 sc->sc_cdev_lock->si_drv1 = sc; 497 498 sc->sc_cdev2->si_tty = tp; 499 sc->sc_cdev2_init->si_tty = tp; 500 sc->sc_cdev2_lock->si_tty = tp; 501 502 sc->sc_cdev2->si_drv1 = sc; 503 sc->sc_cdev2_init->si_drv1 = sc; 504 sc->sc_cdev2_lock->si_drv1 = sc; 505 506 sc->sc_tty = tp; 507 508 DPRINTF("ttycreate: %s\n", buf); 509 510 /* Check if this device should be a console */ 511 if ((ucom_cons_softc == NULL) && 512 (ssc->sc_unit == ucom_cons_unit) && 513 (sc->sc_subunit == ucom_cons_subunit)) { 514 515 DPRINTF("unit %d subunit %d is console", 516 ssc->sc_unit, sc->sc_subunit); 517 518 ucom_cons_softc = sc; 519 520 #if 0 /* XXXDF */ 521 tty_init_console(tp, ucom_cons_baud); 522 #endif 523 tp->t_termios.c_ispeed = ucom_cons_baud; 524 tp->t_termios.c_ospeed = ucom_cons_baud; 525 526 UCOM_MTX_LOCK(ucom_cons_softc); 527 ucom_cons_rx_low = 0; 528 ucom_cons_rx_high = 0; 529 ucom_cons_tx_low = 0; 530 ucom_cons_tx_high = 0; 531 sc->sc_flag |= UCOM_FLAG_CONSOLE; 532 ucom_open(ucom_cons_softc); 533 ucom_param(tp, &tp->t_termios); 534 UCOM_MTX_UNLOCK(ucom_cons_softc); 535 } 536 537 lwkt_reltoken(&tp->t_token); 538 539 return (0); 540 } 541 542 static void 543 ucom_detach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) 544 { 545 struct tty *tp = sc->sc_tty; 546 547 DPRINTF("sc = %p, tp = %p\n", sc, sc->sc_tty); 548 549 if (sc->sc_flag & UCOM_FLAG_CONSOLE) { 550 UCOM_MTX_LOCK(ucom_cons_softc); 551 ucom_close(ucom_cons_softc); 552 sc->sc_flag &= ~UCOM_FLAG_CONSOLE; 553 UCOM_MTX_UNLOCK(ucom_cons_softc); 554 ucom_cons_softc = NULL; 555 } 556 557 /* the config thread has been stopped when we get here */ 558 559 UCOM_MTX_LOCK(sc); 560 sc->sc_flag |= UCOM_FLAG_GONE; 561 sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_LL_READY); 562 UCOM_MTX_UNLOCK(sc); 563 564 if (tp != NULL) { 565 lwkt_gettoken(&tp->t_token); 566 ucom_close_refs++; 567 568 UCOM_MTX_LOCK(sc); 569 if (tp->t_state & TS_ISOPEN) { 570 kprintf("device still open, forcing close\n"); 571 (*linesw[tp->t_line].l_close)(tp, 0); 572 ttyclose(tp); 573 } 574 ucom_close(sc); /* close, if any */ 575 576 /* 577 * make sure that read and write transfers are stopped 578 */ 579 if (sc->sc_callback->ucom_stop_read) { 580 (sc->sc_callback->ucom_stop_read) (sc); 581 } 582 if (sc->sc_callback->ucom_stop_write) { 583 (sc->sc_callback->ucom_stop_write) (sc); 584 } 585 UCOM_MTX_UNLOCK(sc); 586 lwkt_reltoken(&tp->t_token); 587 } else { 588 DPRINTF("no tty\n"); 589 } 590 591 dev_ops_remove_minor(&ucom_ops,ssc->sc_unit); 592 593 ucom_unref(ssc); 594 } 595 596 void 597 ucom_set_pnpinfo_usb(struct ucom_super_softc *ssc, device_t dev) 598 { 599 char buf[64]; 600 uint8_t iface_index; 601 struct usb_attach_arg *uaa; 602 603 ksnprintf(buf, sizeof(buf), "ttyname=" UCOM_TTY_PREFIX 604 "%d ttyports=%d", ssc->sc_unit, ssc->sc_subunits); 605 606 /* Store the PNP info in the first interface for the device */ 607 uaa = device_get_ivars(dev); 608 iface_index = uaa->info.bIfaceIndex; 609 610 if (usbd_set_pnpinfo(uaa->device, iface_index, buf) != 0) 611 device_printf(dev, "Could not set PNP info\n"); 612 613 /* 614 * The following information is also replicated in the PNP-info 615 * string which is registered above: 616 */ 617 if (ssc->sc_sysctl_ttyname == NULL) { 618 /* 619 ssc->sc_sysctl_ttyname = SYSCTL_ADD_STRING(NULL, 620 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 621 OID_AUTO, "ttyname", CTLFLAG_RD, ssc->sc_ttyname, 0, 622 "TTY device basename"); 623 */ 624 } 625 if (ssc->sc_sysctl_ttyports == NULL) { 626 /* 627 ssc->sc_sysctl_ttyports = SYSCTL_ADD_INT(NULL, 628 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 629 OID_AUTO, "ttyports", CTLFLAG_RD, 630 NULL, ssc->sc_subunits, "Number of ports"); 631 */ 632 } 633 } 634 635 static void 636 ucom_queue_command(struct ucom_softc *sc, 637 usb_proc_callback_t *fn, struct termios *pt, 638 struct usb_proc_msg *t0, struct usb_proc_msg *t1) 639 { 640 struct ucom_super_softc *ssc = sc->sc_super; 641 struct ucom_param_task *task; 642 643 UCOM_MTX_ASSERT(sc, MA_OWNED); 644 645 if (usb_proc_is_gone(&ssc->sc_tq)) { 646 DPRINTF("proc is gone\n"); 647 return; /* nothing to do */ 648 } 649 /* 650 * NOTE: The task cannot get executed before we drop the 651 * "sc_lock" lock. It is safe to update fields in the message 652 * structure after that the message got queued. 653 */ 654 task = (struct ucom_param_task *) 655 usb_proc_msignal(&ssc->sc_tq, t0, t1); 656 657 /* Setup callback and softc pointers */ 658 task->hdr.pm_callback = fn; 659 task->sc = sc; 660 661 /* 662 * Make a copy of the termios. This field is only present if 663 * the "pt" field is not NULL. 664 */ 665 if (pt != NULL) 666 task->termios_copy = *pt; 667 668 /* 669 * Closing the device should be synchronous. 670 */ 671 if (fn == ucom_cfg_close) 672 usb_proc_mwait(&ssc->sc_tq, t0, t1); 673 674 /* 675 * In case of multiple configure requests, 676 * keep track of the last one! 677 */ 678 if (fn == ucom_cfg_start_transfers) 679 sc->sc_last_start_xfer = &task->hdr; 680 } 681 682 static void 683 ucom_shutdown(struct ucom_softc *sc) 684 { 685 struct tty *tp = sc->sc_tty; 686 687 UCOM_MTX_ASSERT(sc, MA_OWNED); 688 689 DPRINTF("\n"); 690 691 /* 692 * Hang up if necessary: 693 */ 694 if (tp->t_termios.c_cflag & HUPCL) { 695 ucom_modem(tp, 0, SER_DTR); 696 } 697 } 698 699 /* 700 * Return values: 701 * 0: normal 702 * else: taskqueue is draining or gone 703 */ 704 uint8_t 705 ucom_cfg_is_gone(struct ucom_softc *sc) 706 { 707 struct ucom_super_softc *ssc = sc->sc_super; 708 709 return (usb_proc_is_gone(&ssc->sc_tq)); 710 } 711 712 static void 713 ucom_cfg_start_transfers(struct usb_proc_msg *_task) 714 { 715 struct ucom_cfg_task *task = 716 (struct ucom_cfg_task *)_task; 717 struct ucom_softc *sc = task->sc; 718 719 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { 720 return; 721 } 722 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 723 /* TTY device closed */ 724 return; 725 } 726 727 if (_task == sc->sc_last_start_xfer) 728 sc->sc_flag |= UCOM_FLAG_GP_DATA; 729 730 if (sc->sc_callback->ucom_start_read) { 731 (sc->sc_callback->ucom_start_read) (sc); 732 } 733 if (sc->sc_callback->ucom_start_write) { 734 (sc->sc_callback->ucom_start_write) (sc); 735 } 736 } 737 738 static void 739 ucom_start_transfers(struct ucom_softc *sc) 740 { 741 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 742 return; 743 } 744 /* 745 * Make sure that data transfers are started in both 746 * directions: 747 */ 748 if (sc->sc_callback->ucom_start_read) { 749 (sc->sc_callback->ucom_start_read) (sc); 750 } 751 if (sc->sc_callback->ucom_start_write) { 752 (sc->sc_callback->ucom_start_write) (sc); 753 } 754 } 755 756 static void 757 ucom_cfg_open(struct usb_proc_msg *_task) 758 { 759 struct ucom_cfg_task *task = 760 (struct ucom_cfg_task *)_task; 761 struct ucom_softc *sc = task->sc; 762 763 DPRINTF("\n"); 764 765 if (sc->sc_flag & UCOM_FLAG_LL_READY) { 766 767 /* already opened */ 768 769 } else { 770 771 sc->sc_flag |= UCOM_FLAG_LL_READY; 772 773 if (sc->sc_callback->ucom_cfg_open) { 774 (sc->sc_callback->ucom_cfg_open) (sc); 775 776 /* wait a little */ 777 usb_pause_mtx(sc->sc_lock, hz / 10); 778 } 779 } 780 } 781 782 static int 783 ucom_dev_open(struct dev_open_args *ap) 784 { 785 cdev_t dev = ap->a_head.a_dev; 786 struct ucom_softc *sc = (struct ucom_softc *)dev->si_drv1; 787 int error; 788 int mynor; 789 790 error = 0; 791 mynor = minor(dev); 792 793 UCOM_MTX_LOCK(sc); 794 error = ucom_open(sc); 795 UCOM_MTX_UNLOCK(sc); 796 797 return error; 798 } 799 800 static int 801 ucom_open(struct ucom_softc *sc) 802 { 803 int error; 804 struct tty *tp; 805 806 int mynor; 807 808 mynor = minor(sc->sc_cdev); 809 810 if (sc->sc_flag & UCOM_FLAG_GONE) { 811 return (ENXIO); 812 } 813 if (sc->sc_flag & UCOM_FLAG_HL_READY) { 814 /* already opened */ 815 return (0); 816 } 817 DPRINTF("tp = %p\n", sc->sc_tty); 818 819 if (sc->sc_callback->ucom_pre_open) { 820 /* 821 * give the lower layer a chance to disallow TTY open, for 822 * example if the device is not present: 823 */ 824 error = (sc->sc_callback->ucom_pre_open) (sc); 825 if (error) { 826 return (error); 827 } 828 } 829 sc->sc_flag |= UCOM_FLAG_HL_READY; 830 831 tp = sc->sc_tty; 832 lwkt_gettoken(&tp->t_token); 833 834 if (!ISSET(tp->t_state, TS_ISOPEN)) { 835 struct termios t; 836 837 tp->t_dev = reference_dev(sc->sc_cdev); 838 839 t = mynor & CALLOUT_MASK ? sc->sc_it_out : sc->sc_it_in; 840 841 tp->t_ospeed = 0; 842 ucom_param(tp, &t); 843 tp->t_iflag = TTYDEF_IFLAG; 844 tp->t_oflag = TTYDEF_OFLAG; 845 tp->t_lflag = TTYDEF_LFLAG; 846 ttychars(tp); 847 ttsetwater(tp); 848 849 /* Disable transfers */ 850 sc->sc_flag &= ~UCOM_FLAG_GP_DATA; 851 852 sc->sc_lsr = 0; 853 sc->sc_msr = 0; 854 sc->sc_mcr = 0; 855 856 /* reset programmed line state */ 857 sc->sc_pls_curr = 0; 858 sc->sc_pls_set = 0; 859 sc->sc_pls_clr = 0; 860 861 /* reset jitter buffer */ 862 sc->sc_jitterbuf_in = 0; 863 sc->sc_jitterbuf_out = 0; 864 865 ucom_queue_command(sc, ucom_cfg_open, NULL, 866 &sc->sc_open_task[0].hdr, 867 &sc->sc_open_task[1].hdr); 868 869 /* Queue transfer enable command last */ 870 ucom_queue_command(sc, ucom_cfg_start_transfers, NULL, 871 &sc->sc_start_task[0].hdr, 872 &sc->sc_start_task[1].hdr); 873 874 ucom_modem(sc->sc_tty, SER_DTR | SER_RTS, 0); 875 876 ucom_ring(sc, 0); 877 878 ucom_break(sc, 0); 879 880 ucom_status_change(sc); 881 882 if (ISSET(sc->sc_msr, SER_DCD)) { 883 (*linesw[tp->t_line].l_modem)(tp, 1); 884 } 885 } 886 887 error = ttyopen(sc->sc_cdev, tp); 888 if (error) { 889 lwkt_reltoken(&tp->t_token); 890 return (error); 891 } 892 893 error = (*linesw[tp->t_line].l_open)(sc->sc_cdev, tp); 894 if (error) { 895 lwkt_reltoken(&tp->t_token); 896 return (error); 897 } 898 899 disc_optim(tp, &tp->t_termios, sc); 900 901 lwkt_reltoken(&tp->t_token); 902 903 return (0); 904 } 905 906 static void 907 ucom_cfg_close(struct usb_proc_msg *_task) 908 { 909 struct ucom_cfg_task *task = 910 (struct ucom_cfg_task *)_task; 911 struct ucom_softc *sc = task->sc; 912 913 DPRINTF("\n"); 914 915 if (sc->sc_flag & UCOM_FLAG_LL_READY) { 916 sc->sc_flag &= ~UCOM_FLAG_LL_READY; 917 if (sc->sc_callback->ucom_cfg_close) 918 (sc->sc_callback->ucom_cfg_close) (sc); 919 } else { 920 /* already closed */ 921 } 922 } 923 924 static int 925 ucom_dev_close(struct dev_close_args *ap) 926 { 927 cdev_t dev = ap->a_head.a_dev; 928 struct ucom_softc *sc = (struct ucom_softc *)dev->si_drv1; 929 int error; 930 931 UCOM_MTX_LOCK(sc); 932 error = ucom_close(sc); 933 UCOM_MTX_UNLOCK(sc); 934 935 return error; 936 } 937 938 static int 939 ucom_close(struct ucom_softc *sc) 940 { 941 struct tty *tp = sc->sc_tty; 942 int error = 0; 943 944 DPRINTF("tp=%p\n", tp); 945 946 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 947 DPRINTF("tp=%p already closed\n", tp); 948 return (error); 949 } 950 if (!ISSET(tp->t_state, TS_ISOPEN)) { 951 return(error); 952 } 953 ucom_shutdown(sc); 954 955 ucom_queue_command(sc, ucom_cfg_close, NULL, 956 &sc->sc_close_task[0].hdr, 957 &sc->sc_close_task[1].hdr); 958 959 sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_RTS_IFLOW); 960 961 if (sc->sc_callback->ucom_stop_read) { 962 (sc->sc_callback->ucom_stop_read) (sc); 963 } 964 965 lwkt_gettoken(&tp->t_token); 966 (*linesw[tp->t_line].l_close)(tp, 0); /* XXX: flags */ 967 disc_optim(tp, &tp->t_termios, sc); 968 ttyclose(tp); 969 970 if (tp->t_dev) { 971 release_dev(tp->t_dev); 972 tp->t_dev = NULL; 973 } 974 /* XXX: Detach wakeup */ 975 lwkt_reltoken(&tp->t_token); 976 977 return (error); 978 } 979 980 #if 0 /* XXX */ 981 static void 982 ucom_inwakeup(struct tty *tp) 983 { 984 struct ucom_softc *sc = tty_softc(tp); 985 uint16_t pos; 986 987 if (sc == NULL) 988 return; 989 990 UCOM_MTX_ASSERT(sc, MA_OWNED); 991 992 DPRINTF("tp=%p\n", tp); 993 994 if (ttydisc_can_bypass(tp) != 0 || 995 (sc->sc_flag & UCOM_FLAG_HL_READY) == 0 || 996 (sc->sc_flag & UCOM_FLAG_INWAKEUP) != 0) { 997 return; 998 } 999 1000 /* prevent recursion */ 1001 sc->sc_flag |= UCOM_FLAG_INWAKEUP; 1002 1003 pos = sc->sc_jitterbuf_out; 1004 1005 while (sc->sc_jitterbuf_in != pos) { 1006 int c; 1007 1008 c = (char)sc->sc_jitterbuf[pos]; 1009 1010 if (ttydisc_rint(tp, c, 0) == -1) 1011 break; 1012 pos++; 1013 if (pos >= UCOM_JITTERBUF_SIZE) 1014 pos -= UCOM_JITTERBUF_SIZE; 1015 } 1016 1017 sc->sc_jitterbuf_out = pos; 1018 1019 /* clear RTS in async fashion */ 1020 if ((sc->sc_jitterbuf_in == pos) && 1021 (sc->sc_flag & UCOM_FLAG_RTS_IFLOW)) 1022 ucom_rts(sc, 0); 1023 1024 sc->sc_flag &= ~UCOM_FLAG_INWAKEUP; 1025 } 1026 #endif 1027 1028 static int 1029 ucom_dev_read(struct dev_read_args *ap) 1030 { 1031 cdev_t dev = ap->a_head.a_dev; 1032 struct ucom_softc *sc; 1033 struct tty *tp; 1034 int error; 1035 1036 sc = NULL; 1037 1038 tp = dev->si_tty; 1039 lwkt_gettoken(&tp->t_token); 1040 KKASSERT(tp!=NULL); 1041 sc = tp->t_sc; 1042 KKASSERT(sc!=NULL); 1043 1044 DPRINTF("tp = %p, flag = 0x%x\n", tp, ap->a_ioflag); 1045 1046 /* must not be locked in case it blocks */ 1047 /*UCOM_MTX_LOCK(sc);*/ 1048 error = (*linesw[tp->t_line].l_read)(tp, ap->a_uio, ap->a_ioflag); 1049 /*UCOM_MTX_UNLOCK(sc);*/ 1050 1051 lwkt_reltoken(&tp->t_token); 1052 DPRINTF("error = %d\n", error); 1053 1054 return (error); 1055 } 1056 1057 static int 1058 ucom_dev_write(struct dev_write_args *ap) 1059 { 1060 cdev_t dev = ap->a_head.a_dev; 1061 struct ucom_softc *sc; 1062 struct tty *tp; 1063 int error; 1064 1065 tp = dev->si_tty; 1066 lwkt_gettoken(&tp->t_token); 1067 KKASSERT(tp!=NULL); 1068 sc = tp->t_sc; 1069 KKASSERT(sc!=NULL); 1070 1071 DPRINTF("tp = %p, flag = 0x%x\n", tp, ap->a_ioflag); 1072 1073 /* must not be locked in case it blocks */ 1074 /*UCOM_MTX_LOCK(sc);*/ 1075 error = (*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag); 1076 /*UCOM_MTX_UNLOCK(sc);*/ 1077 1078 lwkt_reltoken(&tp->t_token); 1079 DPRINTF("ucomwrite: error = %d\n", error); 1080 1081 return (error); 1082 } 1083 1084 static int 1085 ucom_dev_ioctl(struct dev_ioctl_args *ap) 1086 { 1087 cdev_t dev = ap->a_head.a_dev; 1088 struct ucom_softc *sc = (struct ucom_softc *)dev->si_drv1; 1089 u_long cmd = ap->a_cmd; 1090 caddr_t data = ap->a_data; 1091 struct tty *tp = sc->sc_tty; 1092 int d; 1093 int error; 1094 int mynor; 1095 1096 UCOM_MTX_LOCK(sc); 1097 lwkt_gettoken(&tp->t_token); 1098 1099 mynor = minor(dev); 1100 1101 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1102 lwkt_reltoken(&tp->t_token); 1103 UCOM_MTX_UNLOCK(sc); 1104 return (EIO); 1105 } 1106 DPRINTF("cmd = 0x%08lx\n", cmd); 1107 if (mynor & CONTROL_MASK) { 1108 struct termios *ct; 1109 1110 switch (mynor & CONTROL_MASK) { 1111 case CONTROL_INIT_STATE: 1112 ct = mynor & CALLOUT_MASK ? &sc->sc_it_out : &sc->sc_it_in; 1113 break; 1114 case CONTROL_LOCK_STATE: 1115 ct = mynor & CALLOUT_MASK ? &sc->sc_lt_out : &sc->sc_lt_in; 1116 break; 1117 default: 1118 lwkt_reltoken(&tp->t_token); 1119 UCOM_MTX_UNLOCK(sc); 1120 return (ENODEV); /* /dev/nodev */ 1121 } 1122 switch (ap->a_cmd) { 1123 case TIOCSETA: 1124 error = caps_priv_check(ap->a_cred, 1125 SYSCAP_RESTRICTEDROOT); 1126 if (error != 0) { 1127 lwkt_reltoken(&tp->t_token); 1128 UCOM_MTX_UNLOCK(sc); 1129 return (error); 1130 } 1131 *ct = *(struct termios *)data; 1132 lwkt_reltoken(&tp->t_token); 1133 UCOM_MTX_UNLOCK(sc); 1134 return (0); 1135 case TIOCGETA: 1136 *(struct termios *)data = *ct; 1137 lwkt_reltoken(&tp->t_token); 1138 UCOM_MTX_UNLOCK(sc); 1139 return (0); 1140 case TIOCGETD: 1141 *(int *)data = TTYDISC; 1142 lwkt_reltoken(&tp->t_token); 1143 UCOM_MTX_UNLOCK(sc); 1144 return (0); 1145 case TIOCGWINSZ: 1146 bzero(data, sizeof(struct winsize)); 1147 lwkt_reltoken(&tp->t_token); 1148 UCOM_MTX_UNLOCK(sc); 1149 return (0); 1150 default: 1151 lwkt_reltoken(&tp->t_token); 1152 UCOM_MTX_UNLOCK(sc); 1153 return (ENOTTY); 1154 } 1155 } 1156 1157 error = (*linesw[tp->t_line].l_ioctl)(tp, ap->a_cmd, ap->a_data, 1158 ap->a_fflag, ap->a_cred); 1159 1160 if (error != ENOIOCTL) { 1161 DPRINTF("ucomioctl: l_ioctl: error = %d\n", error); 1162 lwkt_reltoken(&tp->t_token); 1163 UCOM_MTX_UNLOCK(sc); 1164 return (error); 1165 } 1166 1167 error = ttioctl(tp, ap->a_cmd, ap->a_data, ap->a_fflag); 1168 disc_optim(tp, &tp->t_termios, sc); 1169 if (error != ENOIOCTL) { 1170 DPRINTF("ucomioctl: ttioctl: error = %d\n", error); 1171 lwkt_reltoken(&tp->t_token); 1172 UCOM_MTX_UNLOCK(sc); 1173 1174 return (error); 1175 } 1176 1177 error = 0; 1178 1179 switch (cmd) { 1180 #if 0 /* XXXDF */ 1181 case TIOCSRING: 1182 ucom_ring(sc, 1); 1183 error = 0; 1184 break; 1185 case TIOCCRING: 1186 ucom_ring(sc, 0); 1187 error = 0; 1188 break; 1189 #endif 1190 case TIOCSBRK: 1191 ucom_break(sc, 1); 1192 error = 0; 1193 break; 1194 case TIOCCBRK: 1195 ucom_break(sc, 0); 1196 error = 0; 1197 break; 1198 case TIOCSDTR: 1199 ucom_dtr(sc, 1); 1200 break; 1201 case TIOCCDTR: 1202 ucom_dtr(sc, 0); 1203 break; 1204 case TIOCMSET: 1205 d = *(int *)ap->a_data; 1206 DPRINTF("ucomioctl: TIOCMSET, 0x%x\n", d); 1207 ucom_modem(tp, ucom_fromtio(d), 0); 1208 break; 1209 case TIOCMGET: 1210 d = ucom_modem(tp, 0, 0); 1211 DPRINTF("ucomioctl: TIOCMGET, 0x%x\n", d); 1212 *(int *)ap->a_data = ucom_totio(d); 1213 ucom_status_change(sc); 1214 break; 1215 case TIOCMBIS: 1216 d = *(int *)ap->a_data; 1217 ucom_modem(tp, ucom_fromtio(d), 0); 1218 break; 1219 case TIOCMBIC: 1220 d = *(int *)ap->a_data; 1221 ucom_modem(tp, 0, ucom_fromtio(d)); 1222 break; 1223 default: 1224 if (sc->sc_callback->ucom_ioctl) { 1225 error = (sc->sc_callback->ucom_ioctl) 1226 (sc, cmd, data, 0, curthread); 1227 if (error>=0) { 1228 lwkt_reltoken(&tp->t_token); 1229 UCOM_MTX_UNLOCK(sc); 1230 1231 return(error); 1232 } 1233 } else { 1234 error = ENOIOCTL; 1235 } 1236 if (error == ENOIOCTL) 1237 error = pps_ioctl(cmd, data, &sc->sc_pps); 1238 break; 1239 } 1240 lwkt_reltoken(&tp->t_token); 1241 UCOM_MTX_UNLOCK(sc); 1242 1243 return (error); 1244 } 1245 1246 static int 1247 ucom_totio(int bits) 1248 { 1249 int rbits = 0; 1250 1251 SET(bits, TIOCM_LE); 1252 1253 if (ISSET(bits, SER_DTR)) { 1254 SET(rbits, TIOCM_DTR); 1255 } 1256 if (ISSET(bits, SER_RTS)) { 1257 SET(rbits, TIOCM_RTS); 1258 } 1259 if (ISSET(bits, SER_CTS)) { 1260 SET(rbits, TIOCM_CTS); 1261 } 1262 if (ISSET(bits, SER_DCD)) { 1263 SET(rbits, TIOCM_CD); 1264 } 1265 if (ISSET(bits, SER_DSR)) { 1266 SET(rbits, TIOCM_DSR); 1267 } 1268 if (ISSET(bits, SER_RI)) { 1269 SET(rbits, TIOCM_RI); 1270 } 1271 1272 return (rbits); 1273 } 1274 1275 static int 1276 ucom_fromtio(int bits) 1277 { 1278 int rbits = 0; 1279 1280 if (ISSET(bits, TIOCM_DTR)) { 1281 SET(rbits, SER_DTR); 1282 } 1283 if (ISSET(bits, TIOCM_RTS)) { 1284 SET(rbits, SER_RTS); 1285 } 1286 if (ISSET(bits, TIOCM_CTS)) { 1287 SET(rbits, SER_CTS); 1288 } 1289 if (ISSET(bits, TIOCM_CD)) { 1290 SET(rbits, SER_DCD); 1291 } 1292 if (ISSET(bits, TIOCM_DSR)) { 1293 SET(rbits, SER_DSR); 1294 } 1295 if (ISSET(bits, TIOCM_RI)) { 1296 SET(rbits, SER_RI); 1297 } 1298 1299 return (rbits); 1300 } 1301 1302 static int 1303 ucom_modem(struct tty *tp, int sigon, int sigoff) 1304 { 1305 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc; 1306 uint8_t onoff; 1307 1308 UCOM_MTX_ASSERT(sc, MA_OWNED); 1309 1310 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1311 return (0); 1312 } 1313 if ((sigon == 0) && (sigoff == 0)) { 1314 1315 if (sc->sc_mcr & SER_DTR) { 1316 sigon |= SER_DTR; 1317 } 1318 if (sc->sc_mcr & SER_RTS) { 1319 sigon |= SER_RTS; 1320 } 1321 if (sc->sc_msr & SER_CTS) { 1322 sigon |= SER_CTS; 1323 } 1324 if (sc->sc_msr & SER_DCD) { 1325 sigon |= SER_DCD; 1326 } 1327 if (sc->sc_msr & SER_DSR) { 1328 sigon |= SER_DSR; 1329 } 1330 if (sc->sc_msr & SER_RI) { 1331 sigon |= SER_RI; 1332 } 1333 return (sigon); 1334 } 1335 if (sigon & SER_DTR) { 1336 sc->sc_mcr |= SER_DTR; 1337 } 1338 if (sigoff & SER_DTR) { 1339 sc->sc_mcr &= ~SER_DTR; 1340 } 1341 if (sigon & SER_RTS) { 1342 sc->sc_mcr |= SER_RTS; 1343 } 1344 if (sigoff & SER_RTS) { 1345 sc->sc_mcr &= ~SER_RTS; 1346 } 1347 onoff = (sc->sc_mcr & SER_DTR) ? 1 : 0; 1348 ucom_dtr(sc, onoff); 1349 1350 onoff = (sc->sc_mcr & SER_RTS) ? 1 : 0; 1351 ucom_rts(sc, onoff); 1352 1353 return (0); 1354 } 1355 1356 static void 1357 ucom_cfg_line_state(struct usb_proc_msg *_task) 1358 { 1359 struct ucom_cfg_task *task = 1360 (struct ucom_cfg_task *)_task; 1361 struct ucom_softc *sc = task->sc; 1362 uint8_t notch_bits; 1363 uint8_t any_bits; 1364 uint8_t prev_value; 1365 uint8_t last_value; 1366 uint8_t mask; 1367 1368 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { 1369 return; 1370 } 1371 1372 mask = 0; 1373 /* compute callback mask */ 1374 if (sc->sc_callback->ucom_cfg_set_dtr) 1375 mask |= UCOM_LS_DTR; 1376 if (sc->sc_callback->ucom_cfg_set_rts) 1377 mask |= UCOM_LS_RTS; 1378 if (sc->sc_callback->ucom_cfg_set_break) 1379 mask |= UCOM_LS_BREAK; 1380 if (sc->sc_callback->ucom_cfg_set_ring) 1381 mask |= UCOM_LS_RING; 1382 1383 /* compute the bits we are to program */ 1384 notch_bits = (sc->sc_pls_set & sc->sc_pls_clr) & mask; 1385 any_bits = (sc->sc_pls_set | sc->sc_pls_clr) & mask; 1386 prev_value = sc->sc_pls_curr ^ notch_bits; 1387 last_value = sc->sc_pls_curr; 1388 1389 /* reset programmed line state */ 1390 sc->sc_pls_curr = 0; 1391 sc->sc_pls_set = 0; 1392 sc->sc_pls_clr = 0; 1393 1394 /* ensure that we don't lose any levels */ 1395 if (notch_bits & UCOM_LS_DTR) 1396 sc->sc_callback->ucom_cfg_set_dtr(sc, 1397 (prev_value & UCOM_LS_DTR) ? 1 : 0); 1398 if (notch_bits & UCOM_LS_RTS) 1399 sc->sc_callback->ucom_cfg_set_rts(sc, 1400 (prev_value & UCOM_LS_RTS) ? 1 : 0); 1401 if (notch_bits & UCOM_LS_BREAK) 1402 sc->sc_callback->ucom_cfg_set_break(sc, 1403 (prev_value & UCOM_LS_BREAK) ? 1 : 0); 1404 if (notch_bits & UCOM_LS_RING) 1405 sc->sc_callback->ucom_cfg_set_ring(sc, 1406 (prev_value & UCOM_LS_RING) ? 1 : 0); 1407 1408 /* set last value */ 1409 if (any_bits & UCOM_LS_DTR) 1410 sc->sc_callback->ucom_cfg_set_dtr(sc, 1411 (last_value & UCOM_LS_DTR) ? 1 : 0); 1412 if (any_bits & UCOM_LS_RTS) 1413 sc->sc_callback->ucom_cfg_set_rts(sc, 1414 (last_value & UCOM_LS_RTS) ? 1 : 0); 1415 if (any_bits & UCOM_LS_BREAK) 1416 sc->sc_callback->ucom_cfg_set_break(sc, 1417 (last_value & UCOM_LS_BREAK) ? 1 : 0); 1418 if (any_bits & UCOM_LS_RING) 1419 sc->sc_callback->ucom_cfg_set_ring(sc, 1420 (last_value & UCOM_LS_RING) ? 1 : 0); 1421 } 1422 1423 static void 1424 ucom_line_state(struct ucom_softc *sc, 1425 uint8_t set_bits, uint8_t clear_bits) 1426 { 1427 UCOM_MTX_ASSERT(sc, MA_OWNED); 1428 1429 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1430 return; 1431 } 1432 1433 DPRINTF("on=0x%02x, off=0x%02x\n", set_bits, clear_bits); 1434 1435 /* update current programmed line state */ 1436 sc->sc_pls_curr |= set_bits; 1437 sc->sc_pls_curr &= ~clear_bits; 1438 sc->sc_pls_set |= set_bits; 1439 sc->sc_pls_clr |= clear_bits; 1440 1441 /* defer driver programming */ 1442 ucom_queue_command(sc, ucom_cfg_line_state, NULL, 1443 &sc->sc_line_state_task[0].hdr, 1444 &sc->sc_line_state_task[1].hdr); 1445 } 1446 1447 static void 1448 ucom_ring(struct ucom_softc *sc, uint8_t onoff) 1449 { 1450 DPRINTF("onoff = %d\n", onoff); 1451 1452 if (onoff) 1453 ucom_line_state(sc, UCOM_LS_RING, 0); 1454 else 1455 ucom_line_state(sc, 0, UCOM_LS_RING); 1456 } 1457 1458 static void 1459 ucom_break(struct ucom_softc *sc, uint8_t onoff) 1460 { 1461 DPRINTF("onoff = %d\n", onoff); 1462 1463 if (onoff) 1464 ucom_line_state(sc, UCOM_LS_BREAK, 0); 1465 else 1466 ucom_line_state(sc, 0, UCOM_LS_BREAK); 1467 } 1468 1469 static void 1470 ucom_dtr(struct ucom_softc *sc, uint8_t onoff) 1471 { 1472 DPRINTF("onoff = %d\n", onoff); 1473 1474 if (onoff) 1475 ucom_line_state(sc, UCOM_LS_DTR, 0); 1476 else 1477 ucom_line_state(sc, 0, UCOM_LS_DTR); 1478 } 1479 1480 static void 1481 ucom_rts(struct ucom_softc *sc, uint8_t onoff) 1482 { 1483 DPRINTF("onoff = %d\n", onoff); 1484 1485 if (onoff) 1486 ucom_line_state(sc, UCOM_LS_RTS, 0); 1487 else 1488 ucom_line_state(sc, 0, UCOM_LS_RTS); 1489 } 1490 1491 static void 1492 ucom_cfg_status_change(struct usb_proc_msg *_task) 1493 { 1494 struct ucom_cfg_task *task = 1495 (struct ucom_cfg_task *)_task; 1496 struct ucom_softc *sc = task->sc; 1497 struct tty *tp; 1498 uint8_t new_msr; 1499 uint8_t new_lsr; 1500 uint8_t msr_delta; 1501 uint8_t lsr_delta; 1502 1503 tp = sc->sc_tty; 1504 1505 UCOM_MTX_ASSERT(sc, MA_OWNED); 1506 1507 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { 1508 return; 1509 } 1510 if (sc->sc_callback->ucom_cfg_get_status == NULL) { 1511 return; 1512 } 1513 /* get status */ 1514 1515 new_msr = 0; 1516 new_lsr = 0; 1517 1518 (sc->sc_callback->ucom_cfg_get_status) (sc, &new_lsr, &new_msr); 1519 1520 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1521 /* TTY device closed */ 1522 return; 1523 } 1524 msr_delta = (sc->sc_msr ^ new_msr); 1525 lsr_delta = (sc->sc_lsr ^ new_lsr); 1526 1527 sc->sc_msr = new_msr; 1528 sc->sc_lsr = new_lsr; 1529 1530 #if 0 /* missing pps_capture */ 1531 /* 1532 * Time pulse counting support. Note that both CTS and DCD are 1533 * active-low signals. The status bit is high to indicate that 1534 * the signal on the line is low, which corresponds to a PPS 1535 * clear event. 1536 */ 1537 switch(ucom_pps_mode) { 1538 case 1: 1539 if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) && 1540 (msr_delta & SER_CTS)) { 1541 pps_capture(&sc->sc_pps); 1542 pps_event(&sc->sc_pps, (sc->sc_msr & SER_CTS) ? 1543 PPS_CAPTURECLEAR : PPS_CAPTUREASSERT); 1544 } 1545 break; 1546 case 2: 1547 if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) && 1548 (msr_delta & SER_DCD)) { 1549 pps_capture(&sc->sc_pps); 1550 pps_event(&sc->sc_pps, (sc->sc_msr & SER_DCD) ? 1551 PPS_CAPTURECLEAR : PPS_CAPTUREASSERT); 1552 } 1553 break; 1554 default: 1555 break; 1556 } 1557 #endif 1558 1559 if (msr_delta & SER_DCD) { 1560 1561 int onoff = (sc->sc_msr & SER_DCD) ? 1 : 0; 1562 1563 DPRINTF("DCD changed to %d\n", onoff); 1564 1565 (*linesw[tp->t_line].l_modem)(tp, onoff); 1566 } 1567 1568 if ((lsr_delta & ULSR_BI) && (sc->sc_lsr & ULSR_BI)) { 1569 1570 DPRINTF("BREAK detected\n"); 1571 (*linesw[tp->t_line].l_rint)(0, tp); 1572 1573 /* 1574 ttydisc_rint(tp, 0, TRE_BREAK); 1575 ttydisc_rint_done(tp); 1576 */ 1577 } 1578 1579 if ((lsr_delta & ULSR_FE) && (sc->sc_lsr & ULSR_FE)) { 1580 1581 DPRINTF("Frame error detected\n"); 1582 (*linesw[tp->t_line].l_rint)(0, tp); 1583 1584 /* 1585 ttydisc_rint(tp, 0, TRE_FRAMING); 1586 ttydisc_rint_done(tp); 1587 */ 1588 } 1589 1590 if ((lsr_delta & ULSR_PE) && (sc->sc_lsr & ULSR_PE)) { 1591 1592 DPRINTF("Parity error detected\n"); 1593 (*linesw[tp->t_line].l_rint)(0, tp); 1594 /* 1595 ttydisc_rint(tp, 0, TRE_PARITY); 1596 ttydisc_rint_done(tp); 1597 */ 1598 } 1599 } 1600 1601 void 1602 ucom_status_change(struct ucom_softc *sc) 1603 { 1604 UCOM_MTX_ASSERT(sc, MA_OWNED); 1605 1606 if (sc->sc_flag & UCOM_FLAG_CONSOLE) 1607 return; /* not supported */ 1608 1609 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1610 return; 1611 } 1612 DPRINTF("\n"); 1613 1614 ucom_queue_command(sc, ucom_cfg_status_change, NULL, 1615 &sc->sc_status_task[0].hdr, 1616 &sc->sc_status_task[1].hdr); 1617 } 1618 1619 static void 1620 ucom_cfg_param(struct usb_proc_msg *_task) 1621 { 1622 struct ucom_param_task *task = 1623 (struct ucom_param_task *)_task; 1624 struct ucom_softc *sc = task->sc; 1625 1626 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { 1627 return; 1628 } 1629 if (sc->sc_callback->ucom_cfg_param == NULL) { 1630 return; 1631 } 1632 1633 (sc->sc_callback->ucom_cfg_param) (sc, &task->termios_copy); 1634 1635 /* wait a little */ 1636 usb_pause_mtx(sc->sc_lock, hz / 10); 1637 } 1638 1639 static int 1640 ucom_param(struct tty *tp, struct termios *t) 1641 { 1642 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc; 1643 uint8_t opened; 1644 int error; 1645 1646 lwkt_gettoken(&tp->t_token); 1647 UCOM_MTX_ASSERT(sc, MA_OWNED); 1648 1649 opened = 0; 1650 error = 0; 1651 1652 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1653 1654 /* XXX the TTY layer should call "open()" first! */ 1655 /* 1656 * Not quite: Its ordering is partly backwards, but 1657 * some parameters must be set early in ttydev_open(), 1658 * possibly before calling ttydevsw_open(). 1659 */ 1660 error = ucom_open(sc); 1661 1662 if (error) { 1663 goto done; 1664 } 1665 opened = 1; 1666 } 1667 DPRINTF("sc = %p\n", sc); 1668 1669 /* Check requested parameters. */ 1670 if (t->c_ispeed && (t->c_ispeed != t->c_ospeed)) { 1671 /* XXX c_ospeed == 0 is perfectly valid. */ 1672 DPRINTF("mismatch ispeed and ospeed\n"); 1673 error = EINVAL; 1674 goto done; 1675 } 1676 t->c_ispeed = t->c_ospeed; 1677 1678 if (sc->sc_callback->ucom_pre_param) { 1679 /* Let the lower layer verify the parameters */ 1680 error = (sc->sc_callback->ucom_pre_param) (sc, t); 1681 if (error) { 1682 DPRINTF("callback error = %d\n", error); 1683 goto done; 1684 } 1685 } 1686 1687 /* Disable transfers */ 1688 sc->sc_flag &= ~UCOM_FLAG_GP_DATA; 1689 1690 /* Queue baud rate programming command first */ 1691 ucom_queue_command(sc, ucom_cfg_param, t, 1692 &sc->sc_param_task[0].hdr, 1693 &sc->sc_param_task[1].hdr); 1694 1695 /* Queue transfer enable command last */ 1696 ucom_queue_command(sc, ucom_cfg_start_transfers, NULL, 1697 &sc->sc_start_task[0].hdr, 1698 &sc->sc_start_task[1].hdr); 1699 1700 if (t->c_cflag & CRTS_IFLOW) { 1701 sc->sc_flag |= UCOM_FLAG_RTS_IFLOW; 1702 } else if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW) { 1703 sc->sc_flag &= ~UCOM_FLAG_RTS_IFLOW; 1704 ucom_modem(tp, SER_RTS, 0); 1705 } 1706 done: 1707 if (error) { 1708 if (opened) { 1709 ucom_close(sc); 1710 } 1711 } 1712 lwkt_reltoken(&tp->t_token); 1713 1714 return (error); 1715 } 1716 1717 static void 1718 ucom_start(struct tty *tp) 1719 { 1720 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc; 1721 int didlock; 1722 1723 /* may be called locked or unlocked */ 1724 if (lockowned(sc->sc_lock)) { 1725 didlock = 0; 1726 } else { 1727 UCOM_MTX_LOCK(sc); 1728 didlock = 1; 1729 } 1730 /* UCOM_MTX_ASSERT(sc, MA_OWNED); */ 1731 1732 DPRINTF("sc = %p\n", sc); 1733 1734 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1735 /* The higher layer is not ready */ 1736 if (didlock) 1737 UCOM_MTX_UNLOCK(sc); 1738 return; 1739 } 1740 1741 lwkt_gettoken(&tp->t_token); 1742 1743 if (tp->t_state & TS_TBLOCK) { 1744 if (ISSET(sc->sc_mcr, SER_RTS) && 1745 ISSET(sc->sc_flag, UCOM_FLAG_RTS_IFLOW)) { 1746 DPRINTF("ucom_start: clear RTS\n"); 1747 (void)ucom_modem(tp, 0, SER_RTS); 1748 } 1749 } else { 1750 if (!ISSET(sc->sc_mcr, SER_RTS) && 1751 tp->t_rawq.c_cc <= tp->t_ilowat && 1752 ISSET(sc->sc_flag, UCOM_FLAG_RTS_IFLOW)) { 1753 DPRINTF("ucom_start: set RTS\n"); 1754 (void)ucom_modem(tp, SER_RTS, 0); 1755 } 1756 } 1757 1758 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) { 1759 ttwwakeup(tp); 1760 DPRINTF("ucom_start: stopped\n"); 1761 goto out; 1762 } 1763 1764 if (tp->t_outq.c_cc <= tp->t_olowat) { 1765 if (ISSET(tp->t_state, TS_SO_OLOWAT)) { 1766 CLR(tp->t_state, TS_SO_OLOWAT); 1767 wakeup(TSA_OLOWAT(tp)); 1768 } 1769 KNOTE(&tp->t_wkq.ki_note, 0); 1770 if (tp->t_outq.c_cc == 0) { 1771 if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) == 1772 TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) { 1773 CLR(tp->t_state, TS_SO_OCOMPLETE); 1774 wakeup(TSA_OCOMPLETE(tp)); 1775 } 1776 goto out; 1777 } 1778 } 1779 1780 DPRINTF("about to start write?\n"); 1781 ucom_start_transfers(sc); 1782 1783 ttwwakeup(tp); 1784 1785 out: 1786 lwkt_reltoken(&tp->t_token); 1787 if (didlock) 1788 UCOM_MTX_UNLOCK(sc); 1789 } 1790 1791 static void 1792 ucom_stop(struct tty *tp, int flag) 1793 { 1794 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc; 1795 1796 DPRINTF("sc = %p, x = 0x%x\n", sc, flag); 1797 1798 lwkt_gettoken(&tp->t_token); 1799 if (flag & FREAD) { 1800 /* 1801 * This is just supposed to flush pending receive data, 1802 * not stop the reception of data entirely! 1803 */ 1804 DPRINTF("read\n"); 1805 if (sc->sc_callback->ucom_stop_read) { 1806 (sc->sc_callback->ucom_stop_read) (sc); 1807 } 1808 if (sc->sc_callback->ucom_start_read) { 1809 (sc->sc_callback->ucom_start_read) (sc); 1810 } 1811 #if 0 1812 ucomstopread(sc); 1813 ucomstartread(sc); 1814 #endif 1815 } 1816 1817 if (flag & FWRITE) { 1818 DPRINTF("write\n"); 1819 if (ISSET(tp->t_state, TS_BUSY)) { 1820 /* XXX do what? */ 1821 if (!ISSET(tp->t_state, TS_TTSTOP)) 1822 SET(tp->t_state, TS_FLUSH); 1823 } 1824 } 1825 1826 DPRINTF("done\n"); 1827 lwkt_reltoken(&tp->t_token); 1828 } 1829 1830 /*------------------------------------------------------------------------* 1831 * ucom_get_data 1832 * Input values: 1833 * len: maximum length of data to get 1834 * 1835 * Get data from the TTY layer 1836 * 1837 * Return values: 1838 * 0: No data is available. 1839 * Else: Data is available. 1840 *------------------------------------------------------------------------*/ 1841 1842 /* Copy data from the tty layer to usb */ 1843 uint8_t 1844 ucom_get_data(struct ucom_softc *sc, struct usb_page_cache *pc, 1845 uint32_t offset, uint32_t len, uint32_t *actlen) 1846 { 1847 struct usb_page_search res; 1848 struct tty *tp = sc->sc_tty; 1849 uint32_t cnt; 1850 uint32_t offset_orig; 1851 1852 DPRINTF("\n"); 1853 1854 UCOM_MTX_ASSERT(sc, MA_OWNED); 1855 1856 if (sc->sc_flag & UCOM_FLAG_CONSOLE) { 1857 unsigned int temp; 1858 1859 /* get total TX length */ 1860 1861 temp = ucom_cons_tx_high - ucom_cons_tx_low; 1862 temp %= UCOM_CONS_BUFSIZE; 1863 1864 /* limit TX length */ 1865 1866 if (temp > (UCOM_CONS_BUFSIZE - ucom_cons_tx_low)) 1867 temp = (UCOM_CONS_BUFSIZE - ucom_cons_tx_low); 1868 1869 if (temp > len) 1870 temp = len; 1871 1872 /* copy in data */ 1873 1874 usbd_copy_in(pc, offset, ucom_cons_tx_buf + ucom_cons_tx_low, temp); 1875 1876 /* update counters */ 1877 1878 ucom_cons_tx_low += temp; 1879 ucom_cons_tx_low %= UCOM_CONS_BUFSIZE; 1880 1881 /* store actual length */ 1882 1883 *actlen = temp; 1884 1885 return (temp ? 1 : 0); 1886 } 1887 1888 if (tty_gone(tp) || 1889 !(sc->sc_flag & UCOM_FLAG_GP_DATA)) { 1890 actlen[0] = 0; 1891 return (0); /* multiport device polling */ 1892 } 1893 1894 offset_orig = offset; 1895 1896 lwkt_gettoken(&tp->t_token); 1897 while (len != 0) { 1898 usbd_get_page(pc, offset, &res); 1899 1900 /* Buffer bigger than max requested data */ 1901 if (res.length > len) { 1902 res.length = len; 1903 } 1904 /* copy data directly into USB buffer */ 1905 SET(tp->t_state, TS_BUSY); 1906 cnt = clist_qtob(&tp->t_outq, res.buffer, len); 1907 if (cnt == 0) { 1908 DPRINTF("ucom_get_data: cnt == 0\n"); 1909 CLR(tp->t_state, TS_BUSY); 1910 break; 1911 } 1912 1913 CLR(tp->t_state, TS_BUSY); 1914 1915 /* XXX mp: This breaks avrdude, 1916 does the flush need to happen 1917 elsewhere? 1918 if (ISSET(tp->t_state, TS_FLUSH)) 1919 CLR(tp->t_state, TS_FLUSH); 1920 else 1921 ndflush(&tp->t_outq,cnt); 1922 */ 1923 1924 offset += cnt; 1925 len -= cnt; 1926 1927 if (cnt < res.length) { 1928 /* end of buffer */ 1929 break; 1930 } 1931 } 1932 lwkt_reltoken(&tp->t_token); 1933 1934 actlen[0] = offset - offset_orig; 1935 1936 DPRINTF("cnt=%d\n", actlen[0]); 1937 1938 if (actlen[0] == 0) { 1939 return (0); 1940 } 1941 return (1); 1942 } 1943 1944 /* 1945 * Write data to the tty layer 1946 */ 1947 1948 void 1949 ucom_put_data(struct ucom_softc *sc, struct usb_page_cache *pc, 1950 uint32_t offset, uint32_t len) 1951 { 1952 struct usb_page_search res; 1953 struct tty *tp = sc->sc_tty; 1954 char *buf; 1955 uint32_t cnt; 1956 int lostcc; 1957 1958 DPRINTF("\n"); 1959 1960 UCOM_MTX_ASSERT(sc, MA_OWNED); 1961 lwkt_gettoken(&tp->t_token); 1962 1963 if (sc->sc_flag & UCOM_FLAG_CONSOLE) { 1964 unsigned int temp; 1965 1966 /* get maximum RX length */ 1967 1968 temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_rx_high + ucom_cons_rx_low; 1969 temp %= UCOM_CONS_BUFSIZE; 1970 1971 /* limit RX length */ 1972 1973 if (temp > (UCOM_CONS_BUFSIZE - ucom_cons_rx_high)) 1974 temp = (UCOM_CONS_BUFSIZE - ucom_cons_rx_high); 1975 1976 if (temp > len) 1977 temp = len; 1978 1979 /* copy out data */ 1980 1981 usbd_copy_out(pc, offset, ucom_cons_rx_buf + ucom_cons_rx_high, temp); 1982 1983 /* update counters */ 1984 1985 ucom_cons_rx_high += temp; 1986 ucom_cons_rx_high %= UCOM_CONS_BUFSIZE; 1987 1988 lwkt_reltoken(&tp->t_token); 1989 return; 1990 } 1991 1992 if (tty_gone(tp)) { 1993 lwkt_reltoken(&tp->t_token); 1994 return; /* multiport device polling */ 1995 } 1996 if (len == 0) { 1997 lwkt_reltoken(&tp->t_token); 1998 return; /* no data */ 1999 } 2000 2001 /* set a flag to prevent recursation ? */ 2002 2003 while (len > 0) { 2004 usbd_get_page(pc, offset, &res); 2005 2006 if (res.length > len) { 2007 res.length = len; 2008 } 2009 len -= res.length; 2010 offset += res.length; 2011 2012 /* pass characters to tty layer */ 2013 2014 buf = res.buffer; 2015 cnt = res.length; 2016 2017 /* first check if we can pass the buffer directly */ 2018 2019 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 2020 /* clear any jitter buffer */ 2021 sc->sc_jitterbuf_in = 0; 2022 sc->sc_jitterbuf_out = 0; 2023 2024 if (tp->t_rawq.c_cc + cnt > tp->t_ihiwat 2025 && (sc->sc_flag & UCOM_FLAG_RTS_IFLOW 2026 || tp->t_iflag & IXOFF) 2027 && !(tp->t_state & TS_TBLOCK)) 2028 ttyblock(tp); 2029 lostcc = clist_btoq((char *)buf, cnt, &tp->t_rawq); 2030 tp->t_rawcc += cnt; 2031 if (sc->hotchar) { 2032 while (cnt) { 2033 if (*buf == sc->hotchar) 2034 break; 2035 --cnt; 2036 ++buf; 2037 } 2038 if (cnt) 2039 setsofttty(); 2040 } 2041 ttwakeup(tp); 2042 if (tp->t_state & TS_TTSTOP 2043 && (tp->t_iflag & IXANY 2044 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 2045 tp->t_state &= ~TS_TTSTOP; 2046 tp->t_lflag &= ~FLUSHO; 2047 ucom_start(tp); 2048 } 2049 if (lostcc > 0) 2050 kprintf("lost %d chars\n", lostcc); 2051 2052 /* 2053 if (ttydisc_rint_bypass(tp, buf, cnt) != cnt) { 2054 DPRINTF("tp=%p, data lost\n", tp); 2055 } 2056 */ 2057 continue; 2058 } else { 2059 /* need to loop */ 2060 for (cnt = 0; cnt != res.length; cnt++) { 2061 if (sc->sc_jitterbuf_in != sc->sc_jitterbuf_out || 2062 (*linesw[tp->t_line].l_rint)((unsigned char)buf[cnt], tp) == -1) { 2063 uint16_t end; 2064 uint16_t pos; 2065 2066 pos = sc->sc_jitterbuf_in; 2067 end = sc->sc_jitterbuf_out + 2068 UCOM_JITTERBUF_SIZE - 1; 2069 2070 if (end >= UCOM_JITTERBUF_SIZE) 2071 end -= UCOM_JITTERBUF_SIZE; 2072 2073 for (; cnt != res.length; cnt++) { 2074 if (pos == end) 2075 break; 2076 sc->sc_jitterbuf[pos] = buf[cnt]; 2077 pos++; 2078 if (pos >= UCOM_JITTERBUF_SIZE) 2079 pos -= UCOM_JITTERBUF_SIZE; 2080 } 2081 2082 sc->sc_jitterbuf_in = pos; 2083 2084 /* set RTS in async fashion */ 2085 if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW) 2086 ucom_rts(sc, 1); 2087 2088 DPRINTF("tp=%p, lost %d " 2089 "chars\n", tp, res.length - cnt); 2090 break; 2091 } 2092 } 2093 } 2094 } 2095 lwkt_reltoken(&tp->t_token); 2096 /* 2097 ttydisc_rint_done(tp); 2098 */ 2099 } 2100 2101 #if 0 /* XXX */ 2102 static void 2103 ucom_free(void *xsc) 2104 { 2105 struct ucom_softc *sc = xsc; 2106 2107 if (sc->sc_callback->ucom_free != NULL) 2108 sc->sc_callback->ucom_free(sc); 2109 else 2110 /*ucom_unref(sc->sc_super) XXX hack, see end of ucom_detach_tty() */; 2111 2112 lockmgr(&ucom_lock, LK_EXCLUSIVE); 2113 ucom_close_refs--; 2114 lockmgr(&ucom_lock, LK_RELEASE); 2115 } 2116 2117 static cn_probe_t ucom_cnprobe; 2118 static cn_init_t ucom_cninit; 2119 static cn_term_t ucom_cnterm; 2120 static cn_getc_t ucom_cngetc; 2121 static cn_putc_t ucom_cnputc; 2122 2123 /* 2124 static cn_grab_t ucom_cngrab; 2125 static cn_ungrab_t ucom_cnungrab; 2126 CONSOLE_DRIVER(ucom); 2127 */ 2128 2129 static void 2130 ucom_cnprobe(struct consdev *cp) 2131 { 2132 if (ucom_cons_unit != -1) 2133 cp->cn_pri = CN_NORMAL; 2134 else 2135 cp->cn_pri = CN_DEAD; 2136 2137 /* 2138 strlcpy(cp->cn_name, "ucom", sizeof(cp->cn_name)); 2139 */ 2140 } 2141 2142 static void 2143 ucom_cninit(struct consdev *cp) 2144 { 2145 } 2146 2147 static void 2148 ucom_cnterm(struct consdev *cp) 2149 { 2150 } 2151 2152 static void 2153 ucom_cngrab(struct consdev *cp) 2154 { 2155 } 2156 2157 static void 2158 ucom_cnungrab(struct consdev *cp) 2159 { 2160 } 2161 2162 static int 2163 ucom_cngetc(struct consdev *cd) 2164 { 2165 struct ucom_softc *sc = ucom_cons_softc; 2166 int c; 2167 2168 if (sc == NULL) 2169 return (-1); 2170 2171 UCOM_MTX_LOCK(sc); 2172 2173 if (ucom_cons_rx_low != ucom_cons_rx_high) { 2174 c = ucom_cons_rx_buf[ucom_cons_rx_low]; 2175 ucom_cons_rx_low ++; 2176 ucom_cons_rx_low %= UCOM_CONS_BUFSIZE; 2177 } else { 2178 c = -1; 2179 } 2180 2181 /* start USB transfers */ 2182 ucom_outwakeup(sc->sc_tty); 2183 2184 UCOM_MTX_UNLOCK(sc); 2185 2186 /* poll if necessary */ 2187 /* 2188 if (kdb_active && sc->sc_callback->ucom_poll) 2189 (sc->sc_callback->ucom_poll) (sc); 2190 */ 2191 return (c); 2192 } 2193 2194 static void 2195 ucom_cnputc(void *cd, int c) 2196 /* 2197 ucom_cnputc(struct consdev *cd, int c) 2198 */ 2199 2200 { 2201 struct ucom_softc *sc = ucom_cons_softc; 2202 unsigned int temp; 2203 2204 if (sc == NULL) 2205 return; 2206 2207 repeat: 2208 2209 UCOM_MTX_LOCK(sc); 2210 2211 /* compute maximum TX length */ 2212 2213 temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_tx_high + ucom_cons_tx_low; 2214 temp %= UCOM_CONS_BUFSIZE; 2215 2216 if (temp) { 2217 ucom_cons_tx_buf[ucom_cons_tx_high] = c; 2218 ucom_cons_tx_high ++; 2219 ucom_cons_tx_high %= UCOM_CONS_BUFSIZE; 2220 } 2221 2222 /* start USB transfers */ 2223 ucom_outwakeup(sc->sc_tty); 2224 2225 UCOM_MTX_UNLOCK(sc); 2226 2227 /* poll if necessary */ 2228 #if 0 /* XXX */ 2229 if (kdb_active && sc->sc_callback->ucom_poll) { 2230 (sc->sc_callback->ucom_poll) (sc); 2231 /* simple flow control */ 2232 if (temp == 0) 2233 goto repeat; 2234 } 2235 #endif 2236 } 2237 #endif 2238 /*------------------------------------------------------------------------* 2239 * ucom_ref 2240 * 2241 * This function will increment the super UCOM reference count. 2242 *------------------------------------------------------------------------*/ 2243 void 2244 ucom_ref(struct ucom_super_softc *ssc) 2245 { 2246 lockmgr(&ucom_lock, LK_EXCLUSIVE); 2247 ssc->sc_refs++; 2248 lockmgr(&ucom_lock, LK_RELEASE); 2249 } 2250 2251 /*------------------------------------------------------------------------* 2252 * ucom_free_unit 2253 * 2254 * This function will free the super UCOM's allocated unit 2255 * number. This function can be called on a zero-initialized 2256 * structure. This function can be called multiple times. 2257 *------------------------------------------------------------------------*/ 2258 static void 2259 ucom_free_unit(struct ucom_super_softc *ssc) 2260 { 2261 if (!(ssc->sc_flag & UCOM_FLAG_FREE_UNIT)) 2262 return; 2263 2264 ucom_unit_free(ssc->sc_unit); 2265 2266 ssc->sc_flag &= ~UCOM_FLAG_FREE_UNIT; 2267 } 2268 2269 /*------------------------------------------------------------------------* 2270 * ucom_unref 2271 * 2272 * This function will decrement the super UCOM reference count. 2273 * 2274 * Return values: 2275 * 0: UCOM structures are still referenced. 2276 * Else: UCOM structures are no longer referenced. 2277 *------------------------------------------------------------------------*/ 2278 int 2279 ucom_unref(struct ucom_super_softc *ssc) 2280 { 2281 int retval; 2282 2283 lockmgr(&ucom_lock, LK_EXCLUSIVE); 2284 retval = (ssc->sc_refs < 2); 2285 ssc->sc_refs--; 2286 lockmgr(&ucom_lock, LK_RELEASE); 2287 2288 if (retval) 2289 ucom_free_unit(ssc); 2290 2291 return (retval); 2292 } 2293 2294 /* 2295 * NOTE: Must be called with tp->t_token held. 2296 */ 2297 static void 2298 disc_optim(struct tty *tp, struct termios *t, struct ucom_softc *sc) 2299 { 2300 ASSERT_LWKT_TOKEN_HELD(&tp->t_token); 2301 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 2302 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2303 && (!(t->c_iflag & PARMRK) 2304 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 2305 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 2306 && linesw[tp->t_line].l_rint == ttyinput) { 2307 DPRINTF("disc_optim: bypass l_rint\n"); 2308 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2309 } else { 2310 DPRINTF("disc_optim: can't bypass l_rint\n"); 2311 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2312 } 2313 sc->hotchar = linesw[tp->t_line].l_hotchar; 2314 } 2315 2316 #if defined(GDB) 2317 2318 #include <gdb/gdb.h> 2319 2320 static gdb_probe_f ucom_gdbprobe; 2321 static gdb_init_f ucom_gdbinit; 2322 static gdb_term_f ucom_gdbterm; 2323 static gdb_getc_f ucom_gdbgetc; 2324 static gdb_putc_f ucom_gdbputc; 2325 2326 GDB_DBGPORT(sio, ucom_gdbprobe, ucom_gdbinit, ucom_gdbterm, ucom_gdbgetc, ucom_gdbputc); 2327 2328 static int 2329 ucom_gdbprobe(void) 2330 { 2331 return ((ucom_cons_softc != NULL) ? 0 : -1); 2332 } 2333 2334 static void 2335 ucom_gdbinit(void) 2336 { 2337 } 2338 2339 static void 2340 ucom_gdbterm(void) 2341 { 2342 } 2343 2344 static void 2345 ucom_gdbputc(int c) 2346 { 2347 ucom_cnputc(NULL, c); 2348 } 2349 2350 static int 2351 ucom_gdbgetc(void) 2352 { 2353 return (ucom_cngetc(NULL)); 2354 } 2355 2356 #endif 2357