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/priv.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 = priv_check_cred(ap->a_cred, PRIV_ROOT, 0); 1125 if (error != 0) { 1126 lwkt_reltoken(&tp->t_token); 1127 UCOM_MTX_UNLOCK(sc); 1128 return (error); 1129 } 1130 *ct = *(struct termios *)data; 1131 lwkt_reltoken(&tp->t_token); 1132 UCOM_MTX_UNLOCK(sc); 1133 return (0); 1134 case TIOCGETA: 1135 *(struct termios *)data = *ct; 1136 lwkt_reltoken(&tp->t_token); 1137 UCOM_MTX_UNLOCK(sc); 1138 return (0); 1139 case TIOCGETD: 1140 *(int *)data = TTYDISC; 1141 lwkt_reltoken(&tp->t_token); 1142 UCOM_MTX_UNLOCK(sc); 1143 return (0); 1144 case TIOCGWINSZ: 1145 bzero(data, sizeof(struct winsize)); 1146 lwkt_reltoken(&tp->t_token); 1147 UCOM_MTX_UNLOCK(sc); 1148 return (0); 1149 default: 1150 lwkt_reltoken(&tp->t_token); 1151 UCOM_MTX_UNLOCK(sc); 1152 return (ENOTTY); 1153 } 1154 } 1155 1156 error = (*linesw[tp->t_line].l_ioctl)(tp, ap->a_cmd, ap->a_data, 1157 ap->a_fflag, ap->a_cred); 1158 1159 if (error != ENOIOCTL) { 1160 DPRINTF("ucomioctl: l_ioctl: error = %d\n", error); 1161 lwkt_reltoken(&tp->t_token); 1162 UCOM_MTX_UNLOCK(sc); 1163 return (error); 1164 } 1165 1166 error = ttioctl(tp, ap->a_cmd, ap->a_data, ap->a_fflag); 1167 disc_optim(tp, &tp->t_termios, sc); 1168 if (error != ENOIOCTL) { 1169 DPRINTF("ucomioctl: ttioctl: error = %d\n", error); 1170 lwkt_reltoken(&tp->t_token); 1171 UCOM_MTX_UNLOCK(sc); 1172 1173 return (error); 1174 } 1175 1176 error = 0; 1177 1178 switch (cmd) { 1179 #if 0 /* XXXDF */ 1180 case TIOCSRING: 1181 ucom_ring(sc, 1); 1182 error = 0; 1183 break; 1184 case TIOCCRING: 1185 ucom_ring(sc, 0); 1186 error = 0; 1187 break; 1188 #endif 1189 case TIOCSBRK: 1190 ucom_break(sc, 1); 1191 error = 0; 1192 break; 1193 case TIOCCBRK: 1194 ucom_break(sc, 0); 1195 error = 0; 1196 break; 1197 case TIOCSDTR: 1198 ucom_dtr(sc, 1); 1199 break; 1200 case TIOCCDTR: 1201 ucom_dtr(sc, 0); 1202 break; 1203 case TIOCMSET: 1204 d = *(int *)ap->a_data; 1205 DPRINTF("ucomioctl: TIOCMSET, 0x%x\n", d); 1206 ucom_modem(tp, ucom_fromtio(d), 0); 1207 break; 1208 case TIOCMGET: 1209 d = ucom_modem(tp, 0, 0); 1210 DPRINTF("ucomioctl: TIOCMGET, 0x%x\n", d); 1211 *(int *)ap->a_data = ucom_totio(d); 1212 ucom_status_change(sc); 1213 break; 1214 case TIOCMBIS: 1215 d = *(int *)ap->a_data; 1216 ucom_modem(tp, ucom_fromtio(d), 0); 1217 break; 1218 case TIOCMBIC: 1219 d = *(int *)ap->a_data; 1220 ucom_modem(tp, 0, ucom_fromtio(d)); 1221 break; 1222 default: 1223 if (sc->sc_callback->ucom_ioctl) { 1224 error = (sc->sc_callback->ucom_ioctl) 1225 (sc, cmd, data, 0, curthread); 1226 if (error>=0) { 1227 lwkt_reltoken(&tp->t_token); 1228 UCOM_MTX_UNLOCK(sc); 1229 1230 return(error); 1231 } 1232 } else { 1233 error = ENOIOCTL; 1234 } 1235 if (error == ENOIOCTL) 1236 error = pps_ioctl(cmd, data, &sc->sc_pps); 1237 break; 1238 } 1239 lwkt_reltoken(&tp->t_token); 1240 UCOM_MTX_UNLOCK(sc); 1241 1242 return (error); 1243 } 1244 1245 static int 1246 ucom_totio(int bits) 1247 { 1248 int rbits = 0; 1249 1250 SET(bits, TIOCM_LE); 1251 1252 if (ISSET(bits, SER_DTR)) { 1253 SET(rbits, TIOCM_DTR); 1254 } 1255 if (ISSET(bits, SER_RTS)) { 1256 SET(rbits, TIOCM_RTS); 1257 } 1258 if (ISSET(bits, SER_CTS)) { 1259 SET(rbits, TIOCM_CTS); 1260 } 1261 if (ISSET(bits, SER_DCD)) { 1262 SET(rbits, TIOCM_CD); 1263 } 1264 if (ISSET(bits, SER_DSR)) { 1265 SET(rbits, TIOCM_DSR); 1266 } 1267 if (ISSET(bits, SER_RI)) { 1268 SET(rbits, TIOCM_RI); 1269 } 1270 1271 return (rbits); 1272 } 1273 1274 static int 1275 ucom_fromtio(int bits) 1276 { 1277 int rbits = 0; 1278 1279 if (ISSET(bits, TIOCM_DTR)) { 1280 SET(rbits, SER_DTR); 1281 } 1282 if (ISSET(bits, TIOCM_RTS)) { 1283 SET(rbits, SER_RTS); 1284 } 1285 if (ISSET(bits, TIOCM_CTS)) { 1286 SET(rbits, SER_CTS); 1287 } 1288 if (ISSET(bits, TIOCM_CD)) { 1289 SET(rbits, SER_DCD); 1290 } 1291 if (ISSET(bits, TIOCM_DSR)) { 1292 SET(rbits, SER_DSR); 1293 } 1294 if (ISSET(bits, TIOCM_RI)) { 1295 SET(rbits, SER_RI); 1296 } 1297 1298 return (rbits); 1299 } 1300 1301 static int 1302 ucom_modem(struct tty *tp, int sigon, int sigoff) 1303 { 1304 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc; 1305 uint8_t onoff; 1306 1307 UCOM_MTX_ASSERT(sc, MA_OWNED); 1308 1309 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1310 return (0); 1311 } 1312 if ((sigon == 0) && (sigoff == 0)) { 1313 1314 if (sc->sc_mcr & SER_DTR) { 1315 sigon |= SER_DTR; 1316 } 1317 if (sc->sc_mcr & SER_RTS) { 1318 sigon |= SER_RTS; 1319 } 1320 if (sc->sc_msr & SER_CTS) { 1321 sigon |= SER_CTS; 1322 } 1323 if (sc->sc_msr & SER_DCD) { 1324 sigon |= SER_DCD; 1325 } 1326 if (sc->sc_msr & SER_DSR) { 1327 sigon |= SER_DSR; 1328 } 1329 if (sc->sc_msr & SER_RI) { 1330 sigon |= SER_RI; 1331 } 1332 return (sigon); 1333 } 1334 if (sigon & SER_DTR) { 1335 sc->sc_mcr |= SER_DTR; 1336 } 1337 if (sigoff & SER_DTR) { 1338 sc->sc_mcr &= ~SER_DTR; 1339 } 1340 if (sigon & SER_RTS) { 1341 sc->sc_mcr |= SER_RTS; 1342 } 1343 if (sigoff & SER_RTS) { 1344 sc->sc_mcr &= ~SER_RTS; 1345 } 1346 onoff = (sc->sc_mcr & SER_DTR) ? 1 : 0; 1347 ucom_dtr(sc, onoff); 1348 1349 onoff = (sc->sc_mcr & SER_RTS) ? 1 : 0; 1350 ucom_rts(sc, onoff); 1351 1352 return (0); 1353 } 1354 1355 static void 1356 ucom_cfg_line_state(struct usb_proc_msg *_task) 1357 { 1358 struct ucom_cfg_task *task = 1359 (struct ucom_cfg_task *)_task; 1360 struct ucom_softc *sc = task->sc; 1361 uint8_t notch_bits; 1362 uint8_t any_bits; 1363 uint8_t prev_value; 1364 uint8_t last_value; 1365 uint8_t mask; 1366 1367 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { 1368 return; 1369 } 1370 1371 mask = 0; 1372 /* compute callback mask */ 1373 if (sc->sc_callback->ucom_cfg_set_dtr) 1374 mask |= UCOM_LS_DTR; 1375 if (sc->sc_callback->ucom_cfg_set_rts) 1376 mask |= UCOM_LS_RTS; 1377 if (sc->sc_callback->ucom_cfg_set_break) 1378 mask |= UCOM_LS_BREAK; 1379 if (sc->sc_callback->ucom_cfg_set_ring) 1380 mask |= UCOM_LS_RING; 1381 1382 /* compute the bits we are to program */ 1383 notch_bits = (sc->sc_pls_set & sc->sc_pls_clr) & mask; 1384 any_bits = (sc->sc_pls_set | sc->sc_pls_clr) & mask; 1385 prev_value = sc->sc_pls_curr ^ notch_bits; 1386 last_value = sc->sc_pls_curr; 1387 1388 /* reset programmed line state */ 1389 sc->sc_pls_curr = 0; 1390 sc->sc_pls_set = 0; 1391 sc->sc_pls_clr = 0; 1392 1393 /* ensure that we don't lose any levels */ 1394 if (notch_bits & UCOM_LS_DTR) 1395 sc->sc_callback->ucom_cfg_set_dtr(sc, 1396 (prev_value & UCOM_LS_DTR) ? 1 : 0); 1397 if (notch_bits & UCOM_LS_RTS) 1398 sc->sc_callback->ucom_cfg_set_rts(sc, 1399 (prev_value & UCOM_LS_RTS) ? 1 : 0); 1400 if (notch_bits & UCOM_LS_BREAK) 1401 sc->sc_callback->ucom_cfg_set_break(sc, 1402 (prev_value & UCOM_LS_BREAK) ? 1 : 0); 1403 if (notch_bits & UCOM_LS_RING) 1404 sc->sc_callback->ucom_cfg_set_ring(sc, 1405 (prev_value & UCOM_LS_RING) ? 1 : 0); 1406 1407 /* set last value */ 1408 if (any_bits & UCOM_LS_DTR) 1409 sc->sc_callback->ucom_cfg_set_dtr(sc, 1410 (last_value & UCOM_LS_DTR) ? 1 : 0); 1411 if (any_bits & UCOM_LS_RTS) 1412 sc->sc_callback->ucom_cfg_set_rts(sc, 1413 (last_value & UCOM_LS_RTS) ? 1 : 0); 1414 if (any_bits & UCOM_LS_BREAK) 1415 sc->sc_callback->ucom_cfg_set_break(sc, 1416 (last_value & UCOM_LS_BREAK) ? 1 : 0); 1417 if (any_bits & UCOM_LS_RING) 1418 sc->sc_callback->ucom_cfg_set_ring(sc, 1419 (last_value & UCOM_LS_RING) ? 1 : 0); 1420 } 1421 1422 static void 1423 ucom_line_state(struct ucom_softc *sc, 1424 uint8_t set_bits, uint8_t clear_bits) 1425 { 1426 UCOM_MTX_ASSERT(sc, MA_OWNED); 1427 1428 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1429 return; 1430 } 1431 1432 DPRINTF("on=0x%02x, off=0x%02x\n", set_bits, clear_bits); 1433 1434 /* update current programmed line state */ 1435 sc->sc_pls_curr |= set_bits; 1436 sc->sc_pls_curr &= ~clear_bits; 1437 sc->sc_pls_set |= set_bits; 1438 sc->sc_pls_clr |= clear_bits; 1439 1440 /* defer driver programming */ 1441 ucom_queue_command(sc, ucom_cfg_line_state, NULL, 1442 &sc->sc_line_state_task[0].hdr, 1443 &sc->sc_line_state_task[1].hdr); 1444 } 1445 1446 static void 1447 ucom_ring(struct ucom_softc *sc, uint8_t onoff) 1448 { 1449 DPRINTF("onoff = %d\n", onoff); 1450 1451 if (onoff) 1452 ucom_line_state(sc, UCOM_LS_RING, 0); 1453 else 1454 ucom_line_state(sc, 0, UCOM_LS_RING); 1455 } 1456 1457 static void 1458 ucom_break(struct ucom_softc *sc, uint8_t onoff) 1459 { 1460 DPRINTF("onoff = %d\n", onoff); 1461 1462 if (onoff) 1463 ucom_line_state(sc, UCOM_LS_BREAK, 0); 1464 else 1465 ucom_line_state(sc, 0, UCOM_LS_BREAK); 1466 } 1467 1468 static void 1469 ucom_dtr(struct ucom_softc *sc, uint8_t onoff) 1470 { 1471 DPRINTF("onoff = %d\n", onoff); 1472 1473 if (onoff) 1474 ucom_line_state(sc, UCOM_LS_DTR, 0); 1475 else 1476 ucom_line_state(sc, 0, UCOM_LS_DTR); 1477 } 1478 1479 static void 1480 ucom_rts(struct ucom_softc *sc, uint8_t onoff) 1481 { 1482 DPRINTF("onoff = %d\n", onoff); 1483 1484 if (onoff) 1485 ucom_line_state(sc, UCOM_LS_RTS, 0); 1486 else 1487 ucom_line_state(sc, 0, UCOM_LS_RTS); 1488 } 1489 1490 static void 1491 ucom_cfg_status_change(struct usb_proc_msg *_task) 1492 { 1493 struct ucom_cfg_task *task = 1494 (struct ucom_cfg_task *)_task; 1495 struct ucom_softc *sc = task->sc; 1496 struct tty *tp; 1497 uint8_t new_msr; 1498 uint8_t new_lsr; 1499 uint8_t msr_delta; 1500 uint8_t lsr_delta; 1501 1502 tp = sc->sc_tty; 1503 1504 UCOM_MTX_ASSERT(sc, MA_OWNED); 1505 1506 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { 1507 return; 1508 } 1509 if (sc->sc_callback->ucom_cfg_get_status == NULL) { 1510 return; 1511 } 1512 /* get status */ 1513 1514 new_msr = 0; 1515 new_lsr = 0; 1516 1517 (sc->sc_callback->ucom_cfg_get_status) (sc, &new_lsr, &new_msr); 1518 1519 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1520 /* TTY device closed */ 1521 return; 1522 } 1523 msr_delta = (sc->sc_msr ^ new_msr); 1524 lsr_delta = (sc->sc_lsr ^ new_lsr); 1525 1526 sc->sc_msr = new_msr; 1527 sc->sc_lsr = new_lsr; 1528 1529 #if 0 /* missing pps_capture */ 1530 /* 1531 * Time pulse counting support. Note that both CTS and DCD are 1532 * active-low signals. The status bit is high to indicate that 1533 * the signal on the line is low, which corresponds to a PPS 1534 * clear event. 1535 */ 1536 switch(ucom_pps_mode) { 1537 case 1: 1538 if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) && 1539 (msr_delta & SER_CTS)) { 1540 pps_capture(&sc->sc_pps); 1541 pps_event(&sc->sc_pps, (sc->sc_msr & SER_CTS) ? 1542 PPS_CAPTURECLEAR : PPS_CAPTUREASSERT); 1543 } 1544 break; 1545 case 2: 1546 if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) && 1547 (msr_delta & SER_DCD)) { 1548 pps_capture(&sc->sc_pps); 1549 pps_event(&sc->sc_pps, (sc->sc_msr & SER_DCD) ? 1550 PPS_CAPTURECLEAR : PPS_CAPTUREASSERT); 1551 } 1552 break; 1553 default: 1554 break; 1555 } 1556 #endif 1557 1558 if (msr_delta & SER_DCD) { 1559 1560 int onoff = (sc->sc_msr & SER_DCD) ? 1 : 0; 1561 1562 DPRINTF("DCD changed to %d\n", onoff); 1563 1564 (*linesw[tp->t_line].l_modem)(tp, onoff); 1565 } 1566 1567 if ((lsr_delta & ULSR_BI) && (sc->sc_lsr & ULSR_BI)) { 1568 1569 DPRINTF("BREAK detected\n"); 1570 (*linesw[tp->t_line].l_rint)(0, tp); 1571 1572 /* 1573 ttydisc_rint(tp, 0, TRE_BREAK); 1574 ttydisc_rint_done(tp); 1575 */ 1576 } 1577 1578 if ((lsr_delta & ULSR_FE) && (sc->sc_lsr & ULSR_FE)) { 1579 1580 DPRINTF("Frame error detected\n"); 1581 (*linesw[tp->t_line].l_rint)(0, tp); 1582 1583 /* 1584 ttydisc_rint(tp, 0, TRE_FRAMING); 1585 ttydisc_rint_done(tp); 1586 */ 1587 } 1588 1589 if ((lsr_delta & ULSR_PE) && (sc->sc_lsr & ULSR_PE)) { 1590 1591 DPRINTF("Parity error detected\n"); 1592 (*linesw[tp->t_line].l_rint)(0, tp); 1593 /* 1594 ttydisc_rint(tp, 0, TRE_PARITY); 1595 ttydisc_rint_done(tp); 1596 */ 1597 } 1598 } 1599 1600 void 1601 ucom_status_change(struct ucom_softc *sc) 1602 { 1603 UCOM_MTX_ASSERT(sc, MA_OWNED); 1604 1605 if (sc->sc_flag & UCOM_FLAG_CONSOLE) 1606 return; /* not supported */ 1607 1608 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1609 return; 1610 } 1611 DPRINTF("\n"); 1612 1613 ucom_queue_command(sc, ucom_cfg_status_change, NULL, 1614 &sc->sc_status_task[0].hdr, 1615 &sc->sc_status_task[1].hdr); 1616 } 1617 1618 static void 1619 ucom_cfg_param(struct usb_proc_msg *_task) 1620 { 1621 struct ucom_param_task *task = 1622 (struct ucom_param_task *)_task; 1623 struct ucom_softc *sc = task->sc; 1624 1625 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { 1626 return; 1627 } 1628 if (sc->sc_callback->ucom_cfg_param == NULL) { 1629 return; 1630 } 1631 1632 (sc->sc_callback->ucom_cfg_param) (sc, &task->termios_copy); 1633 1634 /* wait a little */ 1635 usb_pause_mtx(sc->sc_lock, hz / 10); 1636 } 1637 1638 static int 1639 ucom_param(struct tty *tp, struct termios *t) 1640 { 1641 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc; 1642 uint8_t opened; 1643 int error; 1644 1645 lwkt_gettoken(&tp->t_token); 1646 UCOM_MTX_ASSERT(sc, MA_OWNED); 1647 1648 opened = 0; 1649 error = 0; 1650 1651 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1652 1653 /* XXX the TTY layer should call "open()" first! */ 1654 /* 1655 * Not quite: Its ordering is partly backwards, but 1656 * some parameters must be set early in ttydev_open(), 1657 * possibly before calling ttydevsw_open(). 1658 */ 1659 error = ucom_open(sc); 1660 1661 if (error) { 1662 goto done; 1663 } 1664 opened = 1; 1665 } 1666 DPRINTF("sc = %p\n", sc); 1667 1668 /* Check requested parameters. */ 1669 if (t->c_ispeed && (t->c_ispeed != t->c_ospeed)) { 1670 /* XXX c_ospeed == 0 is perfectly valid. */ 1671 DPRINTF("mismatch ispeed and ospeed\n"); 1672 error = EINVAL; 1673 goto done; 1674 } 1675 t->c_ispeed = t->c_ospeed; 1676 1677 if (sc->sc_callback->ucom_pre_param) { 1678 /* Let the lower layer verify the parameters */ 1679 error = (sc->sc_callback->ucom_pre_param) (sc, t); 1680 if (error) { 1681 DPRINTF("callback error = %d\n", error); 1682 goto done; 1683 } 1684 } 1685 1686 /* Disable transfers */ 1687 sc->sc_flag &= ~UCOM_FLAG_GP_DATA; 1688 1689 /* Queue baud rate programming command first */ 1690 ucom_queue_command(sc, ucom_cfg_param, t, 1691 &sc->sc_param_task[0].hdr, 1692 &sc->sc_param_task[1].hdr); 1693 1694 /* Queue transfer enable command last */ 1695 ucom_queue_command(sc, ucom_cfg_start_transfers, NULL, 1696 &sc->sc_start_task[0].hdr, 1697 &sc->sc_start_task[1].hdr); 1698 1699 if (t->c_cflag & CRTS_IFLOW) { 1700 sc->sc_flag |= UCOM_FLAG_RTS_IFLOW; 1701 } else if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW) { 1702 sc->sc_flag &= ~UCOM_FLAG_RTS_IFLOW; 1703 ucom_modem(tp, SER_RTS, 0); 1704 } 1705 done: 1706 if (error) { 1707 if (opened) { 1708 ucom_close(sc); 1709 } 1710 } 1711 lwkt_reltoken(&tp->t_token); 1712 1713 return (error); 1714 } 1715 1716 static void 1717 ucom_start(struct tty *tp) 1718 { 1719 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc; 1720 int didlock; 1721 1722 /* may be called locked or unlocked */ 1723 if (lockowned(sc->sc_lock)) { 1724 didlock = 0; 1725 } else { 1726 UCOM_MTX_LOCK(sc); 1727 didlock = 1; 1728 } 1729 /* UCOM_MTX_ASSERT(sc, MA_OWNED); */ 1730 1731 DPRINTF("sc = %p\n", sc); 1732 1733 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1734 /* The higher layer is not ready */ 1735 if (didlock) 1736 UCOM_MTX_UNLOCK(sc); 1737 return; 1738 } 1739 1740 lwkt_gettoken(&tp->t_token); 1741 1742 if (tp->t_state & TS_TBLOCK) { 1743 if (ISSET(sc->sc_mcr, SER_RTS) && 1744 ISSET(sc->sc_flag, UCOM_FLAG_RTS_IFLOW)) { 1745 DPRINTF("ucom_start: clear RTS\n"); 1746 (void)ucom_modem(tp, 0, SER_RTS); 1747 } 1748 } else { 1749 if (!ISSET(sc->sc_mcr, SER_RTS) && 1750 tp->t_rawq.c_cc <= tp->t_ilowat && 1751 ISSET(sc->sc_flag, UCOM_FLAG_RTS_IFLOW)) { 1752 DPRINTF("ucom_start: set RTS\n"); 1753 (void)ucom_modem(tp, SER_RTS, 0); 1754 } 1755 } 1756 1757 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) { 1758 ttwwakeup(tp); 1759 DPRINTF("ucom_start: stopped\n"); 1760 goto out; 1761 } 1762 1763 if (tp->t_outq.c_cc <= tp->t_olowat) { 1764 if (ISSET(tp->t_state, TS_SO_OLOWAT)) { 1765 CLR(tp->t_state, TS_SO_OLOWAT); 1766 wakeup(TSA_OLOWAT(tp)); 1767 } 1768 KNOTE(&tp->t_wkq.ki_note, 0); 1769 if (tp->t_outq.c_cc == 0) { 1770 if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) == 1771 TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) { 1772 CLR(tp->t_state, TS_SO_OCOMPLETE); 1773 wakeup(TSA_OCOMPLETE(tp)); 1774 } 1775 goto out; 1776 } 1777 } 1778 1779 DPRINTF("about to start write?\n"); 1780 ucom_start_transfers(sc); 1781 1782 ttwwakeup(tp); 1783 1784 out: 1785 lwkt_reltoken(&tp->t_token); 1786 if (didlock) 1787 UCOM_MTX_UNLOCK(sc); 1788 } 1789 1790 static void 1791 ucom_stop(struct tty *tp, int flag) 1792 { 1793 struct ucom_softc *sc = (struct ucom_softc *)tp->t_sc; 1794 1795 DPRINTF("sc = %p, x = 0x%x\n", sc, flag); 1796 1797 lwkt_gettoken(&tp->t_token); 1798 if (flag & FREAD) { 1799 /* 1800 * This is just supposed to flush pending receive data, 1801 * not stop the reception of data entirely! 1802 */ 1803 DPRINTF("read\n"); 1804 if (sc->sc_callback->ucom_stop_read) { 1805 (sc->sc_callback->ucom_stop_read) (sc); 1806 } 1807 if (sc->sc_callback->ucom_start_read) { 1808 (sc->sc_callback->ucom_start_read) (sc); 1809 } 1810 #if 0 1811 ucomstopread(sc); 1812 ucomstartread(sc); 1813 #endif 1814 } 1815 1816 if (flag & FWRITE) { 1817 DPRINTF("write\n"); 1818 if (ISSET(tp->t_state, TS_BUSY)) { 1819 /* XXX do what? */ 1820 if (!ISSET(tp->t_state, TS_TTSTOP)) 1821 SET(tp->t_state, TS_FLUSH); 1822 } 1823 } 1824 1825 DPRINTF("done\n"); 1826 lwkt_reltoken(&tp->t_token); 1827 } 1828 1829 /*------------------------------------------------------------------------* 1830 * ucom_get_data 1831 * Input values: 1832 * len: maximum length of data to get 1833 * 1834 * Get data from the TTY layer 1835 * 1836 * Return values: 1837 * 0: No data is available. 1838 * Else: Data is available. 1839 *------------------------------------------------------------------------*/ 1840 1841 /* Copy data from the tty layer to usb */ 1842 uint8_t 1843 ucom_get_data(struct ucom_softc *sc, struct usb_page_cache *pc, 1844 uint32_t offset, uint32_t len, uint32_t *actlen) 1845 { 1846 struct usb_page_search res; 1847 struct tty *tp = sc->sc_tty; 1848 uint32_t cnt; 1849 uint32_t offset_orig; 1850 1851 DPRINTF("\n"); 1852 1853 UCOM_MTX_ASSERT(sc, MA_OWNED); 1854 1855 if (sc->sc_flag & UCOM_FLAG_CONSOLE) { 1856 unsigned int temp; 1857 1858 /* get total TX length */ 1859 1860 temp = ucom_cons_tx_high - ucom_cons_tx_low; 1861 temp %= UCOM_CONS_BUFSIZE; 1862 1863 /* limit TX length */ 1864 1865 if (temp > (UCOM_CONS_BUFSIZE - ucom_cons_tx_low)) 1866 temp = (UCOM_CONS_BUFSIZE - ucom_cons_tx_low); 1867 1868 if (temp > len) 1869 temp = len; 1870 1871 /* copy in data */ 1872 1873 usbd_copy_in(pc, offset, ucom_cons_tx_buf + ucom_cons_tx_low, temp); 1874 1875 /* update counters */ 1876 1877 ucom_cons_tx_low += temp; 1878 ucom_cons_tx_low %= UCOM_CONS_BUFSIZE; 1879 1880 /* store actual length */ 1881 1882 *actlen = temp; 1883 1884 return (temp ? 1 : 0); 1885 } 1886 1887 if (tty_gone(tp) || 1888 !(sc->sc_flag & UCOM_FLAG_GP_DATA)) { 1889 actlen[0] = 0; 1890 return (0); /* multiport device polling */ 1891 } 1892 1893 offset_orig = offset; 1894 1895 lwkt_gettoken(&tp->t_token); 1896 while (len != 0) { 1897 usbd_get_page(pc, offset, &res); 1898 1899 /* Buffer bigger than max requested data */ 1900 if (res.length > len) { 1901 res.length = len; 1902 } 1903 /* copy data directly into USB buffer */ 1904 SET(tp->t_state, TS_BUSY); 1905 cnt = clist_qtob(&tp->t_outq, res.buffer, len); 1906 if (cnt == 0) { 1907 DPRINTF("ucom_get_data: cnt == 0\n"); 1908 CLR(tp->t_state, TS_BUSY); 1909 break; 1910 } 1911 1912 CLR(tp->t_state, TS_BUSY); 1913 1914 /* XXX mp: This breaks avrdude, 1915 does the flush need to happen 1916 elsewhere? 1917 if (ISSET(tp->t_state, TS_FLUSH)) 1918 CLR(tp->t_state, TS_FLUSH); 1919 else 1920 ndflush(&tp->t_outq,cnt); 1921 */ 1922 1923 offset += cnt; 1924 len -= cnt; 1925 1926 if (cnt < res.length) { 1927 /* end of buffer */ 1928 break; 1929 } 1930 } 1931 lwkt_reltoken(&tp->t_token); 1932 1933 actlen[0] = offset - offset_orig; 1934 1935 DPRINTF("cnt=%d\n", actlen[0]); 1936 1937 if (actlen[0] == 0) { 1938 return (0); 1939 } 1940 return (1); 1941 } 1942 1943 /* 1944 * Write data to the tty layer 1945 */ 1946 1947 void 1948 ucom_put_data(struct ucom_softc *sc, struct usb_page_cache *pc, 1949 uint32_t offset, uint32_t len) 1950 { 1951 struct usb_page_search res; 1952 struct tty *tp = sc->sc_tty; 1953 char *buf; 1954 uint32_t cnt; 1955 int lostcc; 1956 1957 DPRINTF("\n"); 1958 1959 UCOM_MTX_ASSERT(sc, MA_OWNED); 1960 lwkt_gettoken(&tp->t_token); 1961 1962 if (sc->sc_flag & UCOM_FLAG_CONSOLE) { 1963 unsigned int temp; 1964 1965 /* get maximum RX length */ 1966 1967 temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_rx_high + ucom_cons_rx_low; 1968 temp %= UCOM_CONS_BUFSIZE; 1969 1970 /* limit RX length */ 1971 1972 if (temp > (UCOM_CONS_BUFSIZE - ucom_cons_rx_high)) 1973 temp = (UCOM_CONS_BUFSIZE - ucom_cons_rx_high); 1974 1975 if (temp > len) 1976 temp = len; 1977 1978 /* copy out data */ 1979 1980 usbd_copy_out(pc, offset, ucom_cons_rx_buf + ucom_cons_rx_high, temp); 1981 1982 /* update counters */ 1983 1984 ucom_cons_rx_high += temp; 1985 ucom_cons_rx_high %= UCOM_CONS_BUFSIZE; 1986 1987 lwkt_reltoken(&tp->t_token); 1988 return; 1989 } 1990 1991 if (tty_gone(tp)) { 1992 lwkt_reltoken(&tp->t_token); 1993 return; /* multiport device polling */ 1994 } 1995 if (len == 0) { 1996 lwkt_reltoken(&tp->t_token); 1997 return; /* no data */ 1998 } 1999 2000 /* set a flag to prevent recursation ? */ 2001 2002 while (len > 0) { 2003 usbd_get_page(pc, offset, &res); 2004 2005 if (res.length > len) { 2006 res.length = len; 2007 } 2008 len -= res.length; 2009 offset += res.length; 2010 2011 /* pass characters to tty layer */ 2012 2013 buf = res.buffer; 2014 cnt = res.length; 2015 2016 /* first check if we can pass the buffer directly */ 2017 2018 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 2019 /* clear any jitter buffer */ 2020 sc->sc_jitterbuf_in = 0; 2021 sc->sc_jitterbuf_out = 0; 2022 2023 if (tp->t_rawq.c_cc + cnt > tp->t_ihiwat 2024 && (sc->sc_flag & UCOM_FLAG_RTS_IFLOW 2025 || tp->t_iflag & IXOFF) 2026 && !(tp->t_state & TS_TBLOCK)) 2027 ttyblock(tp); 2028 lostcc = clist_btoq((char *)buf, cnt, &tp->t_rawq); 2029 tp->t_rawcc += cnt; 2030 if (sc->hotchar) { 2031 while (cnt) { 2032 if (*buf == sc->hotchar) 2033 break; 2034 --cnt; 2035 ++buf; 2036 } 2037 if (cnt) 2038 setsofttty(); 2039 } 2040 ttwakeup(tp); 2041 if (tp->t_state & TS_TTSTOP 2042 && (tp->t_iflag & IXANY 2043 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 2044 tp->t_state &= ~TS_TTSTOP; 2045 tp->t_lflag &= ~FLUSHO; 2046 ucom_start(tp); 2047 } 2048 if (lostcc > 0) 2049 kprintf("lost %d chars\n", lostcc); 2050 2051 /* 2052 if (ttydisc_rint_bypass(tp, buf, cnt) != cnt) { 2053 DPRINTF("tp=%p, data lost\n", tp); 2054 } 2055 */ 2056 continue; 2057 } else { 2058 /* need to loop */ 2059 for (cnt = 0; cnt != res.length; cnt++) { 2060 if (sc->sc_jitterbuf_in != sc->sc_jitterbuf_out || 2061 (*linesw[tp->t_line].l_rint)((unsigned char)buf[cnt], tp) == -1) { 2062 uint16_t end; 2063 uint16_t pos; 2064 2065 pos = sc->sc_jitterbuf_in; 2066 end = sc->sc_jitterbuf_out + 2067 UCOM_JITTERBUF_SIZE - 1; 2068 2069 if (end >= UCOM_JITTERBUF_SIZE) 2070 end -= UCOM_JITTERBUF_SIZE; 2071 2072 for (; cnt != res.length; cnt++) { 2073 if (pos == end) 2074 break; 2075 sc->sc_jitterbuf[pos] = buf[cnt]; 2076 pos++; 2077 if (pos >= UCOM_JITTERBUF_SIZE) 2078 pos -= UCOM_JITTERBUF_SIZE; 2079 } 2080 2081 sc->sc_jitterbuf_in = pos; 2082 2083 /* set RTS in async fashion */ 2084 if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW) 2085 ucom_rts(sc, 1); 2086 2087 DPRINTF("tp=%p, lost %d " 2088 "chars\n", tp, res.length - cnt); 2089 break; 2090 } 2091 } 2092 } 2093 } 2094 lwkt_reltoken(&tp->t_token); 2095 /* 2096 ttydisc_rint_done(tp); 2097 */ 2098 } 2099 2100 #if 0 /* XXX */ 2101 static void 2102 ucom_free(void *xsc) 2103 { 2104 struct ucom_softc *sc = xsc; 2105 2106 if (sc->sc_callback->ucom_free != NULL) 2107 sc->sc_callback->ucom_free(sc); 2108 else 2109 /*ucom_unref(sc->sc_super) XXX hack, see end of ucom_detach_tty() */; 2110 2111 lockmgr(&ucom_lock, LK_EXCLUSIVE); 2112 ucom_close_refs--; 2113 lockmgr(&ucom_lock, LK_RELEASE); 2114 } 2115 2116 static cn_probe_t ucom_cnprobe; 2117 static cn_init_t ucom_cninit; 2118 static cn_term_t ucom_cnterm; 2119 static cn_getc_t ucom_cngetc; 2120 static cn_putc_t ucom_cnputc; 2121 2122 /* 2123 static cn_grab_t ucom_cngrab; 2124 static cn_ungrab_t ucom_cnungrab; 2125 CONSOLE_DRIVER(ucom); 2126 */ 2127 2128 static void 2129 ucom_cnprobe(struct consdev *cp) 2130 { 2131 if (ucom_cons_unit != -1) 2132 cp->cn_pri = CN_NORMAL; 2133 else 2134 cp->cn_pri = CN_DEAD; 2135 2136 /* 2137 strlcpy(cp->cn_name, "ucom", sizeof(cp->cn_name)); 2138 */ 2139 } 2140 2141 static void 2142 ucom_cninit(struct consdev *cp) 2143 { 2144 } 2145 2146 static void 2147 ucom_cnterm(struct consdev *cp) 2148 { 2149 } 2150 2151 static void 2152 ucom_cngrab(struct consdev *cp) 2153 { 2154 } 2155 2156 static void 2157 ucom_cnungrab(struct consdev *cp) 2158 { 2159 } 2160 2161 static int 2162 ucom_cngetc(struct consdev *cd) 2163 { 2164 struct ucom_softc *sc = ucom_cons_softc; 2165 int c; 2166 2167 if (sc == NULL) 2168 return (-1); 2169 2170 UCOM_MTX_LOCK(sc); 2171 2172 if (ucom_cons_rx_low != ucom_cons_rx_high) { 2173 c = ucom_cons_rx_buf[ucom_cons_rx_low]; 2174 ucom_cons_rx_low ++; 2175 ucom_cons_rx_low %= UCOM_CONS_BUFSIZE; 2176 } else { 2177 c = -1; 2178 } 2179 2180 /* start USB transfers */ 2181 ucom_outwakeup(sc->sc_tty); 2182 2183 UCOM_MTX_UNLOCK(sc); 2184 2185 /* poll if necessary */ 2186 /* 2187 if (kdb_active && sc->sc_callback->ucom_poll) 2188 (sc->sc_callback->ucom_poll) (sc); 2189 */ 2190 return (c); 2191 } 2192 2193 static void 2194 ucom_cnputc(void *cd, int c) 2195 /* 2196 ucom_cnputc(struct consdev *cd, int c) 2197 */ 2198 2199 { 2200 struct ucom_softc *sc = ucom_cons_softc; 2201 unsigned int temp; 2202 2203 if (sc == NULL) 2204 return; 2205 2206 repeat: 2207 2208 UCOM_MTX_LOCK(sc); 2209 2210 /* compute maximum TX length */ 2211 2212 temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_tx_high + ucom_cons_tx_low; 2213 temp %= UCOM_CONS_BUFSIZE; 2214 2215 if (temp) { 2216 ucom_cons_tx_buf[ucom_cons_tx_high] = c; 2217 ucom_cons_tx_high ++; 2218 ucom_cons_tx_high %= UCOM_CONS_BUFSIZE; 2219 } 2220 2221 /* start USB transfers */ 2222 ucom_outwakeup(sc->sc_tty); 2223 2224 UCOM_MTX_UNLOCK(sc); 2225 2226 /* poll if necessary */ 2227 #if 0 /* XXX */ 2228 if (kdb_active && sc->sc_callback->ucom_poll) { 2229 (sc->sc_callback->ucom_poll) (sc); 2230 /* simple flow control */ 2231 if (temp == 0) 2232 goto repeat; 2233 } 2234 #endif 2235 } 2236 #endif 2237 /*------------------------------------------------------------------------* 2238 * ucom_ref 2239 * 2240 * This function will increment the super UCOM reference count. 2241 *------------------------------------------------------------------------*/ 2242 void 2243 ucom_ref(struct ucom_super_softc *ssc) 2244 { 2245 lockmgr(&ucom_lock, LK_EXCLUSIVE); 2246 ssc->sc_refs++; 2247 lockmgr(&ucom_lock, LK_RELEASE); 2248 } 2249 2250 /*------------------------------------------------------------------------* 2251 * ucom_free_unit 2252 * 2253 * This function will free the super UCOM's allocated unit 2254 * number. This function can be called on a zero-initialized 2255 * structure. This function can be called multiple times. 2256 *------------------------------------------------------------------------*/ 2257 static void 2258 ucom_free_unit(struct ucom_super_softc *ssc) 2259 { 2260 if (!(ssc->sc_flag & UCOM_FLAG_FREE_UNIT)) 2261 return; 2262 2263 ucom_unit_free(ssc->sc_unit); 2264 2265 ssc->sc_flag &= ~UCOM_FLAG_FREE_UNIT; 2266 } 2267 2268 /*------------------------------------------------------------------------* 2269 * ucom_unref 2270 * 2271 * This function will decrement the super UCOM reference count. 2272 * 2273 * Return values: 2274 * 0: UCOM structures are still referenced. 2275 * Else: UCOM structures are no longer referenced. 2276 *------------------------------------------------------------------------*/ 2277 int 2278 ucom_unref(struct ucom_super_softc *ssc) 2279 { 2280 int retval; 2281 2282 lockmgr(&ucom_lock, LK_EXCLUSIVE); 2283 retval = (ssc->sc_refs < 2); 2284 ssc->sc_refs--; 2285 lockmgr(&ucom_lock, LK_RELEASE); 2286 2287 if (retval) 2288 ucom_free_unit(ssc); 2289 2290 return (retval); 2291 } 2292 2293 /* 2294 * NOTE: Must be called with tp->t_token held. 2295 */ 2296 static void 2297 disc_optim(struct tty *tp, struct termios *t, struct ucom_softc *sc) 2298 { 2299 ASSERT_LWKT_TOKEN_HELD(&tp->t_token); 2300 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 2301 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2302 && (!(t->c_iflag & PARMRK) 2303 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 2304 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 2305 && linesw[tp->t_line].l_rint == ttyinput) { 2306 DPRINTF("disc_optim: bypass l_rint\n"); 2307 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2308 } else { 2309 DPRINTF("disc_optim: can't bypass l_rint\n"); 2310 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2311 } 2312 sc->hotchar = linesw[tp->t_line].l_hotchar; 2313 } 2314 2315 #if defined(GDB) 2316 2317 #include <gdb/gdb.h> 2318 2319 static gdb_probe_f ucom_gdbprobe; 2320 static gdb_init_f ucom_gdbinit; 2321 static gdb_term_f ucom_gdbterm; 2322 static gdb_getc_f ucom_gdbgetc; 2323 static gdb_putc_f ucom_gdbputc; 2324 2325 GDB_DBGPORT(sio, ucom_gdbprobe, ucom_gdbinit, ucom_gdbterm, ucom_gdbgetc, ucom_gdbputc); 2326 2327 static int 2328 ucom_gdbprobe(void) 2329 { 2330 return ((ucom_cons_softc != NULL) ? 0 : -1); 2331 } 2332 2333 static void 2334 ucom_gdbinit(void) 2335 { 2336 } 2337 2338 static void 2339 ucom_gdbterm(void) 2340 { 2341 } 2342 2343 static void 2344 ucom_gdbputc(int c) 2345 { 2346 ucom_cnputc(NULL, c); 2347 } 2348 2349 static int 2350 ucom_gdbgetc(void) 2351 { 2352 return (ucom_cngetc(NULL)); 2353 } 2354 2355 #endif 2356