1 /* $NetBSD: ucom.c,v 1.15 2000/02/08 18:45:27 augustss Exp $ */ 2 3 /* 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (augustss@carlstedt.se) at 9 * Carlstedt Research & Technology. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/ioctl.h> 44 #include <sys/conf.h> 45 #include <sys/tty.h> 46 #include <sys/file.h> 47 #include <sys/select.h> 48 #include <sys/proc.h> 49 #include <sys/vnode.h> 50 #include <sys/device.h> 51 #include <sys/poll.h> 52 53 #include <dev/usb/usb.h> 54 55 #include <dev/usb/usbdi.h> 56 #include <dev/usb/usbdi_util.h> 57 #include <dev/usb/usbdevs.h> 58 #include <dev/usb/usb_quirks.h> 59 60 #include <dev/usb/ucomvar.h> 61 62 #include "ucom.h" 63 64 #if NUCOM > 0 65 66 #ifdef UCOM_DEBUG 67 #define DPRINTFN(n, x) if (ucomdebug > (n)) logprintf x 68 int ucomdebug = 0; 69 #else 70 #define DPRINTFN(n, x) 71 #endif 72 #define DPRINTF(x) DPRINTFN(0, x) 73 74 #define UCOMUNIT_MASK 0x3ffff 75 #define UCOMDIALOUT_MASK 0x80000 76 #define UCOMCALLUNIT_MASK 0x40000 77 78 #define UCOMUNIT(x) (minor(x) & UCOMUNIT_MASK) 79 #define UCOMDIALOUT(x) (minor(x) & UCOMDIALOUT_MASK) 80 #define UCOMCALLUNIT(x) (minor(x) & UCOMCALLUNIT_MASK) 81 82 /* 83 * These are the maximum number of bytes transferred per frame. 84 * If some really high speed devices should use this driver they 85 * may need to be increased, but this is good enough for modems. 86 */ 87 #define UCOMIBUFSIZE 64 88 #define UCOMOBUFSIZE 256 89 90 struct ucom_softc { 91 USBBASEDEVICE sc_dev; /* base device */ 92 93 usbd_device_handle sc_udev; /* USB device */ 94 95 usbd_interface_handle sc_iface; /* data interface */ 96 97 int sc_bulkin_no; /* bulk in endpoint address */ 98 usbd_pipe_handle sc_bulkin_pipe; /* bulk in pipe */ 99 usbd_xfer_handle sc_ixfer; /* read request */ 100 u_char *sc_ibuf; /* read buffer */ 101 102 int sc_bulkout_no; /* bulk out endpoint address */ 103 usbd_pipe_handle sc_bulkout_pipe;/* bulk out pipe */ 104 usbd_xfer_handle sc_oxfer; /* write request */ 105 u_char *sc_obuf; /* write buffer */ 106 107 struct ucom_methods *sc_methods; 108 void *sc_parent; 109 int sc_portno; 110 111 struct tty *sc_tty; /* our tty */ 112 u_char sc_lsr; 113 u_char sc_msr; 114 u_char sc_mcr; 115 u_char sc_tx_stopped; 116 int sc_swflags; 117 118 u_char sc_opening; /* lock during open */ 119 u_char sc_dying; /* disconnecting */ 120 }; 121 122 cdev_decl(ucom); 123 124 static void ucom_cleanup __P((struct ucom_softc *)); 125 static void ucom_hwiflow __P((struct ucom_softc *)); 126 static int ucomparam __P((struct tty *, struct termios *)); 127 static void ucomstart __P((struct tty *)); 128 static void ucom_shutdown __P((struct ucom_softc *)); 129 static void ucom_dtr __P((struct ucom_softc *, int)); 130 static void ucom_rts __P((struct ucom_softc *, int)); 131 static void ucom_break __P((struct ucom_softc *, int)); 132 static usbd_status ucomstartread __P((struct ucom_softc *)); 133 static void ucomreadcb __P((usbd_xfer_handle, usbd_private_handle, 134 usbd_status status)); 135 static void ucomwritecb __P((usbd_xfer_handle, usbd_private_handle, 136 usbd_status status)); 137 static void tiocm_to_ucom __P((struct ucom_softc *, int, int)); 138 static int ucom_to_tiocm __P((struct ucom_softc *)); 139 140 USB_DECLARE_DRIVER(ucom); 141 142 USB_MATCH(ucom) 143 { 144 return (1); 145 } 146 147 USB_ATTACH(ucom) 148 { 149 struct ucom_softc *sc = (struct ucom_softc *)self; 150 struct ucom_attach_args *uca = aux; 151 struct tty *tp; 152 153 if (uca->portno != UCOM_UNK_PORTNO) 154 printf(": portno %d", uca->portno); 155 printf("\n"); 156 157 sc->sc_udev = uca->device; 158 sc->sc_iface = uca->iface; 159 sc->sc_bulkout_no = uca->bulkout; 160 sc->sc_bulkin_no = uca->bulkin; 161 sc->sc_methods = uca->methods; 162 sc->sc_parent = uca->arg; 163 sc->sc_portno = uca->portno; 164 165 tp = ttymalloc(); 166 tp->t_oproc = ucomstart; 167 tp->t_param = ucomparam; 168 sc->sc_tty = tp; 169 170 DPRINTF(("ucom_attach: tty_attach %p\n", tp)); 171 tty_attach(tp); 172 173 USB_ATTACH_SUCCESS_RETURN; 174 } 175 176 USB_DETACH(ucom) 177 { 178 struct ucom_softc *sc = (struct ucom_softc *)self; 179 int maj, mn; 180 181 DPRINTF(("ucom_detach: sc=%p flags=%d tp=%p\n", 182 sc, flags, sc->sc_tty)); 183 184 sc->sc_dying = 1; 185 186 #ifdef DIAGNOSTIC 187 if (sc->sc_tty == NULL) { 188 DPRINTF(("ucom_detach: no tty\n")); 189 return (0); 190 } 191 #endif 192 193 /* XXX Use reference count? */ 194 195 /* locate the major number */ 196 for (maj = 0; maj < nchrdev; maj++) 197 if (cdevsw[maj].d_open == ucomopen) 198 break; 199 200 /* Nuke the vnodes for any open instances. */ 201 mn = self->dv_unit; 202 vdevgone(maj, mn, mn, VCHR); 203 vdevgone(maj, mn, mn | UCOMDIALOUT_MASK, VCHR); 204 vdevgone(maj, mn, mn | UCOMCALLUNIT_MASK, VCHR); 205 206 /* Detach and free the tty. */ 207 tty_detach(sc->sc_tty); 208 ttyfree(sc->sc_tty); 209 sc->sc_tty = 0; 210 211 return (0); 212 } 213 214 #if defined(__NetBSD__) || defined(__OpenBSD__) 215 int 216 ucom_activate(self, act) 217 device_ptr_t self; 218 enum devact act; 219 { 220 struct ucom_softc *sc = (struct ucom_softc *)self; 221 222 switch (act) { 223 case DVACT_ACTIVATE: 224 return (EOPNOTSUPP); 225 break; 226 227 case DVACT_DEACTIVATE: 228 sc->sc_dying = 1; 229 break; 230 } 231 return (0); 232 } 233 #endif 234 235 void 236 ucom_shutdown(sc) 237 struct ucom_softc *sc; 238 { 239 struct tty *tp = sc->sc_tty; 240 241 DPRINTF(("ucom_shutdown\n")); 242 /* 243 * Hang up if necessary. Wait a bit, so the other side has time to 244 * notice even if we immediately open the port again. 245 */ 246 if (ISSET(tp->t_cflag, HUPCL)) { 247 ucom_dtr(sc, 0); 248 (void)tsleep(sc, TTIPRI, ttclos, hz); 249 } 250 } 251 252 int 253 ucomopen(dev, flag, mode, p) 254 dev_t dev; 255 int flag, mode; 256 struct proc *p; 257 { 258 int unit = UCOMUNIT(dev); 259 usbd_status err; 260 struct ucom_softc *sc; 261 struct tty *tp; 262 int s; 263 int error; 264 265 if (unit >= ucom_cd.cd_ndevs) 266 return (ENXIO); 267 sc = ucom_cd.cd_devs[unit]; 268 if (sc == NULL) 269 return (ENXIO); 270 271 if (sc->sc_dying) 272 return (EIO); 273 274 if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) 275 return (ENXIO); 276 277 tp = sc->sc_tty; 278 279 DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp)); 280 281 if (ISSET(tp->t_state, TS_ISOPEN) && 282 ISSET(tp->t_state, TS_XCLUDE) && 283 p->p_ucred->cr_uid != 0) 284 return (EBUSY); 285 286 s = spltty(); 287 288 /* 289 * Do the following iff this is a first open. 290 */ 291 while (sc->sc_opening) 292 tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0); 293 sc->sc_opening = 1; 294 295 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 296 struct termios t; 297 298 tp->t_dev = dev; 299 300 ucom_status_change(sc); 301 302 /* 303 * Initialize the termios status to the defaults. Add in the 304 * sticky bits from TIOCSFLAGS. 305 */ 306 t.c_ispeed = 0; 307 t.c_ospeed = TTYDEF_SPEED; 308 t.c_cflag = TTYDEF_CFLAG; 309 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 310 SET(t.c_cflag, CLOCAL); 311 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 312 SET(t.c_cflag, CRTSCTS); 313 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 314 SET(t.c_cflag, MDMBUF); 315 /* Make sure ucomparam() will do something. */ 316 tp->t_ospeed = 0; 317 (void) ucomparam(tp, &t); 318 tp->t_iflag = TTYDEF_IFLAG; 319 tp->t_oflag = TTYDEF_OFLAG; 320 tp->t_lflag = TTYDEF_LFLAG; 321 ttychars(tp); 322 ttsetwater(tp); 323 324 /* 325 * Turn on DTR. We must always do this, even if carrier is not 326 * present, because otherwise we'd have to use TIOCSDTR 327 * immediately after setting CLOCAL, which applications do not 328 * expect. We always assert DTR while the device is open 329 * unless explicitly requested to deassert it. 330 */ 331 ucom_dtr(sc, 1); 332 333 // XXX CLR(sc->sc_rx_flags, RX_ANY_BLOCK); 334 ucom_hwiflow(sc); 335 336 DPRINTF(("ucomopen: open pipes in=%d out=%d\n", 337 sc->sc_bulkin_no, sc->sc_bulkout_no)); 338 339 /* Open the bulk pipes */ 340 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0, 341 &sc->sc_bulkin_pipe); 342 if (err) { 343 DPRINTF(("%s: open bulk out error (addr %d), err=%s\n", 344 USBDEVNAME(sc->sc_dev), sc->sc_bulkin_no, 345 usbd_errstr(err))); 346 return (EIO); 347 } 348 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, 349 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); 350 if (err) { 351 DPRINTF(("%s: open bulk in error (addr %d), err=%s\n", 352 USBDEVNAME(sc->sc_dev), sc->sc_bulkout_no, 353 usbd_errstr(err))); 354 usbd_close_pipe(sc->sc_bulkin_pipe); 355 return (EIO); 356 } 357 358 /* Allocate a request and an input buffer and start reading. */ 359 sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev); 360 if (sc->sc_ixfer == NULL) { 361 usbd_close_pipe(sc->sc_bulkin_pipe); 362 usbd_close_pipe(sc->sc_bulkout_pipe); 363 return (ENOMEM); 364 } 365 sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer, UCOMIBUFSIZE); 366 if (sc->sc_ibuf == NULL) { 367 usbd_free_xfer(sc->sc_ixfer); 368 usbd_close_pipe(sc->sc_bulkin_pipe); 369 usbd_close_pipe(sc->sc_bulkout_pipe); 370 return (ENOMEM); 371 } 372 373 sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev); 374 if (sc->sc_oxfer == NULL) { 375 usbd_free_xfer(sc->sc_ixfer); 376 usbd_close_pipe(sc->sc_bulkin_pipe); 377 usbd_close_pipe(sc->sc_bulkout_pipe); 378 return (ENOMEM); 379 } 380 sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer, UCOMOBUFSIZE); 381 if (sc->sc_obuf == NULL) { 382 usbd_free_xfer(sc->sc_oxfer); 383 usbd_free_xfer(sc->sc_ixfer); 384 usbd_close_pipe(sc->sc_bulkin_pipe); 385 usbd_close_pipe(sc->sc_bulkout_pipe); 386 return (ENOMEM); 387 } 388 389 if (sc->sc_methods->ucom_open != NULL) 390 sc->sc_methods->ucom_open(sc->sc_parent, sc->sc_portno); 391 392 ucomstartread(sc); 393 } 394 sc->sc_opening = 0; 395 wakeup(&sc->sc_opening); 396 splx(s); 397 398 error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); 399 if (error) 400 goto bad; 401 402 error = (*linesw[tp->t_line].l_open)(dev, tp); 403 if (error) 404 goto bad; 405 406 return (0); 407 408 bad: 409 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 410 /* 411 * We failed to open the device, and nobody else had it opened. 412 * Clean up the state as appropriate. 413 */ 414 ucom_cleanup(sc); 415 } 416 417 return (error); 418 } 419 420 int 421 ucomclose(dev, flag, mode, p) 422 dev_t dev; 423 int flag, mode; 424 struct proc *p; 425 { 426 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 427 struct tty *tp = sc->sc_tty; 428 429 DPRINTF(("ucomclose: unit=%d\n", UCOMUNIT(dev))); 430 if (!ISSET(tp->t_state, TS_ISOPEN)) 431 return (0); 432 433 (*linesw[tp->t_line].l_close)(tp, flag); 434 ttyclose(tp); 435 436 if (sc->sc_dying) 437 return (0); 438 439 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 440 /* 441 * Although we got a last close, the device may still be in 442 * use; e.g. if this was the dialout node, and there are still 443 * processes waiting for carrier on the non-dialout node. 444 */ 445 ucom_cleanup(sc); 446 } 447 448 if (sc->sc_methods->ucom_close != NULL) 449 sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno); 450 451 return (0); 452 } 453 454 int 455 ucomread(dev, uio, flag) 456 dev_t dev; 457 struct uio *uio; 458 int flag; 459 { 460 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 461 struct tty *tp = sc->sc_tty; 462 463 if (sc->sc_dying) 464 return (EIO); 465 466 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 467 } 468 469 int 470 ucomwrite(dev, uio, flag) 471 dev_t dev; 472 struct uio *uio; 473 int flag; 474 { 475 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 476 struct tty *tp = sc->sc_tty; 477 478 if (sc->sc_dying) 479 return (EIO); 480 481 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 482 } 483 484 struct tty * 485 ucomtty(dev) 486 dev_t dev; 487 { 488 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 489 struct tty *tp = sc->sc_tty; 490 491 return (tp); 492 } 493 494 int 495 ucomioctl(dev, cmd, data, flag, p) 496 dev_t dev; 497 u_long cmd; 498 caddr_t data; 499 int flag; 500 struct proc *p; 501 { 502 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 503 struct tty *tp = sc->sc_tty; 504 int error; 505 int s; 506 507 if (sc->sc_dying) 508 return (EIO); 509 510 DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd)); 511 512 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 513 if (error >= 0) 514 return (error); 515 516 error = ttioctl(tp, cmd, data, flag, p); 517 if (error >= 0) 518 return (error); 519 520 if (sc->sc_methods->ucom_ioctl != NULL) { 521 error = sc->sc_methods->ucom_ioctl(sc->sc_parent, 522 sc->sc_portno, cmd, data, flag, p); 523 if (error >= 0) 524 return (error); 525 } 526 527 error = 0; 528 529 DPRINTF(("ucomioctl: our cmd=0x%08lx\n", cmd)); 530 s = spltty(); 531 532 switch (cmd) { 533 case TIOCSBRK: 534 ucom_break(sc, 1); 535 break; 536 537 case TIOCCBRK: 538 ucom_break(sc, 0); 539 break; 540 541 case TIOCSDTR: 542 ucom_dtr(sc, 1); 543 break; 544 545 case TIOCCDTR: 546 ucom_dtr(sc, 0); 547 break; 548 549 case TIOCGFLAGS: 550 *(int *)data = sc->sc_swflags; 551 break; 552 553 case TIOCSFLAGS: 554 error = suser(p->p_ucred, &p->p_acflag); 555 if (error) 556 break; 557 sc->sc_swflags = *(int *)data; 558 break; 559 560 case TIOCMSET: 561 case TIOCMBIS: 562 case TIOCMBIC: 563 tiocm_to_ucom(sc, cmd, *(int *)data); 564 break; 565 566 case TIOCMGET: 567 *(int *)data = ucom_to_tiocm(sc); 568 break; 569 570 default: 571 error = ENOTTY; 572 break; 573 } 574 575 splx(s); 576 577 return (error); 578 } 579 580 void 581 tiocm_to_ucom(sc, how, ttybits) 582 struct ucom_softc *sc; 583 int how, ttybits; 584 { 585 u_char combits; 586 587 combits = 0; 588 if (ISSET(ttybits, TIOCM_DTR)) 589 SET(combits, UMCR_DTR); 590 if (ISSET(ttybits, TIOCM_RTS)) 591 SET(combits, UMCR_RTS); 592 593 switch (how) { 594 case TIOCMBIC: 595 CLR(sc->sc_mcr, combits); 596 break; 597 598 case TIOCMBIS: 599 SET(sc->sc_mcr, combits); 600 break; 601 602 case TIOCMSET: 603 CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS); 604 SET(sc->sc_mcr, combits); 605 break; 606 } 607 608 ucom_dtr(sc, (sc->sc_mcr & UMCR_DTR) != 0); 609 ucom_rts(sc, (sc->sc_mcr & UMCR_RTS) != 0); 610 } 611 612 int 613 ucom_to_tiocm(sc) 614 struct ucom_softc *sc; 615 { 616 u_char combits; 617 int ttybits = 0; 618 619 combits = sc->sc_mcr; 620 if (ISSET(combits, UMCR_DTR)) 621 SET(ttybits, TIOCM_DTR); 622 if (ISSET(combits, UMCR_RTS)) 623 SET(ttybits, TIOCM_RTS); 624 625 combits = sc->sc_msr; 626 if (ISSET(combits, UMSR_DCD)) 627 SET(ttybits, TIOCM_CD); 628 if (ISSET(combits, UMSR_CTS)) 629 SET(ttybits, TIOCM_CTS); 630 if (ISSET(combits, UMSR_DSR)) 631 SET(ttybits, TIOCM_DSR); 632 if (ISSET(combits, UMSR_RI | UMSR_TERI)) 633 SET(ttybits, TIOCM_RI); 634 635 #if 0 636 XXX; 637 if (sc->sc_ier != 0) 638 SET(ttybits, TIOCM_LE); 639 #endif 640 641 return (ttybits); 642 } 643 644 void 645 ucom_break(sc, onoff) 646 struct ucom_softc *sc; 647 int onoff; 648 { 649 DPRINTF(("ucom_break: onoff=%d\n", onoff)); 650 651 if (sc->sc_methods->ucom_set != NULL) 652 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 653 UCOM_SET_BREAK, onoff); 654 } 655 656 void 657 ucom_dtr(sc, onoff) 658 struct ucom_softc *sc; 659 int onoff; 660 { 661 DPRINTF(("ucom_dtr: onoff=%d\n", onoff)); 662 663 if (sc->sc_methods->ucom_set != NULL) 664 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 665 UCOM_SET_DTR, onoff); 666 } 667 668 void 669 ucom_rts(sc, onoff) 670 struct ucom_softc *sc; 671 int onoff; 672 { 673 DPRINTF(("ucom_rts: onoff=%d\n", onoff)); 674 675 if (sc->sc_methods->ucom_set != NULL) 676 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 677 UCOM_SET_RTS, onoff); 678 } 679 680 void 681 ucom_status_change(sc) 682 struct ucom_softc *sc; 683 { 684 if (sc->sc_methods->ucom_get_status != NULL) { 685 sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno, 686 &sc->sc_lsr, &sc->sc_msr); 687 } else { 688 sc->sc_lsr = 0; 689 sc->sc_msr = 0; 690 } 691 } 692 693 int 694 ucomparam(tp, t) 695 struct tty *tp; 696 struct termios *t; 697 { 698 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)]; 699 int error; 700 701 if (sc->sc_dying) 702 return (EIO); 703 704 /* Check requested parameters. */ 705 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 706 return (EINVAL); 707 708 /* 709 * For the console, always force CLOCAL and !HUPCL, so that the port 710 * is always active. 711 */ 712 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) { 713 SET(t->c_cflag, CLOCAL); 714 CLR(t->c_cflag, HUPCL); 715 } 716 717 /* 718 * If there were no changes, don't do anything. This avoids dropping 719 * input and improves performance when all we did was frob things like 720 * VMIN and VTIME. 721 */ 722 if (tp->t_ospeed == t->c_ospeed && 723 tp->t_cflag == t->c_cflag) 724 return (0); 725 726 //XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); 727 728 /* And copy to tty. */ 729 tp->t_ispeed = 0; 730 tp->t_ospeed = t->c_ospeed; 731 tp->t_cflag = t->c_cflag; 732 733 if (sc->sc_methods->ucom_param != NULL) { 734 error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno, 735 t); 736 if (error) 737 return (error); 738 } 739 740 // XXX worry about CHWFLOW 741 742 /* 743 * Update the tty layer's idea of the carrier bit, in case we changed 744 * CLOCAL or MDMBUF. We don't hang up here; we only do that by 745 * explicit request. 746 */ 747 DPRINTF(("ucomparam: l_modem\n")); 748 (void) (*linesw[tp->t_line].l_modem)(tp, 1 /* XXX carrier */ ); 749 750 #if 0 751 XXX what if the hardware is not open 752 if (!ISSET(t->c_cflag, CHWFLOW)) { 753 if (sc->sc_tx_stopped) { 754 sc->sc_tx_stopped = 0; 755 ucomstart(tp); 756 } 757 } 758 #endif 759 760 return (0); 761 } 762 763 /* 764 * (un)block input via hw flowcontrol 765 */ 766 void 767 ucom_hwiflow(sc) 768 struct ucom_softc *sc; 769 { 770 #if 0 771 XXX 772 bus_space_tag_t iot = sc->sc_iot; 773 bus_space_handle_t ioh = sc->sc_ioh; 774 775 if (sc->sc_mcr_rts == 0) 776 return; 777 778 if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) { 779 CLR(sc->sc_mcr, sc->sc_mcr_rts); 780 CLR(sc->sc_mcr_active, sc->sc_mcr_rts); 781 } else { 782 SET(sc->sc_mcr, sc->sc_mcr_rts); 783 SET(sc->sc_mcr_active, sc->sc_mcr_rts); 784 } 785 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active); 786 #endif 787 } 788 789 void 790 ucomstart(tp) 791 struct tty *tp; 792 { 793 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)]; 794 usbd_status err; 795 int s; 796 u_char *data; 797 int cnt; 798 799 if (sc->sc_dying) 800 return; 801 802 s = spltty(); 803 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) { 804 DPRINTFN(4,("ucomstart: stopped\n")); 805 goto out; 806 } 807 if (sc->sc_tx_stopped) 808 goto out; 809 810 if (tp->t_outq.c_cc <= tp->t_lowat) { 811 if (ISSET(tp->t_state, TS_ASLEEP)) { 812 CLR(tp->t_state, TS_ASLEEP); 813 wakeup(&tp->t_outq); 814 } 815 selwakeup(&tp->t_wsel); 816 if (tp->t_outq.c_cc == 0) 817 goto out; 818 } 819 820 /* Grab the first contiguous region of buffer space. */ 821 data = tp->t_outq.c_cf; 822 cnt = ndqb(&tp->t_outq, 0); 823 824 if (cnt == 0) { 825 DPRINTF(("ucomstart: cnt==0\n")); 826 goto out; 827 } 828 829 SET(tp->t_state, TS_BUSY); 830 831 if (cnt > UCOMOBUFSIZE) { 832 DPRINTF(("ucomstart: big buffer %d chars\n", cnt)); 833 cnt = UCOMOBUFSIZE; 834 } 835 memcpy(sc->sc_obuf, data, cnt); 836 837 DPRINTFN(4,("ucomstart: %d chars\n", cnt)); 838 usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe, 839 (usbd_private_handle)sc, sc->sc_obuf, cnt, 840 USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb); 841 /* What can we do on error? */ 842 err = usbd_transfer(sc->sc_oxfer); 843 #ifdef DIAGNOSTIC 844 if (err != USBD_IN_PROGRESS) 845 printf("ucomstart: err=%s\n", usbd_errstr(err)); 846 #endif 847 848 out: 849 splx(s); 850 } 851 852 void 853 ucomstop(tp, flag) 854 struct tty *tp; 855 int flag; 856 { 857 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)]; 858 int s; 859 860 DPRINTF(("ucomstop: %d\n", flag)); 861 s = spltty(); 862 if (ISSET(tp->t_state, TS_BUSY)) { 863 DPRINTF(("ucomstop: XXX\n")); 864 sc->sc_tx_stopped = 1; 865 if (!ISSET(tp->t_state, TS_TTSTOP)) 866 SET(tp->t_state, TS_FLUSH); 867 } 868 splx(s); 869 } 870 871 void 872 ucomwritecb(xfer, p, status) 873 usbd_xfer_handle xfer; 874 usbd_private_handle p; 875 usbd_status status; 876 { 877 struct ucom_softc *sc = (struct ucom_softc *)p; 878 struct tty *tp = sc->sc_tty; 879 u_int32_t cc; 880 int s; 881 882 DPRINTFN(5,("ucomwritecb: status=%d\n", status)); 883 884 if (status == USBD_CANCELLED) 885 return; 886 887 if (status) { 888 DPRINTF(("ucomwritecb: status=%d\n", status)); 889 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); 890 /* XXX we should restart after some delay. */ 891 return; 892 } 893 894 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); 895 DPRINTFN(5,("ucomwritecb: cc=%d\n", cc)); 896 897 s = spltty(); 898 CLR(tp->t_state, TS_BUSY); 899 if (ISSET(tp->t_state, TS_FLUSH)) 900 CLR(tp->t_state, TS_FLUSH); 901 else 902 ndflush(&tp->t_outq, cc); 903 (*linesw[tp->t_line].l_start)(tp); 904 splx(s); 905 } 906 907 usbd_status 908 ucomstartread(sc) 909 struct ucom_softc *sc; 910 { 911 usbd_status err; 912 913 DPRINTFN(5,("ucomstartread: start\n")); 914 usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe, 915 (usbd_private_handle)sc, 916 sc->sc_ibuf, UCOMIBUFSIZE, 917 USBD_SHORT_XFER_OK | USBD_NO_COPY, 918 USBD_NO_TIMEOUT, ucomreadcb); 919 err = usbd_transfer(sc->sc_ixfer); 920 if (err != USBD_IN_PROGRESS) { 921 DPRINTF(("ucomstartread: err=%s\n", usbd_errstr(err))); 922 return (err); 923 } 924 return (USBD_NORMAL_COMPLETION); 925 } 926 927 void 928 ucomreadcb(xfer, p, status) 929 usbd_xfer_handle xfer; 930 usbd_private_handle p; 931 usbd_status status; 932 { 933 struct ucom_softc *sc = (struct ucom_softc *)p; 934 struct tty *tp = sc->sc_tty; 935 int (*rint) __P((int c, struct tty *tp)) = linesw[tp->t_line].l_rint; 936 usbd_status err; 937 u_int32_t cc; 938 u_char *cp; 939 int s; 940 941 if (status == USBD_CANCELLED) 942 return; 943 944 if (status) { 945 DPRINTF(("ucomreadcb: status=%d\n", status)); 946 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); 947 /* XXX we should restart after some delay. */ 948 return; 949 } 950 951 usbd_get_xfer_status(xfer, NULL, (void **)&cp, &cc, NULL); 952 DPRINTFN(5,("ucomreadcb: got %d chars, tp=%p\n", cc, tp)); 953 s = spltty(); 954 /* Give characters to tty layer. */ 955 while (cc-- > 0) { 956 DPRINTFN(7,("ucomreadcb: char=0x%02x\n", *cp)); 957 if ((*rint)(*cp++, tp) == -1) { 958 /* XXX what should we do? */ 959 break; 960 } 961 } 962 splx(s); 963 964 err = ucomstartread(sc); 965 if (err) { 966 printf("%s: read start failed\n", USBDEVNAME(sc->sc_dev)); 967 /* XXX what should we dow now? */ 968 } 969 } 970 971 void 972 ucom_cleanup(sc) 973 struct ucom_softc *sc; 974 { 975 DPRINTF(("ucom_cleanup: closing pipes\n")); 976 977 ucom_shutdown(sc); 978 usbd_abort_pipe(sc->sc_bulkin_pipe); 979 usbd_close_pipe(sc->sc_bulkin_pipe); 980 usbd_abort_pipe(sc->sc_bulkout_pipe); 981 usbd_close_pipe(sc->sc_bulkout_pipe); 982 usbd_free_xfer(sc->sc_ixfer); 983 usbd_free_xfer(sc->sc_oxfer); 984 } 985 986 #endif /* NUCOM > 0 */ 987 988 int 989 ucomprint(aux, pnp) 990 void *aux; 991 const char *pnp; 992 { 993 994 if (pnp) 995 printf("ucom at %s\n", pnp); 996 return (UNCONF); 997 } 998 999 int 1000 ucomsubmatch(parent, cf, aux) 1001 struct device *parent; 1002 struct cfdata *cf; 1003 void *aux; 1004 { 1005 struct ucom_attach_args *uca = aux; 1006 1007 if (uca->portno != UCOM_UNK_PORTNO && 1008 cf->ucomcf_portno != UCOM_UNK_PORTNO && 1009 cf->ucomcf_portno != uca->portno) 1010 return (0); 1011 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 1012 } 1013