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