ucom.c revision 1.108.2.9 1 /* $NetBSD: ucom.c,v 1.108.2.9 2015/10/06 21:32:15 skrll Exp $ */
2
3 /*
4 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart (at) augustsson.net) at
9 * Carlstedt Research & Technology.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * This code is very heavily based on the 16550 driver, com.c.
34 */
35
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.108.2.9 2015/10/06 21:32:15 skrll Exp $");
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/ioctl.h>
43 #include <sys/conf.h>
44 #include <sys/tty.h>
45 #include <sys/file.h>
46 #include <sys/select.h>
47 #include <sys/proc.h>
48 #include <sys/vnode.h>
49 #include <sys/device.h>
50 #include <sys/poll.h>
51 #include <sys/queue.h>
52 #include <sys/kauth.h>
53 #include <sys/sysctl.h>
54 #include <sys/timepps.h>
55 #include <sys/rndsource.h>
56
57 #include <dev/usb/usb.h>
58
59 #include <dev/usb/usbdi.h>
60 #include <dev/usb/usbdi_util.h>
61 #include <dev/usb/usbdevs.h>
62 #include <dev/usb/usb_quirks.h>
63 #include <dev/usb/usbhist.h>
64
65 #include <dev/usb/ucomvar.h>
66
67 #include "ucom.h"
68
69 #include "locators.h"
70
71 #if NUCOM > 0
72
73 #ifdef USB_DEBUG
74 #ifndef UCOM_DEBUG
75 #define ucomdebug 0
76 #else
77 int ucomdebug = 0;
78
79 SYSCTL_SETUP(sysctl_hw_ucom_setup, "sysctl hw.ucom setup")
80 {
81 int err;
82 const struct sysctlnode *rnode;
83 const struct sysctlnode *cnode;
84
85 err = sysctl_createv(clog, 0, NULL, &rnode,
86 CTLFLAG_PERMANENT, CTLTYPE_NODE, "ucom",
87 SYSCTL_DESCR("ucom global controls"),
88 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
89
90 if (err)
91 goto fail;
92
93 /* control debugging printfs */
94 err = sysctl_createv(clog, 0, &rnode, &cnode,
95 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
96 "debug", SYSCTL_DESCR("Enable debugging output"),
97 NULL, 0, &ucomdebug, sizeof(ucomdebug), CTL_CREATE, CTL_EOL);
98 if (err)
99 goto fail;
100
101 return;
102 fail:
103 aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err);
104 }
105
106 #endif /* UCOM_DEBUG */
107 #endif /* USB_DEBUG */
108
109 #define DPRINTF(FMT,A,B,C,D) USBHIST_LOGN(ucomdebug,1,FMT,A,B,C,D)
110 #define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(ucomdebug,N,FMT,A,B,C,D)
111 #define UCOMHIST_FUNC() USBHIST_FUNC()
112 #define UCOMHIST_CALLED(name) USBHIST_CALLED(ucomdebug)
113
114 #define UCOMCALLUNIT_MASK TTCALLUNIT_MASK
115 #define UCOMUNIT_MASK TTUNIT_MASK
116 #define UCOMDIALOUT_MASK TTDIALOUT_MASK
117
118 #define UCOMCALLUNIT(x) TTCALLUNIT(x)
119 #define UCOMUNIT(x) TTUNIT(x)
120 #define UCOMDIALOUT(x) TTDIALOUT(x)
121
122 /*
123 * XXX: We can submit multiple input/output buffers to the usb stack
124 * to improve throughput, but the usb stack is too lame to deal with this
125 * in a number of places.
126 */
127 #define UCOM_IN_BUFFS 1
128 #define UCOM_OUT_BUFFS 1
129
130 struct ucom_buffer {
131 SIMPLEQ_ENTRY(ucom_buffer) ub_link;
132 struct usbd_xfer *ub_xfer;
133 u_char *ub_data;
134 u_int ub_len;
135 u_int ub_index;
136 };
137
138 struct ucom_softc {
139 device_t sc_dev; /* base device */
140
141 struct usbd_device * sc_udev; /* USB device */
142
143 struct usbd_interface * sc_iface; /* data interface */
144
145 int sc_bulkin_no; /* bulk in endpoint address */
146 struct usbd_pipe * sc_bulkin_pipe; /* bulk in pipe */
147 u_int sc_ibufsize; /* read buffer size */
148 u_int sc_ibufsizepad; /* read buffer size padded */
149 struct ucom_buffer sc_ibuff[UCOM_IN_BUFFS];
150 SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_empty;
151 SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_full;
152
153 int sc_bulkout_no; /* bulk out endpoint address */
154 struct usbd_pipe * sc_bulkout_pipe;/* bulk out pipe */
155 u_int sc_obufsize; /* write buffer size */
156 u_int sc_opkthdrlen; /* header length of */
157 struct ucom_buffer sc_obuff[UCOM_OUT_BUFFS];
158 SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_free;
159 SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_full;
160
161 void *sc_si;
162
163 const struct ucom_methods *sc_methods;
164 void *sc_parent;
165 int sc_portno;
166
167 struct tty *sc_tty; /* our tty */
168 u_char sc_lsr;
169 u_char sc_msr;
170 u_char sc_mcr;
171 volatile u_char sc_rx_stopped;
172 u_char sc_rx_unblock;
173 u_char sc_tx_stopped;
174 int sc_swflags;
175
176 u_char sc_opening; /* lock during open */
177 int sc_refcnt;
178 u_char sc_dying; /* disconnecting */
179
180 struct pps_state sc_pps_state; /* pps state */
181
182 krndsource_t sc_rndsource; /* random source */
183
184 kmutex_t *sc_lock;
185 kcondvar_t sc_opencv;
186 kcondvar_t sc_detachcv;
187 };
188
189 dev_type_open(ucomopen);
190 dev_type_close(ucomclose);
191 dev_type_read(ucomread);
192 dev_type_write(ucomwrite);
193 dev_type_ioctl(ucomioctl);
194 dev_type_stop(ucomstop);
195 dev_type_tty(ucomtty);
196 dev_type_poll(ucompoll);
197
198 const struct cdevsw ucom_cdevsw = {
199 .d_open = ucomopen,
200 .d_close = ucomclose,
201 .d_read = ucomread,
202 .d_write = ucomwrite,
203 .d_ioctl = ucomioctl,
204 .d_stop = ucomstop,
205 .d_tty = ucomtty,
206 .d_poll = ucompoll,
207 .d_mmap = nommap,
208 .d_kqfilter = ttykqfilter,
209 .d_discard = nodiscard,
210 .d_flag = D_TTY | D_MPSAFE
211 };
212
213 static void ucom_cleanup(struct ucom_softc *);
214 static int ucomparam(struct tty *, struct termios *);
215 static int ucomhwiflow(struct tty *, int);
216 static void ucomstart(struct tty *);
217 static void ucom_shutdown(struct ucom_softc *);
218 static int ucom_do_ioctl(struct ucom_softc *, u_long, void *,
219 int, struct lwp *);
220 static void ucom_dtr(struct ucom_softc *, int);
221 static void ucom_rts(struct ucom_softc *, int);
222 static void ucom_break(struct ucom_softc *, int);
223 static void tiocm_to_ucom(struct ucom_softc *, u_long, int);
224 static int ucom_to_tiocm(struct ucom_softc *);
225
226 static void ucomreadcb(struct usbd_xfer *, void *, usbd_status);
227 static void ucom_submit_write(struct ucom_softc *, struct ucom_buffer *);
228 static void ucom_write_status(struct ucom_softc *, struct ucom_buffer *,
229 usbd_status);
230
231 static void ucomwritecb(struct usbd_xfer *, void *, usbd_status);
232 static void ucom_read_complete(struct ucom_softc *);
233 static usbd_status ucomsubmitread(struct ucom_softc *, struct ucom_buffer *);
234 static void ucom_softintr(void *);
235
236 int ucom_match(device_t, cfdata_t, void *);
237 void ucom_attach(device_t, device_t, void *);
238 int ucom_detach(device_t, int);
239 int ucom_activate(device_t, enum devact);
240 extern struct cfdriver ucom_cd;
241 CFATTACH_DECL_NEW(ucom, sizeof(struct ucom_softc), ucom_match, ucom_attach,
242 ucom_detach, ucom_activate);
243
244 int
245 ucom_match(device_t parent, cfdata_t match, void *aux)
246 {
247 return 1;
248 }
249
250 void
251 ucom_attach(device_t parent, device_t self, void *aux)
252 {
253 struct ucom_softc *sc = device_private(self);
254 struct ucom_attach_args *uca = aux;
255 struct tty *tp;
256
257 UCOMHIST_FUNC(); UCOMHIST_CALLED();
258
259 if (uca->info != NULL)
260 aprint_normal(": %s", uca->info);
261 aprint_normal("\n");
262
263 sc->sc_dev = self;
264 sc->sc_udev = uca->device;
265 sc->sc_iface = uca->iface;
266 sc->sc_bulkout_no = uca->bulkout;
267 sc->sc_bulkin_no = uca->bulkin;
268 sc->sc_ibufsize = uca->ibufsize;
269 sc->sc_ibufsizepad = uca->ibufsizepad;
270 sc->sc_obufsize = uca->obufsize;
271 sc->sc_opkthdrlen = uca->opkthdrlen;
272 sc->sc_methods = uca->methods;
273 sc->sc_parent = uca->arg;
274 sc->sc_portno = uca->portno;
275
276 sc->sc_lsr = 0;
277 sc->sc_msr = 0;
278 sc->sc_mcr = 0;
279 sc->sc_tx_stopped = 0;
280 sc->sc_swflags = 0;
281 sc->sc_opening = 0;
282 sc->sc_refcnt = 0;
283 sc->sc_dying = 0;
284
285 sc->sc_si = softint_establish(SOFTINT_USB, ucom_softintr, sc);
286 sc->sc_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SOFTUSB);
287 cv_init(&sc->sc_opencv, "ucomopen");
288 cv_init(&sc->sc_detachcv, "ucomdtch");
289
290 SIMPLEQ_INIT(&sc->sc_ibuff_empty);
291 SIMPLEQ_INIT(&sc->sc_ibuff_full);
292 SIMPLEQ_INIT(&sc->sc_obuff_free);
293 SIMPLEQ_INIT(&sc->sc_obuff_full);
294
295 memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff));
296 memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff));
297
298 DPRINTF("open pipes in=%d out=%d", sc->sc_bulkin_no, sc->sc_bulkout_no,
299 0, 0);
300
301 struct ucom_buffer *ub;
302 usbd_status err;
303 int error;
304
305 /* Open the bulk pipes */
306 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no,
307 USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
308 if (err) {
309 DPRINTF("open bulk in error (addr %d), err=%d",
310 sc->sc_bulkin_no, err, 0, 0);
311 error = EIO;
312 goto fail_0;
313 }
314 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
315 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
316 if (err) {
317 DPRINTF("open bulk out error (addr %d), err=%d",
318 sc->sc_bulkout_no, err, 0, 0);
319 error = EIO;
320 goto fail_1;
321 }
322
323 /* Allocate input buffers */
324 for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
325 ub++) {
326 error = usbd_create_xfer(sc->sc_bulkin_pipe, sc->sc_ibufsizepad,
327 USBD_SHORT_XFER_OK, 0, &ub->ub_xfer);
328 if (error)
329 goto fail_2;
330 ub->ub_data = usbd_get_buffer(ub->ub_xfer);
331 }
332
333 for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
334 ub++) {
335 error = usbd_create_xfer(sc->sc_bulkout_pipe, sc->sc_obufsize,
336 0, 0, &ub->ub_xfer);
337 if (error)
338 goto fail_2;
339 ub->ub_data = usbd_get_buffer(ub->ub_xfer);
340 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
341 }
342
343 tp = tty_alloc();
344 tp->t_oproc = ucomstart;
345 tp->t_param = ucomparam;
346 tp->t_hwiflow = ucomhwiflow;
347 sc->sc_tty = tp;
348
349 DPRINTF("tty_attach %p", tp, 0, 0, 0);
350 tty_attach(tp);
351
352 rnd_attach_source(&sc->sc_rndsource, device_xname(sc->sc_dev),
353 RND_TYPE_TTY, RND_FLAG_DEFAULT);
354
355 if (!pmf_device_register(self, NULL, NULL))
356 aprint_error_dev(self, "couldn't establish power handler\n");
357 return;
358
359 fail_2:
360 for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
361 ub++) {
362 if (ub->ub_xfer)
363 usbd_destroy_xfer(ub->ub_xfer);
364 }
365 for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
366 ub++) {
367 if (ub->ub_xfer)
368 usbd_destroy_xfer(ub->ub_xfer);
369 }
370
371 fail_1:
372 usbd_close_pipe(sc->sc_bulkin_pipe);
373
374 fail_0:
375 aprint_error_dev(self, "attach failed, error=%d\n", error);
376
377 return;
378 }
379
380 int
381 ucom_detach(device_t self, int flags)
382 {
383 struct ucom_softc *sc = device_private(self);
384 struct tty *tp = sc->sc_tty;
385 int maj, mn;
386 int i;
387
388 UCOMHIST_FUNC(); UCOMHIST_CALLED();
389
390 DPRINTF("sc=%p flags=%d tp=%p", sc, flags, tp, 0);
391 DPRINTF("... pipe=%d,%d",sc->sc_bulkin_no, sc->sc_bulkout_no, 0, 0);
392
393 mutex_enter(sc->sc_lock);
394 sc->sc_dying = 1;
395 mutex_exit(sc->sc_lock);
396
397 pmf_device_deregister(self);
398
399 if (sc->sc_bulkin_pipe != NULL)
400 usbd_abort_pipe(sc->sc_bulkin_pipe);
401 if (sc->sc_bulkout_pipe != NULL)
402 usbd_abort_pipe(sc->sc_bulkout_pipe);
403
404 mutex_enter(sc->sc_lock);
405 while (sc->sc_refcnt > 0) {
406 /* Wake up anyone waiting */
407 if (tp != NULL) {
408 mutex_spin_enter(&tty_lock);
409 CLR(tp->t_state, TS_CARR_ON);
410 CLR(tp->t_cflag, CLOCAL | MDMBUF);
411 ttyflush(tp, FREAD|FWRITE);
412 mutex_spin_exit(&tty_lock);
413 }
414 /* Wait for processes to go away. */
415 usb_detach_wait(sc->sc_dev, &sc->sc_detachcv, sc->sc_lock);
416 }
417
418 softint_disestablish(sc->sc_si);
419 mutex_exit(sc->sc_lock);
420
421 /* locate the major number */
422 maj = cdevsw_lookup_major(&ucom_cdevsw);
423
424 /* Nuke the vnodes for any open instances. */
425 mn = device_unit(self);
426 DPRINTF("maj=%d mn=%d\n", maj, mn, 0, 0);
427 vdevgone(maj, mn, mn, VCHR);
428 vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR);
429 vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR);
430
431 /* Detach and free the tty. */
432 if (tp != NULL) {
433 tty_detach(tp);
434 tty_free(tp);
435 sc->sc_tty = NULL;
436 }
437
438 for (i = 0; i < UCOM_IN_BUFFS; i++) {
439 if (sc->sc_ibuff[i].ub_xfer != NULL)
440 usbd_destroy_xfer(sc->sc_ibuff[i].ub_xfer);
441 }
442
443 for (i = 0; i < UCOM_OUT_BUFFS; i++) {
444 if (sc->sc_obuff[i].ub_xfer != NULL)
445 usbd_destroy_xfer(sc->sc_obuff[i].ub_xfer);
446 }
447
448 /* Detach the random source */
449 rnd_detach_source(&sc->sc_rndsource);
450
451 mutex_destroy(sc->sc_lock);
452 cv_destroy(&sc->sc_opencv);
453 cv_destroy(&sc->sc_detachcv);
454
455 return 0;
456 }
457
458 int
459 ucom_activate(device_t self, enum devact act)
460 {
461 struct ucom_softc *sc = device_private(self);
462
463 UCOMHIST_FUNC(); UCOMHIST_CALLED();
464
465 DPRINTFN(5, "%d", act, 0, 0, 0);
466
467 switch (act) {
468 case DVACT_DEACTIVATE:
469 mutex_enter(sc->sc_lock);
470 sc->sc_dying = 1;
471 mutex_exit(sc->sc_lock);
472 return 0;
473 default:
474 return EOPNOTSUPP;
475 }
476 }
477
478 void
479 ucom_shutdown(struct ucom_softc *sc)
480 {
481 struct tty *tp = sc->sc_tty;
482
483 UCOMHIST_FUNC(); UCOMHIST_CALLED();
484
485 KASSERT(mutex_owned(sc->sc_lock));
486 /*
487 * Hang up if necessary. Wait a bit, so the other side has time to
488 * notice even if we immediately open the port again.
489 */
490 if (ISSET(tp->t_cflag, HUPCL)) {
491 ucom_dtr(sc, 0);
492 /* XXX will only timeout */
493 (void) kpause(ttclos, false, hz, sc->sc_lock);
494 }
495 }
496
497 int
498 ucomopen(dev_t dev, int flag, int mode, struct lwp *l)
499 {
500 int unit = UCOMUNIT(dev);
501 struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
502 struct ucom_buffer *ub;
503 struct tty *tp;
504 int error;
505
506 UCOMHIST_FUNC(); UCOMHIST_CALLED();
507
508 if (sc == NULL)
509 return ENXIO;
510
511 mutex_enter(sc->sc_lock);
512 if (sc->sc_dying) {
513 mutex_exit(sc->sc_lock);
514 return EIO;
515 }
516
517 if (!device_is_active(sc->sc_dev)) {
518 mutex_exit(sc->sc_lock);
519 return ENXIO;
520 }
521
522 tp = sc->sc_tty;
523
524 DPRINTF("unit=%d, tp=%p\n", unit, tp, 0, 0);
525
526 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) {
527 mutex_exit(sc->sc_lock);
528 return EBUSY;
529 }
530
531 /*
532 * Do the following iff this is a first open.
533 */
534 while (sc->sc_opening) {
535 error = cv_wait_sig(&sc->sc_opencv, sc->sc_lock);
536
537 if (error) {
538 mutex_exit(sc->sc_lock);
539 return error;
540 }
541 }
542
543 sc->sc_opening = 1;
544
545 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
546 struct termios t;
547
548 tp->t_dev = dev;
549
550 if (sc->sc_methods->ucom_open != NULL) {
551 error = sc->sc_methods->ucom_open(sc->sc_parent,
552 sc->sc_portno);
553 if (error) {
554 ucom_cleanup(sc);
555 sc->sc_opening = 0;
556 cv_signal(&sc->sc_opencv);
557 mutex_exit(sc->sc_lock);
558 return error;
559 }
560 }
561
562 ucom_status_change(sc);
563
564 /* Clear PPS capture state on first open. */
565 mutex_spin_enter(&timecounter_lock);
566 memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state));
567 sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
568 pps_init(&sc->sc_pps_state);
569 mutex_spin_exit(&timecounter_lock);
570
571 /*
572 * Initialize the termios status to the defaults. Add in the
573 * sticky bits from TIOCSFLAGS.
574 */
575 t.c_ispeed = 0;
576 t.c_ospeed = TTYDEF_SPEED;
577 t.c_cflag = TTYDEF_CFLAG;
578 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
579 SET(t.c_cflag, CLOCAL);
580 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
581 SET(t.c_cflag, CRTSCTS);
582 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
583 SET(t.c_cflag, MDMBUF);
584 /* Make sure ucomparam() will do something. */
585 tp->t_ospeed = 0;
586 (void) ucomparam(tp, &t);
587 tp->t_iflag = TTYDEF_IFLAG;
588 tp->t_oflag = TTYDEF_OFLAG;
589 tp->t_lflag = TTYDEF_LFLAG;
590 ttychars(tp);
591 ttsetwater(tp);
592
593 /*
594 * Turn on DTR. We must always do this, even if carrier is not
595 * present, because otherwise we'd have to use TIOCSDTR
596 * immediately after setting CLOCAL, which applications do not
597 * expect. We always assert DTR while the device is open
598 * unless explicitly requested to deassert it. Ditto RTS.
599 */
600 ucom_dtr(sc, 1);
601 ucom_rts(sc, 1);
602
603 sc->sc_rx_unblock = 0;
604 sc->sc_rx_stopped = 0;
605 sc->sc_tx_stopped = 0;
606
607 for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
608 ub++) {
609 if (ucomsubmitread(sc, ub) != USBD_NORMAL_COMPLETION) {
610 error = EIO;
611 goto fail_2;
612 }
613 }
614 }
615 sc->sc_opening = 0;
616 cv_signal(&sc->sc_opencv);
617 mutex_exit(sc->sc_lock);
618
619 error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
620 if (error)
621 goto bad;
622
623 error = (*tp->t_linesw->l_open)(dev, tp);
624 if (error)
625 goto bad;
626
627 return 0;
628
629 fail_2:
630 usbd_abort_pipe(sc->sc_bulkin_pipe);
631 usbd_abort_pipe(sc->sc_bulkout_pipe);
632
633 mutex_enter(sc->sc_lock);
634 sc->sc_opening = 0;
635 cv_signal(&sc->sc_opencv);
636 mutex_exit(sc->sc_lock);
637
638 return error;
639
640 bad:
641 mutex_spin_enter(&tty_lock);
642 CLR(tp->t_state, TS_BUSY);
643 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
644 /*
645 * We failed to open the device, and nobody else had it opened.
646 * Clean up the state as appropriate.
647 */
648 ucom_cleanup(sc);
649 }
650 mutex_spin_exit(&tty_lock);
651
652 return error;
653 }
654
655 int
656 ucomclose(dev_t dev, int flag, int mode, struct lwp *l)
657 {
658 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
659 struct tty *tp;
660
661 UCOMHIST_FUNC(); UCOMHIST_CALLED();
662
663 DPRINTF("unit=%d", UCOMUNIT(dev), 0, 0, 0);
664
665 if (sc == NULL)
666 return 0;
667
668 mutex_enter(sc->sc_lock);
669 tp = sc->sc_tty;
670
671 if (!ISSET(tp->t_state, TS_ISOPEN)) {
672 goto out;
673 }
674
675 sc->sc_refcnt++;
676
677 (*tp->t_linesw->l_close)(tp, flag);
678 ttyclose(tp);
679
680 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
681 /*
682 * Although we got a last close, the device may still be in
683 * use; e.g. if this was the dialout node, and there are still
684 * processes waiting for carrier on the non-dialout node.
685 */
686 ucom_cleanup(sc);
687 }
688
689 if (sc->sc_methods->ucom_close != NULL)
690 sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno);
691
692 if (--sc->sc_refcnt < 0)
693 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
694
695 out:
696 mutex_exit(sc->sc_lock);
697
698 return 0;
699 }
700
701 int
702 ucomread(dev_t dev, struct uio *uio, int flag)
703 {
704 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
705 struct tty *tp;
706 int error;
707
708 UCOMHIST_FUNC(); UCOMHIST_CALLED();
709
710 if (sc == NULL)
711 return EIO;
712
713 mutex_enter(sc->sc_lock);
714 if (sc->sc_dying) {
715 mutex_exit(sc->sc_lock);
716 return EIO;
717 }
718
719 tp = sc->sc_tty;
720
721 sc->sc_refcnt++;
722 mutex_exit(sc->sc_lock);
723 error = ((*tp->t_linesw->l_read)(tp, uio, flag));
724 mutex_enter(sc->sc_lock);
725
726 if (--sc->sc_refcnt < 0)
727 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
728 mutex_exit(sc->sc_lock);
729
730 return error;
731 }
732
733 int
734 ucomwrite(dev_t dev, struct uio *uio, int flag)
735 {
736 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
737 struct tty *tp;
738 int error;
739
740 if (sc == NULL)
741 return EIO;
742
743 mutex_enter(sc->sc_lock);
744 if (sc->sc_dying) {
745 mutex_exit(sc->sc_lock);
746 return EIO;
747 }
748
749 tp = sc->sc_tty;
750
751 sc->sc_refcnt++;
752 mutex_exit(sc->sc_lock);
753 error = ((*tp->t_linesw->l_write)(tp, uio, flag));
754 mutex_enter(sc->sc_lock);
755 if (--sc->sc_refcnt < 0)
756 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
757 mutex_exit(sc->sc_lock);
758
759 return error;
760 }
761
762 int
763 ucompoll(dev_t dev, int events, struct lwp *l)
764 {
765 struct ucom_softc *sc;
766 struct tty *tp;
767 int revents;
768
769 sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
770 if (sc == NULL)
771 return POLLHUP;
772
773 mutex_enter(sc->sc_lock);
774 if (sc->sc_dying) {
775 mutex_exit(sc->sc_lock);
776 return POLLHUP;
777 }
778 tp = sc->sc_tty;
779
780 sc->sc_refcnt++;
781 mutex_exit(sc->sc_lock);
782 revents = ((*tp->t_linesw->l_poll)(tp, events, l));
783 mutex_enter(sc->sc_lock);
784 if (--sc->sc_refcnt < 0)
785 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
786 mutex_exit(sc->sc_lock);
787
788 return revents;
789 }
790
791 struct tty *
792 ucomtty(dev_t dev)
793 {
794 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
795
796 return sc != NULL ? sc->sc_tty : NULL;
797 }
798
799 int
800 ucomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
801 {
802 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
803 int error;
804
805 if (sc == NULL)
806 return EIO;
807
808 mutex_enter(sc->sc_lock);
809 if (sc->sc_dying) {
810 mutex_exit(sc->sc_lock);
811 return EIO;
812 }
813
814 sc->sc_refcnt++;
815 error = ucom_do_ioctl(sc, cmd, data, flag, l);
816 if (--sc->sc_refcnt < 0)
817 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
818 mutex_exit(sc->sc_lock);
819 return error;
820 }
821
822 static int
823 ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, void *data,
824 int flag, struct lwp *l)
825 {
826 struct tty *tp = sc->sc_tty;
827 int error;
828
829 UCOMHIST_FUNC(); UCOMHIST_CALLED();
830
831 DPRINTF("cmd=0x%08lx", cmd, 0, 0, 0);
832
833 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
834 if (error != EPASSTHROUGH)
835 return error;
836
837 error = ttioctl(tp, cmd, data, flag, l);
838 if (error != EPASSTHROUGH)
839 return error;
840
841 if (sc->sc_methods->ucom_ioctl != NULL) {
842 error = sc->sc_methods->ucom_ioctl(sc->sc_parent,
843 sc->sc_portno, cmd, data, flag, l->l_proc);
844 if (error != EPASSTHROUGH)
845 return error;
846 }
847
848 error = 0;
849
850 DPRINTF("our cmd=0x%08lx", cmd, 0, 0, 0);
851 //mutex_enter(&tty_lock);
852
853 switch (cmd) {
854 case TIOCSBRK:
855 ucom_break(sc, 1);
856 break;
857
858 case TIOCCBRK:
859 ucom_break(sc, 0);
860 break;
861
862 case TIOCSDTR:
863 ucom_dtr(sc, 1);
864 break;
865
866 case TIOCCDTR:
867 ucom_dtr(sc, 0);
868 break;
869
870 case TIOCGFLAGS:
871 *(int *)data = sc->sc_swflags;
872 break;
873
874 case TIOCSFLAGS:
875 error = kauth_authorize_device_tty(l->l_cred,
876 KAUTH_DEVICE_TTY_PRIVSET, tp);
877 if (error)
878 break;
879 sc->sc_swflags = *(int *)data;
880 break;
881
882 case TIOCMSET:
883 case TIOCMBIS:
884 case TIOCMBIC:
885 tiocm_to_ucom(sc, cmd, *(int *)data);
886 break;
887
888 case TIOCMGET:
889 *(int *)data = ucom_to_tiocm(sc);
890 break;
891
892 case PPS_IOC_CREATE:
893 case PPS_IOC_DESTROY:
894 case PPS_IOC_GETPARAMS:
895 case PPS_IOC_SETPARAMS:
896 case PPS_IOC_GETCAP:
897 case PPS_IOC_FETCH:
898 #ifdef PPS_SYNC
899 case PPS_IOC_KCBIND:
900 #endif
901 mutex_spin_enter(&timecounter_lock);
902 error = pps_ioctl(cmd, data, &sc->sc_pps_state);
903 mutex_spin_exit(&timecounter_lock);
904 break;
905
906 default:
907 error = EPASSTHROUGH;
908 break;
909 }
910
911 //mutex_exit(&tty_lock);
912
913 return error;
914 }
915
916 static void
917 tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits)
918 {
919 u_char combits;
920
921 combits = 0;
922 if (ISSET(ttybits, TIOCM_DTR))
923 SET(combits, UMCR_DTR);
924 if (ISSET(ttybits, TIOCM_RTS))
925 SET(combits, UMCR_RTS);
926
927 switch (how) {
928 case TIOCMBIC:
929 CLR(sc->sc_mcr, combits);
930 break;
931
932 case TIOCMBIS:
933 SET(sc->sc_mcr, combits);
934 break;
935
936 case TIOCMSET:
937 CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS);
938 SET(sc->sc_mcr, combits);
939 break;
940 }
941
942 if (how == TIOCMSET || ISSET(combits, UMCR_DTR))
943 ucom_dtr(sc, (sc->sc_mcr & UMCR_DTR) != 0);
944 if (how == TIOCMSET || ISSET(combits, UMCR_RTS))
945 ucom_rts(sc, (sc->sc_mcr & UMCR_RTS) != 0);
946 }
947
948 static int
949 ucom_to_tiocm(struct ucom_softc *sc)
950 {
951 u_char combits;
952 int ttybits = 0;
953
954 combits = sc->sc_mcr;
955 if (ISSET(combits, UMCR_DTR))
956 SET(ttybits, TIOCM_DTR);
957 if (ISSET(combits, UMCR_RTS))
958 SET(ttybits, TIOCM_RTS);
959
960 combits = sc->sc_msr;
961 if (ISSET(combits, UMSR_DCD))
962 SET(ttybits, TIOCM_CD);
963 if (ISSET(combits, UMSR_CTS))
964 SET(ttybits, TIOCM_CTS);
965 if (ISSET(combits, UMSR_DSR))
966 SET(ttybits, TIOCM_DSR);
967 if (ISSET(combits, UMSR_RI | UMSR_TERI))
968 SET(ttybits, TIOCM_RI);
969
970 #if 0
971 XXX;
972 if (sc->sc_ier != 0)
973 SET(ttybits, TIOCM_LE);
974 #endif
975
976 return ttybits;
977 }
978
979 static void
980 ucom_break(struct ucom_softc *sc, int onoff)
981 {
982 UCOMHIST_FUNC(); UCOMHIST_CALLED();
983
984 DPRINTF("onoff=%d", onoff, 0, 0, 0);
985
986 if (sc->sc_methods->ucom_set != NULL)
987 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
988 UCOM_SET_BREAK, onoff);
989 }
990
991 static void
992 ucom_dtr(struct ucom_softc *sc, int onoff)
993 {
994 UCOMHIST_FUNC(); UCOMHIST_CALLED();
995
996 DPRINTF("onoff=%d", onoff, 0, 0, 0);
997
998 if (sc->sc_methods->ucom_set != NULL)
999 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1000 UCOM_SET_DTR, onoff);
1001 }
1002
1003 static void
1004 ucom_rts(struct ucom_softc *sc, int onoff)
1005 {
1006 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1007
1008 DPRINTF("onoff=%d", onoff, 0, 0, 0);
1009
1010 if (sc->sc_methods->ucom_set != NULL)
1011 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1012 UCOM_SET_RTS, onoff);
1013 }
1014
1015 void
1016 ucom_status_change(struct ucom_softc *sc)
1017 {
1018 struct tty *tp = sc->sc_tty;
1019 u_char old_msr;
1020
1021 if (sc->sc_methods->ucom_get_status != NULL) {
1022 old_msr = sc->sc_msr;
1023 sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno,
1024 &sc->sc_lsr, &sc->sc_msr);
1025 if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) {
1026 mutex_spin_enter(&timecounter_lock);
1027 pps_capture(&sc->sc_pps_state);
1028 pps_event(&sc->sc_pps_state,
1029 (sc->sc_msr & UMSR_DCD) ?
1030 PPS_CAPTUREASSERT :
1031 PPS_CAPTURECLEAR);
1032 mutex_spin_exit(&timecounter_lock);
1033
1034 (*tp->t_linesw->l_modem)(tp,
1035 ISSET(sc->sc_msr, UMSR_DCD));
1036 }
1037 } else {
1038 sc->sc_lsr = 0;
1039 /* Assume DCD is present, if we have no chance to check it. */
1040 sc->sc_msr = UMSR_DCD;
1041 }
1042 }
1043
1044 static int
1045 ucomparam(struct tty *tp, struct termios *t)
1046 {
1047 struct ucom_softc *sc = device_lookup_private(&ucom_cd,
1048 UCOMUNIT(tp->t_dev));
1049 int error;
1050
1051 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1052
1053 if (sc == NULL || sc->sc_dying)
1054 return EIO;
1055
1056 /* Check requested parameters. */
1057 if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
1058 return EINVAL;
1059
1060 /*
1061 * For the console, always force CLOCAL and !HUPCL, so that the port
1062 * is always active.
1063 */
1064 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) {
1065 SET(t->c_cflag, CLOCAL);
1066 CLR(t->c_cflag, HUPCL);
1067 }
1068
1069 /*
1070 * If there were no changes, don't do anything. This avoids dropping
1071 * input and improves performance when all we did was frob things like
1072 * VMIN and VTIME.
1073 */
1074 if (tp->t_ospeed == t->c_ospeed &&
1075 tp->t_cflag == t->c_cflag)
1076 return 0;
1077
1078 /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */
1079
1080 /* And copy to tty. */
1081 tp->t_ispeed = 0;
1082 tp->t_ospeed = t->c_ospeed;
1083 tp->t_cflag = t->c_cflag;
1084
1085 if (sc->sc_methods->ucom_param != NULL) {
1086 error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno,
1087 t);
1088 if (error)
1089 return error;
1090 }
1091
1092 /* XXX worry about CHWFLOW */
1093
1094 /*
1095 * Update the tty layer's idea of the carrier bit, in case we changed
1096 * CLOCAL or MDMBUF. We don't hang up here; we only do that by
1097 * explicit request.
1098 */
1099 DPRINTF("l_modem", 0, 0, 0, 0);
1100 (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD));
1101
1102 #if 0
1103 XXX what if the hardware is not open
1104 if (!ISSET(t->c_cflag, CHWFLOW)) {
1105 if (sc->sc_tx_stopped) {
1106 sc->sc_tx_stopped = 0;
1107 ucomstart(tp);
1108 }
1109 }
1110 #endif
1111
1112 return 0;
1113 }
1114
1115 static int
1116 ucomhwiflow(struct tty *tp, int block)
1117 {
1118 struct ucom_softc *sc = device_lookup_private(&ucom_cd,
1119 UCOMUNIT(tp->t_dev));
1120 int old;
1121
1122 if (sc == NULL)
1123 return 0;
1124
1125 mutex_enter(sc->sc_lock);
1126 old = sc->sc_rx_stopped;
1127 sc->sc_rx_stopped = (u_char)block;
1128
1129 if (old && !block) {
1130 sc->sc_rx_unblock = 1;
1131 softint_schedule(sc->sc_si);
1132 }
1133 mutex_exit(sc->sc_lock);
1134
1135 return 1;
1136 }
1137
1138 static void
1139 ucomstart(struct tty *tp)
1140 {
1141 struct ucom_softc *sc = device_lookup_private(&ucom_cd,
1142 UCOMUNIT(tp->t_dev));
1143 struct ucom_buffer *ub;
1144 u_char *data;
1145 int cnt;
1146
1147 if (sc == NULL)
1148 return;
1149
1150 KASSERT(sc->sc_lock);
1151 KASSERT(mutex_owned(&tty_lock));
1152 if (sc->sc_dying) {
1153 return;
1154 }
1155
1156 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
1157 goto out;
1158 if (sc->sc_tx_stopped)
1159 goto out;
1160
1161 if (!ttypull(tp))
1162 goto out;
1163
1164 /* Grab the first contiguous region of buffer space. */
1165 data = tp->t_outq.c_cf;
1166 cnt = ndqb(&tp->t_outq, 0);
1167
1168 if (cnt == 0)
1169 goto out;
1170
1171 ub = SIMPLEQ_FIRST(&sc->sc_obuff_free);
1172 if (ub == NULL) {
1173 SET(tp->t_state, TS_BUSY);
1174 goto out;
1175 }
1176
1177 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_free, ub_link);
1178
1179 if (SIMPLEQ_FIRST(&sc->sc_obuff_free) == NULL)
1180 SET(tp->t_state, TS_BUSY);
1181
1182 if (cnt > sc->sc_obufsize)
1183 cnt = sc->sc_obufsize;
1184
1185 if (sc->sc_methods->ucom_write != NULL)
1186 sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno,
1187 ub->ub_data, data, &cnt);
1188 else
1189 memcpy(ub->ub_data, data, cnt);
1190
1191 ub->ub_len = cnt;
1192 ub->ub_index = 0;
1193
1194 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_full, ub, ub_link);
1195
1196 softint_schedule(sc->sc_si);
1197
1198 out:
1199 return;
1200 }
1201
1202 void
1203 ucomstop(struct tty *tp, int flag)
1204 {
1205 #if 0
1206 struct ucom_softc *sc =
1207 device_lookup_private(&ucom_cd, UCOMUNIT(tp->t_dev));
1208
1209 mutex_enter(sc->sc_lock);
1210 mutex_spin_enter(&tty_lock);
1211 if (ISSET(tp->t_state, TS_BUSY)) {
1212 /* obuff_full -> obuff_free? */
1213 /* sc->sc_tx_stopped = 1; */
1214 if (!ISSET(tp->t_state, TS_TTSTOP))
1215 SET(tp->t_state, TS_FLUSH);
1216 }
1217 mutex_spin_exit(&tty_lock);
1218 mutex_exit(sc->sc_lock);
1219 #endif
1220 }
1221
1222 static void
1223 ucom_write_status(struct ucom_softc *sc, struct ucom_buffer *ub,
1224 usbd_status err)
1225 {
1226 struct tty *tp = sc->sc_tty;
1227 uint32_t cc = ub->ub_len;
1228
1229 KASSERT(mutex_owned(sc->sc_lock));
1230
1231 switch (err) {
1232 case USBD_IN_PROGRESS:
1233 ub->ub_index = ub->ub_len;
1234 break;
1235 case USBD_STALLED:
1236 ub->ub_index = 0;
1237 softint_schedule(sc->sc_si);
1238 break;
1239 case USBD_NORMAL_COMPLETION:
1240 usbd_get_xfer_status(ub->ub_xfer, NULL, NULL, &cc, NULL);
1241 rnd_add_uint32(&sc->sc_rndsource, cc);
1242 /*FALLTHROUGH*/
1243 default:
1244 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_full, ub_link);
1245 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
1246 cc -= sc->sc_opkthdrlen;
1247
1248 mutex_spin_enter(&tty_lock);
1249 CLR(tp->t_state, TS_BUSY);
1250 if (ISSET(tp->t_state, TS_FLUSH))
1251 CLR(tp->t_state, TS_FLUSH);
1252 else
1253 ndflush(&tp->t_outq, cc);
1254 mutex_spin_exit(&tty_lock);
1255
1256 if (err != USBD_CANCELLED && err != USBD_IOERROR &&
1257 !sc->sc_dying) {
1258 if ((ub = SIMPLEQ_FIRST(&sc->sc_obuff_full)) != NULL)
1259 ucom_submit_write(sc, ub);
1260
1261 mutex_spin_enter(&tty_lock);
1262 (*tp->t_linesw->l_start)(tp);
1263 mutex_spin_exit(&tty_lock);
1264 }
1265 break;
1266 }
1267 }
1268
1269 static void
1270 ucom_submit_write(struct ucom_softc *sc, struct ucom_buffer *ub)
1271 {
1272
1273 KASSERT(mutex_owned(sc->sc_lock));
1274
1275 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, ub->ub_len,
1276 0, USBD_NO_TIMEOUT, ucomwritecb);
1277
1278 ucom_write_status(sc, ub, usbd_transfer(ub->ub_xfer));
1279 }
1280
1281 static void
1282 ucomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status)
1283 {
1284 struct ucom_softc *sc = (struct ucom_softc *)p;
1285
1286 mutex_enter(sc->sc_lock);
1287 ucom_write_status(sc, SIMPLEQ_FIRST(&sc->sc_obuff_full), status);
1288 mutex_exit(sc->sc_lock);
1289
1290 }
1291
1292 static void
1293 ucom_softintr(void *arg)
1294 {
1295 struct ucom_softc *sc = arg;
1296 struct tty *tp = sc->sc_tty;
1297 struct ucom_buffer *ub;
1298
1299 mutex_enter(sc->sc_lock);
1300 mutex_enter(&tty_lock);
1301 if (!ISSET(tp->t_state, TS_ISOPEN)) {
1302 mutex_exit(&tty_lock);
1303 mutex_exit(sc->sc_lock);
1304 return;
1305 }
1306 mutex_exit(&tty_lock);
1307
1308 ub = SIMPLEQ_FIRST(&sc->sc_obuff_full);
1309
1310 if (ub != NULL && ub->ub_index == 0)
1311 ucom_submit_write(sc, ub);
1312
1313 if (sc->sc_rx_unblock)
1314 ucom_read_complete(sc);
1315
1316 mutex_exit(sc->sc_lock);
1317 }
1318
1319 static void
1320 ucom_read_complete(struct ucom_softc *sc)
1321 {
1322 int (*rint)(int, struct tty *);
1323 struct ucom_buffer *ub;
1324 struct tty *tp;
1325
1326 KASSERT(mutex_owned(sc->sc_lock));
1327
1328 tp = sc->sc_tty;
1329 rint = tp->t_linesw->l_rint;
1330 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full);
1331
1332 while (ub != NULL && !sc->sc_rx_stopped) {
1333
1334 /* XXX ttyinput takes tty_lock */
1335 while (ub->ub_index < ub->ub_len && !sc->sc_rx_stopped) {
1336 /* Give characters to tty layer. */
1337 if ((*rint)(ub->ub_data[ub->ub_index], tp) == -1) {
1338 /* Overflow: drop remainder */
1339 ub->ub_index = ub->ub_len;
1340 } else
1341 ub->ub_index++;
1342 }
1343
1344 if (ub->ub_index == ub->ub_len) {
1345 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_full, ub_link);
1346
1347 ucomsubmitread(sc, ub);
1348
1349 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full);
1350 }
1351 }
1352
1353 sc->sc_rx_unblock = (ub != NULL);
1354 }
1355
1356 static usbd_status
1357 ucomsubmitread(struct ucom_softc *sc, struct ucom_buffer *ub)
1358 {
1359 usbd_status err;
1360
1361 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, sc->sc_ibufsize,
1362 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ucomreadcb);
1363
1364 if ((err = usbd_transfer(ub->ub_xfer)) != USBD_IN_PROGRESS) {
1365 /* XXX: Recover from this, please! */
1366 printf("ucomsubmitread: err=%s\n", usbd_errstr(err));
1367 return err;
1368 }
1369
1370 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_empty, ub, ub_link);
1371
1372 return USBD_NORMAL_COMPLETION;
1373 }
1374
1375 static void
1376 ucomreadcb(struct usbd_xfer *xfer, void *p, usbd_status status)
1377 {
1378 struct ucom_softc *sc = (struct ucom_softc *)p;
1379 struct tty *tp = sc->sc_tty;
1380 struct ucom_buffer *ub;
1381 uint32_t cc;
1382 u_char *cp;
1383
1384 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1385
1386 mutex_enter(sc->sc_lock);
1387 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_empty);
1388 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_empty, ub_link);
1389
1390 if (status == USBD_CANCELLED || status == USBD_IOERROR ||
1391 sc->sc_dying) {
1392 DPRINTF("dying", 0, 0, 0, 0);
1393 ub->ub_index = ub->ub_len = 0;
1394 /* Send something to wake upper layer */
1395 if (status != USBD_CANCELLED) {
1396 (tp->t_linesw->l_rint)('\n', tp);
1397 mutex_spin_enter(&tty_lock); /* XXX */
1398 ttwakeup(tp);
1399 mutex_spin_exit(&tty_lock); /* XXX */
1400 }
1401 mutex_exit(sc->sc_lock);
1402 return;
1403 }
1404
1405 if (status == USBD_STALLED) {
1406 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
1407 ucomsubmitread(sc, ub);
1408 mutex_exit(sc->sc_lock);
1409 return;
1410 }
1411
1412 if (status != USBD_NORMAL_COMPLETION) {
1413 printf("ucomreadcb: wonky status=%s\n", usbd_errstr(status));
1414 mutex_exit(sc->sc_lock);
1415 return;
1416 }
1417
1418 usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL);
1419
1420 #ifdef UCOM_DEBUG
1421 /* This is triggered by uslsa(4) occasionally. */
1422 if ((ucomdebug > 0) && (cc == 0)) {
1423 device_printf(sc->sc_dev, "ucomreadcb: zero length xfer!\n");
1424 }
1425 #endif
1426
1427 KDASSERT(cp == ub->ub_data);
1428
1429 rnd_add_uint32(&sc->sc_rndsource, cc);
1430
1431 if (sc->sc_opening) {
1432 ucomsubmitread(sc, ub);
1433 mutex_exit(sc->sc_lock);
1434 return;
1435 }
1436
1437 if (sc->sc_methods->ucom_read != NULL) {
1438 sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno,
1439 &cp, &cc);
1440 ub->ub_index = (u_int)(cp - ub->ub_data);
1441 } else
1442 ub->ub_index = 0;
1443
1444 ub->ub_len = cc;
1445
1446 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_full, ub, ub_link);
1447
1448 ucom_read_complete(sc);
1449 mutex_exit(sc->sc_lock);
1450 }
1451
1452 static void
1453 ucom_cleanup(struct ucom_softc *sc)
1454 {
1455
1456 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1457
1458 DPRINTF("aborting pipes", 0, 0, 0, 0);
1459
1460 KASSERT(mutex_owned(sc->sc_lock));
1461
1462 ucom_shutdown(sc);
1463 if (sc->sc_bulkin_pipe != NULL) {
1464 struct usbd_pipe *bulkin_pipe = sc->sc_bulkin_pipe;
1465 sc->sc_bulkin_pipe = NULL;
1466 mutex_exit(sc->sc_lock);
1467 usbd_abort_pipe(bulkin_pipe);
1468 mutex_enter(sc->sc_lock);
1469 }
1470 if (sc->sc_bulkout_pipe != NULL) {
1471 struct usbd_pipe *bulkout_pipe = sc->sc_bulkout_pipe;
1472 sc->sc_bulkout_pipe = NULL;
1473 mutex_exit(sc->sc_lock);
1474 usbd_abort_pipe(bulkout_pipe);
1475 mutex_enter(sc->sc_lock);
1476 }
1477 }
1478
1479 #endif /* NUCOM > 0 */
1480
1481 int
1482 ucomprint(void *aux, const char *pnp)
1483 {
1484 struct ucom_attach_args *uca = aux;
1485
1486 if (pnp)
1487 aprint_normal("ucom at %s", pnp);
1488 if (uca->portno != UCOM_UNK_PORTNO)
1489 aprint_normal(" portno %d", uca->portno);
1490 return UNCONF;
1491 }
1492
1493 int
1494 ucomsubmatch(device_t parent, cfdata_t cf,
1495 const int *ldesc, void *aux)
1496 {
1497 struct ucom_attach_args *uca = aux;
1498
1499 if (uca->portno != UCOM_UNK_PORTNO &&
1500 cf->cf_loc[UCOMBUSCF_PORTNO] != UCOMBUSCF_PORTNO_DEFAULT &&
1501 cf->cf_loc[UCOMBUSCF_PORTNO] != uca->portno)
1502 return 0;
1503 return config_match(parent, cf, aux);
1504 }
1505