ucom.c revision 1.111 1 /* $NetBSD: ucom.c,v 1.111 2016/04/23 10:15:32 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.111 2016/04/23 10:15:32 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 *ucaa = aux;
255 struct tty *tp;
256
257 UCOMHIST_FUNC(); UCOMHIST_CALLED();
258
259 if (ucaa->ucaa_info != NULL)
260 aprint_normal(": %s", ucaa->ucaa_info);
261 aprint_normal("\n");
262
263 prop_dictionary_set_int32(device_properties(self), "port",
264 ucaa->ucaa_portno);
265
266 sc->sc_dev = self;
267 sc->sc_udev = ucaa->ucaa_device;
268 sc->sc_iface = ucaa->ucaa_iface;
269 sc->sc_bulkout_no = ucaa->ucaa_bulkout;
270 sc->sc_bulkin_no = ucaa->ucaa_bulkin;
271 sc->sc_ibufsize = ucaa->ucaa_ibufsize;
272 sc->sc_ibufsizepad = ucaa->ucaa_ibufsizepad;
273 sc->sc_obufsize = ucaa->ucaa_obufsize;
274 sc->sc_opkthdrlen = ucaa->ucaa_opkthdrlen;
275 sc->sc_methods = ucaa->ucaa_methods;
276 sc->sc_parent = ucaa->ucaa_arg;
277 sc->sc_portno = ucaa->ucaa_portno;
278
279 sc->sc_lsr = 0;
280 sc->sc_msr = 0;
281 sc->sc_mcr = 0;
282 sc->sc_tx_stopped = 0;
283 sc->sc_swflags = 0;
284 sc->sc_opening = 0;
285 sc->sc_refcnt = 0;
286 sc->sc_dying = 0;
287
288 sc->sc_si = softint_establish(SOFTINT_USB, ucom_softintr, sc);
289 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB);
290 cv_init(&sc->sc_opencv, "ucomopen");
291 cv_init(&sc->sc_detachcv, "ucomdtch");
292
293 SIMPLEQ_INIT(&sc->sc_ibuff_empty);
294 SIMPLEQ_INIT(&sc->sc_ibuff_full);
295 SIMPLEQ_INIT(&sc->sc_obuff_free);
296 SIMPLEQ_INIT(&sc->sc_obuff_full);
297
298 memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff));
299 memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff));
300
301 DPRINTF("open pipes in=%d out=%d", sc->sc_bulkin_no, sc->sc_bulkout_no,
302 0, 0);
303
304 struct ucom_buffer *ub;
305 usbd_status err;
306 int error;
307
308 /* Open the bulk pipes */
309 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no,
310 USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
311 if (err) {
312 DPRINTF("open bulk in error (addr %d), err=%d",
313 sc->sc_bulkin_no, err, 0, 0);
314 error = EIO;
315 goto fail_0;
316 }
317 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
318 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
319 if (err) {
320 DPRINTF("open bulk out error (addr %d), err=%d",
321 sc->sc_bulkout_no, err, 0, 0);
322 error = EIO;
323 goto fail_1;
324 }
325
326 /* Allocate input buffers */
327 for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
328 ub++) {
329 error = usbd_create_xfer(sc->sc_bulkin_pipe, sc->sc_ibufsizepad,
330 USBD_SHORT_XFER_OK, 0, &ub->ub_xfer);
331 if (error)
332 goto fail_2;
333 ub->ub_data = usbd_get_buffer(ub->ub_xfer);
334 }
335
336 for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
337 ub++) {
338 error = usbd_create_xfer(sc->sc_bulkout_pipe, sc->sc_obufsize,
339 0, 0, &ub->ub_xfer);
340 if (error)
341 goto fail_2;
342 ub->ub_data = usbd_get_buffer(ub->ub_xfer);
343 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
344 }
345
346 tp = tty_alloc();
347 tp->t_oproc = ucomstart;
348 tp->t_param = ucomparam;
349 tp->t_hwiflow = ucomhwiflow;
350 sc->sc_tty = tp;
351
352 DPRINTF("tty_attach %p", tp, 0, 0, 0);
353 tty_attach(tp);
354
355 rnd_attach_source(&sc->sc_rndsource, device_xname(sc->sc_dev),
356 RND_TYPE_TTY, RND_FLAG_DEFAULT);
357
358 if (!pmf_device_register(self, NULL, NULL))
359 aprint_error_dev(self, "couldn't establish power handler\n");
360 return;
361
362 fail_2:
363 for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
364 ub++) {
365 if (ub->ub_xfer)
366 usbd_destroy_xfer(ub->ub_xfer);
367 }
368 for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
369 ub++) {
370 if (ub->ub_xfer)
371 usbd_destroy_xfer(ub->ub_xfer);
372 }
373
374 fail_1:
375 usbd_close_pipe(sc->sc_bulkin_pipe);
376
377 fail_0:
378 aprint_error_dev(self, "attach failed, error=%d\n", error);
379
380 return;
381 }
382
383 int
384 ucom_detach(device_t self, int flags)
385 {
386 struct ucom_softc *sc = device_private(self);
387 struct tty *tp = sc->sc_tty;
388 int maj, mn;
389 int i;
390
391 UCOMHIST_FUNC(); UCOMHIST_CALLED();
392
393 DPRINTF("sc=%p flags=%d tp=%p", sc, flags, tp, 0);
394 DPRINTF("... pipe=%d,%d",sc->sc_bulkin_no, sc->sc_bulkout_no, 0, 0);
395
396 mutex_enter(&sc->sc_lock);
397 sc->sc_dying = 1;
398 mutex_exit(&sc->sc_lock);
399
400 pmf_device_deregister(self);
401
402 if (sc->sc_bulkin_pipe != NULL)
403 usbd_abort_pipe(sc->sc_bulkin_pipe);
404 if (sc->sc_bulkout_pipe != NULL)
405 usbd_abort_pipe(sc->sc_bulkout_pipe);
406
407 mutex_enter(&sc->sc_lock);
408 while (sc->sc_refcnt > 0) {
409 /* Wake up anyone waiting */
410 if (tp != NULL) {
411 mutex_spin_enter(&tty_lock);
412 CLR(tp->t_state, TS_CARR_ON);
413 CLR(tp->t_cflag, CLOCAL | MDMBUF);
414 ttyflush(tp, FREAD|FWRITE);
415 mutex_spin_exit(&tty_lock);
416 }
417 /* Wait for processes to go away. */
418 usb_detach_wait(sc->sc_dev, &sc->sc_detachcv, &sc->sc_lock);
419 }
420
421 softint_disestablish(sc->sc_si);
422 mutex_exit(&sc->sc_lock);
423
424 /* locate the major number */
425 maj = cdevsw_lookup_major(&ucom_cdevsw);
426
427 /* Nuke the vnodes for any open instances. */
428 mn = device_unit(self);
429 DPRINTF("maj=%d mn=%d\n", maj, mn, 0, 0);
430 vdevgone(maj, mn, mn, VCHR);
431 vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR);
432 vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR);
433
434 /* Detach and free the tty. */
435 if (tp != NULL) {
436 tty_detach(tp);
437 tty_free(tp);
438 sc->sc_tty = NULL;
439 }
440
441 for (i = 0; i < UCOM_IN_BUFFS; i++) {
442 if (sc->sc_ibuff[i].ub_xfer != NULL)
443 usbd_destroy_xfer(sc->sc_ibuff[i].ub_xfer);
444 }
445
446 for (i = 0; i < UCOM_OUT_BUFFS; i++) {
447 if (sc->sc_obuff[i].ub_xfer != NULL)
448 usbd_destroy_xfer(sc->sc_obuff[i].ub_xfer);
449 }
450
451 if (sc->sc_bulkin_pipe != NULL) {
452 usbd_close_pipe(sc->sc_bulkin_pipe);
453 sc->sc_bulkin_pipe = NULL;
454 }
455
456 if (sc->sc_bulkout_pipe != NULL) {
457 usbd_close_pipe(sc->sc_bulkout_pipe);
458 sc->sc_bulkout_pipe = NULL;
459 }
460
461 /* Detach the random source */
462 rnd_detach_source(&sc->sc_rndsource);
463
464 mutex_destroy(&sc->sc_lock);
465 cv_destroy(&sc->sc_opencv);
466 cv_destroy(&sc->sc_detachcv);
467
468 return 0;
469 }
470
471 int
472 ucom_activate(device_t self, enum devact act)
473 {
474 struct ucom_softc *sc = device_private(self);
475
476 UCOMHIST_FUNC(); UCOMHIST_CALLED();
477
478 DPRINTFN(5, "%d", act, 0, 0, 0);
479
480 switch (act) {
481 case DVACT_DEACTIVATE:
482 mutex_enter(&sc->sc_lock);
483 sc->sc_dying = 1;
484 mutex_exit(&sc->sc_lock);
485 return 0;
486 default:
487 return EOPNOTSUPP;
488 }
489 }
490
491 void
492 ucom_shutdown(struct ucom_softc *sc)
493 {
494 struct tty *tp = sc->sc_tty;
495
496 UCOMHIST_FUNC(); UCOMHIST_CALLED();
497
498 KASSERT(mutex_owned(&sc->sc_lock));
499 /*
500 * Hang up if necessary. Wait a bit, so the other side has time to
501 * notice even if we immediately open the port again.
502 */
503 if (ISSET(tp->t_cflag, HUPCL)) {
504 ucom_dtr(sc, 0);
505 /* XXX will only timeout */
506 (void) kpause(ttclos, false, hz, &sc->sc_lock);
507 }
508 }
509
510 int
511 ucomopen(dev_t dev, int flag, int mode, struct lwp *l)
512 {
513 int unit = UCOMUNIT(dev);
514 struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
515 struct ucom_buffer *ub;
516 struct tty *tp;
517 int error;
518
519 UCOMHIST_FUNC(); UCOMHIST_CALLED();
520
521 if (sc == NULL)
522 return ENXIO;
523
524 mutex_enter(&sc->sc_lock);
525 if (sc->sc_dying) {
526 mutex_exit(&sc->sc_lock);
527 return EIO;
528 }
529
530 if (!device_is_active(sc->sc_dev)) {
531 mutex_exit(&sc->sc_lock);
532 return ENXIO;
533 }
534
535 tp = sc->sc_tty;
536
537 DPRINTF("unit=%d, tp=%p\n", unit, tp, 0, 0);
538
539 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) {
540 mutex_exit(&sc->sc_lock);
541 return EBUSY;
542 }
543
544 /*
545 * Do the following iff this is a first open.
546 */
547 while (sc->sc_opening) {
548 error = cv_wait_sig(&sc->sc_opencv, &sc->sc_lock);
549
550 if (error) {
551 mutex_exit(&sc->sc_lock);
552 return error;
553 }
554 }
555
556 sc->sc_opening = 1;
557
558 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
559 struct termios t;
560
561 tp->t_dev = dev;
562
563 if (sc->sc_methods->ucom_open != NULL) {
564 error = sc->sc_methods->ucom_open(sc->sc_parent,
565 sc->sc_portno);
566 if (error) {
567 ucom_cleanup(sc);
568 sc->sc_opening = 0;
569 cv_signal(&sc->sc_opencv);
570 mutex_exit(&sc->sc_lock);
571 return error;
572 }
573 }
574
575 ucom_status_change(sc);
576
577 /* Clear PPS capture state on first open. */
578 mutex_spin_enter(&timecounter_lock);
579 memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state));
580 sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
581 pps_init(&sc->sc_pps_state);
582 mutex_spin_exit(&timecounter_lock);
583
584 /*
585 * Initialize the termios status to the defaults. Add in the
586 * sticky bits from TIOCSFLAGS.
587 */
588 t.c_ispeed = 0;
589 t.c_ospeed = TTYDEF_SPEED;
590 t.c_cflag = TTYDEF_CFLAG;
591 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
592 SET(t.c_cflag, CLOCAL);
593 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
594 SET(t.c_cflag, CRTSCTS);
595 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
596 SET(t.c_cflag, MDMBUF);
597 /* Make sure ucomparam() will do something. */
598 tp->t_ospeed = 0;
599 (void) ucomparam(tp, &t);
600 tp->t_iflag = TTYDEF_IFLAG;
601 tp->t_oflag = TTYDEF_OFLAG;
602 tp->t_lflag = TTYDEF_LFLAG;
603 ttychars(tp);
604 ttsetwater(tp);
605
606 /*
607 * Turn on DTR. We must always do this, even if carrier is not
608 * present, because otherwise we'd have to use TIOCSDTR
609 * immediately after setting CLOCAL, which applications do not
610 * expect. We always assert DTR while the device is open
611 * unless explicitly requested to deassert it. Ditto RTS.
612 */
613 ucom_dtr(sc, 1);
614 ucom_rts(sc, 1);
615
616 sc->sc_rx_unblock = 0;
617 sc->sc_rx_stopped = 0;
618 sc->sc_tx_stopped = 0;
619
620 for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
621 ub++) {
622 if (ucomsubmitread(sc, ub) != USBD_NORMAL_COMPLETION) {
623 error = EIO;
624 goto fail_2;
625 }
626 }
627 }
628 sc->sc_opening = 0;
629 cv_signal(&sc->sc_opencv);
630 mutex_exit(&sc->sc_lock);
631
632 error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
633 if (error)
634 goto bad;
635
636 error = (*tp->t_linesw->l_open)(dev, tp);
637 if (error)
638 goto bad;
639
640 return 0;
641
642 fail_2:
643 usbd_abort_pipe(sc->sc_bulkin_pipe);
644 usbd_abort_pipe(sc->sc_bulkout_pipe);
645
646 mutex_enter(&sc->sc_lock);
647 sc->sc_opening = 0;
648 cv_signal(&sc->sc_opencv);
649 mutex_exit(&sc->sc_lock);
650
651 return error;
652
653 bad:
654 mutex_spin_enter(&tty_lock);
655 CLR(tp->t_state, TS_BUSY);
656 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
657 /*
658 * We failed to open the device, and nobody else had it opened.
659 * Clean up the state as appropriate.
660 */
661 ucom_cleanup(sc);
662 }
663 mutex_spin_exit(&tty_lock);
664
665 return error;
666 }
667
668 int
669 ucomclose(dev_t dev, int flag, int mode, struct lwp *l)
670 {
671 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
672 struct tty *tp;
673
674 UCOMHIST_FUNC(); UCOMHIST_CALLED();
675
676 DPRINTF("unit=%d", UCOMUNIT(dev), 0, 0, 0);
677
678 if (sc == NULL)
679 return 0;
680
681 mutex_enter(&sc->sc_lock);
682 tp = sc->sc_tty;
683
684 if (!ISSET(tp->t_state, TS_ISOPEN)) {
685 goto out;
686 }
687
688 sc->sc_refcnt++;
689
690 (*tp->t_linesw->l_close)(tp, flag);
691 ttyclose(tp);
692
693 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
694 /*
695 * Although we got a last close, the device may still be in
696 * use; e.g. if this was the dialout node, and there are still
697 * processes waiting for carrier on the non-dialout node.
698 */
699 ucom_cleanup(sc);
700 }
701
702 if (sc->sc_methods->ucom_close != NULL)
703 sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno);
704
705 if (--sc->sc_refcnt < 0)
706 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
707
708 out:
709 mutex_exit(&sc->sc_lock);
710
711 return 0;
712 }
713
714 int
715 ucomread(dev_t dev, struct uio *uio, int flag)
716 {
717 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
718 struct tty *tp;
719 int error;
720
721 UCOMHIST_FUNC(); UCOMHIST_CALLED();
722
723 if (sc == NULL)
724 return EIO;
725
726 mutex_enter(&sc->sc_lock);
727 if (sc->sc_dying) {
728 mutex_exit(&sc->sc_lock);
729 return EIO;
730 }
731
732 tp = sc->sc_tty;
733
734 sc->sc_refcnt++;
735 mutex_exit(&sc->sc_lock);
736 error = ((*tp->t_linesw->l_read)(tp, uio, flag));
737 mutex_enter(&sc->sc_lock);
738
739 if (--sc->sc_refcnt < 0)
740 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
741 mutex_exit(&sc->sc_lock);
742
743 return error;
744 }
745
746 int
747 ucomwrite(dev_t dev, struct uio *uio, int flag)
748 {
749 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
750 struct tty *tp;
751 int error;
752
753 if (sc == NULL)
754 return EIO;
755
756 mutex_enter(&sc->sc_lock);
757 if (sc->sc_dying) {
758 mutex_exit(&sc->sc_lock);
759 return EIO;
760 }
761
762 tp = sc->sc_tty;
763
764 sc->sc_refcnt++;
765 mutex_exit(&sc->sc_lock);
766 error = ((*tp->t_linesw->l_write)(tp, uio, flag));
767 mutex_enter(&sc->sc_lock);
768 if (--sc->sc_refcnt < 0)
769 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
770 mutex_exit(&sc->sc_lock);
771
772 return error;
773 }
774
775 int
776 ucompoll(dev_t dev, int events, struct lwp *l)
777 {
778 struct ucom_softc *sc;
779 struct tty *tp;
780 int revents;
781
782 sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
783 if (sc == NULL)
784 return POLLHUP;
785
786 mutex_enter(&sc->sc_lock);
787 if (sc->sc_dying) {
788 mutex_exit(&sc->sc_lock);
789 return POLLHUP;
790 }
791 tp = sc->sc_tty;
792
793 sc->sc_refcnt++;
794 mutex_exit(&sc->sc_lock);
795 revents = ((*tp->t_linesw->l_poll)(tp, events, l));
796 mutex_enter(&sc->sc_lock);
797 if (--sc->sc_refcnt < 0)
798 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
799 mutex_exit(&sc->sc_lock);
800
801 return revents;
802 }
803
804 struct tty *
805 ucomtty(dev_t dev)
806 {
807 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
808
809 return sc != NULL ? sc->sc_tty : NULL;
810 }
811
812 int
813 ucomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
814 {
815 struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
816 int error;
817
818 if (sc == NULL)
819 return EIO;
820
821 mutex_enter(&sc->sc_lock);
822 if (sc->sc_dying) {
823 mutex_exit(&sc->sc_lock);
824 return EIO;
825 }
826
827 sc->sc_refcnt++;
828 error = ucom_do_ioctl(sc, cmd, data, flag, l);
829 if (--sc->sc_refcnt < 0)
830 usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
831 mutex_exit(&sc->sc_lock);
832 return error;
833 }
834
835 static int
836 ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, void *data,
837 int flag, struct lwp *l)
838 {
839 struct tty *tp = sc->sc_tty;
840 int error;
841
842 UCOMHIST_FUNC(); UCOMHIST_CALLED();
843
844 DPRINTF("cmd=0x%08lx", cmd, 0, 0, 0);
845
846 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
847 if (error != EPASSTHROUGH)
848 return error;
849
850 error = ttioctl(tp, cmd, data, flag, l);
851 if (error != EPASSTHROUGH)
852 return error;
853
854 if (sc->sc_methods->ucom_ioctl != NULL) {
855 error = sc->sc_methods->ucom_ioctl(sc->sc_parent,
856 sc->sc_portno, cmd, data, flag, l->l_proc);
857 if (error != EPASSTHROUGH)
858 return error;
859 }
860
861 error = 0;
862
863 DPRINTF("our cmd=0x%08lx", cmd, 0, 0, 0);
864 //mutex_enter(&tty_lock);
865
866 switch (cmd) {
867 case TIOCSBRK:
868 ucom_break(sc, 1);
869 break;
870
871 case TIOCCBRK:
872 ucom_break(sc, 0);
873 break;
874
875 case TIOCSDTR:
876 ucom_dtr(sc, 1);
877 break;
878
879 case TIOCCDTR:
880 ucom_dtr(sc, 0);
881 break;
882
883 case TIOCGFLAGS:
884 *(int *)data = sc->sc_swflags;
885 break;
886
887 case TIOCSFLAGS:
888 error = kauth_authorize_device_tty(l->l_cred,
889 KAUTH_DEVICE_TTY_PRIVSET, tp);
890 if (error)
891 break;
892 sc->sc_swflags = *(int *)data;
893 break;
894
895 case TIOCMSET:
896 case TIOCMBIS:
897 case TIOCMBIC:
898 tiocm_to_ucom(sc, cmd, *(int *)data);
899 break;
900
901 case TIOCMGET:
902 *(int *)data = ucom_to_tiocm(sc);
903 break;
904
905 case PPS_IOC_CREATE:
906 case PPS_IOC_DESTROY:
907 case PPS_IOC_GETPARAMS:
908 case PPS_IOC_SETPARAMS:
909 case PPS_IOC_GETCAP:
910 case PPS_IOC_FETCH:
911 #ifdef PPS_SYNC
912 case PPS_IOC_KCBIND:
913 #endif
914 mutex_spin_enter(&timecounter_lock);
915 error = pps_ioctl(cmd, data, &sc->sc_pps_state);
916 mutex_spin_exit(&timecounter_lock);
917 break;
918
919 default:
920 error = EPASSTHROUGH;
921 break;
922 }
923
924 //mutex_exit(&tty_lock);
925
926 return error;
927 }
928
929 static void
930 tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits)
931 {
932 u_char combits;
933
934 combits = 0;
935 if (ISSET(ttybits, TIOCM_DTR))
936 SET(combits, UMCR_DTR);
937 if (ISSET(ttybits, TIOCM_RTS))
938 SET(combits, UMCR_RTS);
939
940 switch (how) {
941 case TIOCMBIC:
942 CLR(sc->sc_mcr, combits);
943 break;
944
945 case TIOCMBIS:
946 SET(sc->sc_mcr, combits);
947 break;
948
949 case TIOCMSET:
950 CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS);
951 SET(sc->sc_mcr, combits);
952 break;
953 }
954
955 if (how == TIOCMSET || ISSET(combits, UMCR_DTR))
956 ucom_dtr(sc, (sc->sc_mcr & UMCR_DTR) != 0);
957 if (how == TIOCMSET || ISSET(combits, UMCR_RTS))
958 ucom_rts(sc, (sc->sc_mcr & UMCR_RTS) != 0);
959 }
960
961 static int
962 ucom_to_tiocm(struct ucom_softc *sc)
963 {
964 u_char combits;
965 int ttybits = 0;
966
967 combits = sc->sc_mcr;
968 if (ISSET(combits, UMCR_DTR))
969 SET(ttybits, TIOCM_DTR);
970 if (ISSET(combits, UMCR_RTS))
971 SET(ttybits, TIOCM_RTS);
972
973 combits = sc->sc_msr;
974 if (ISSET(combits, UMSR_DCD))
975 SET(ttybits, TIOCM_CD);
976 if (ISSET(combits, UMSR_CTS))
977 SET(ttybits, TIOCM_CTS);
978 if (ISSET(combits, UMSR_DSR))
979 SET(ttybits, TIOCM_DSR);
980 if (ISSET(combits, UMSR_RI | UMSR_TERI))
981 SET(ttybits, TIOCM_RI);
982
983 #if 0
984 XXX;
985 if (sc->sc_ier != 0)
986 SET(ttybits, TIOCM_LE);
987 #endif
988
989 return ttybits;
990 }
991
992 static void
993 ucom_break(struct ucom_softc *sc, int onoff)
994 {
995 UCOMHIST_FUNC(); UCOMHIST_CALLED();
996
997 DPRINTF("onoff=%d", onoff, 0, 0, 0);
998
999 if (sc->sc_methods->ucom_set != NULL)
1000 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1001 UCOM_SET_BREAK, onoff);
1002 }
1003
1004 static void
1005 ucom_dtr(struct ucom_softc *sc, int onoff)
1006 {
1007 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1008
1009 DPRINTF("onoff=%d", onoff, 0, 0, 0);
1010
1011 if (sc->sc_methods->ucom_set != NULL)
1012 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1013 UCOM_SET_DTR, onoff);
1014 }
1015
1016 static void
1017 ucom_rts(struct ucom_softc *sc, int onoff)
1018 {
1019 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1020
1021 DPRINTF("onoff=%d", onoff, 0, 0, 0);
1022
1023 if (sc->sc_methods->ucom_set != NULL)
1024 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1025 UCOM_SET_RTS, onoff);
1026 }
1027
1028 void
1029 ucom_status_change(struct ucom_softc *sc)
1030 {
1031 struct tty *tp = sc->sc_tty;
1032 u_char old_msr;
1033
1034 if (sc->sc_methods->ucom_get_status != NULL) {
1035 old_msr = sc->sc_msr;
1036 sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno,
1037 &sc->sc_lsr, &sc->sc_msr);
1038 if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) {
1039 mutex_spin_enter(&timecounter_lock);
1040 pps_capture(&sc->sc_pps_state);
1041 pps_event(&sc->sc_pps_state,
1042 (sc->sc_msr & UMSR_DCD) ?
1043 PPS_CAPTUREASSERT :
1044 PPS_CAPTURECLEAR);
1045 mutex_spin_exit(&timecounter_lock);
1046
1047 (*tp->t_linesw->l_modem)(tp,
1048 ISSET(sc->sc_msr, UMSR_DCD));
1049 }
1050 } else {
1051 sc->sc_lsr = 0;
1052 /* Assume DCD is present, if we have no chance to check it. */
1053 sc->sc_msr = UMSR_DCD;
1054 }
1055 }
1056
1057 static int
1058 ucomparam(struct tty *tp, struct termios *t)
1059 {
1060 struct ucom_softc *sc = device_lookup_private(&ucom_cd,
1061 UCOMUNIT(tp->t_dev));
1062 int error;
1063
1064 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1065
1066 if (sc == NULL || sc->sc_dying)
1067 return EIO;
1068
1069 /* Check requested parameters. */
1070 if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
1071 return EINVAL;
1072
1073 /*
1074 * For the console, always force CLOCAL and !HUPCL, so that the port
1075 * is always active.
1076 */
1077 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) {
1078 SET(t->c_cflag, CLOCAL);
1079 CLR(t->c_cflag, HUPCL);
1080 }
1081
1082 /*
1083 * If there were no changes, don't do anything. This avoids dropping
1084 * input and improves performance when all we did was frob things like
1085 * VMIN and VTIME.
1086 */
1087 if (tp->t_ospeed == t->c_ospeed &&
1088 tp->t_cflag == t->c_cflag)
1089 return 0;
1090
1091 /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */
1092
1093 /* And copy to tty. */
1094 tp->t_ispeed = 0;
1095 tp->t_ospeed = t->c_ospeed;
1096 tp->t_cflag = t->c_cflag;
1097
1098 if (sc->sc_methods->ucom_param != NULL) {
1099 error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno,
1100 t);
1101 if (error)
1102 return error;
1103 }
1104
1105 /* XXX worry about CHWFLOW */
1106
1107 /*
1108 * Update the tty layer's idea of the carrier bit, in case we changed
1109 * CLOCAL or MDMBUF. We don't hang up here; we only do that by
1110 * explicit request.
1111 */
1112 DPRINTF("l_modem", 0, 0, 0, 0);
1113 (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD));
1114
1115 #if 0
1116 XXX what if the hardware is not open
1117 if (!ISSET(t->c_cflag, CHWFLOW)) {
1118 if (sc->sc_tx_stopped) {
1119 sc->sc_tx_stopped = 0;
1120 ucomstart(tp);
1121 }
1122 }
1123 #endif
1124
1125 return 0;
1126 }
1127
1128 static int
1129 ucomhwiflow(struct tty *tp, int block)
1130 {
1131 struct ucom_softc *sc = device_lookup_private(&ucom_cd,
1132 UCOMUNIT(tp->t_dev));
1133 int old;
1134
1135 if (sc == NULL)
1136 return 0;
1137
1138 mutex_enter(&sc->sc_lock);
1139 old = sc->sc_rx_stopped;
1140 sc->sc_rx_stopped = (u_char)block;
1141
1142 if (old && !block) {
1143 sc->sc_rx_unblock = 1;
1144 softint_schedule(sc->sc_si);
1145 }
1146 mutex_exit(&sc->sc_lock);
1147
1148 return 1;
1149 }
1150
1151 static void
1152 ucomstart(struct tty *tp)
1153 {
1154 struct ucom_softc *sc = device_lookup_private(&ucom_cd,
1155 UCOMUNIT(tp->t_dev));
1156 struct ucom_buffer *ub;
1157 u_char *data;
1158 int cnt;
1159
1160 if (sc == NULL)
1161 return;
1162
1163 KASSERT(&sc->sc_lock);
1164 KASSERT(mutex_owned(&tty_lock));
1165 if (sc->sc_dying) {
1166 return;
1167 }
1168
1169 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
1170 goto out;
1171 if (sc->sc_tx_stopped)
1172 goto out;
1173
1174 if (!ttypull(tp))
1175 goto out;
1176
1177 /* Grab the first contiguous region of buffer space. */
1178 data = tp->t_outq.c_cf;
1179 cnt = ndqb(&tp->t_outq, 0);
1180
1181 if (cnt == 0)
1182 goto out;
1183
1184 ub = SIMPLEQ_FIRST(&sc->sc_obuff_free);
1185 if (ub == NULL) {
1186 SET(tp->t_state, TS_BUSY);
1187 goto out;
1188 }
1189
1190 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_free, ub_link);
1191
1192 if (SIMPLEQ_FIRST(&sc->sc_obuff_free) == NULL)
1193 SET(tp->t_state, TS_BUSY);
1194
1195 if (cnt > sc->sc_obufsize)
1196 cnt = sc->sc_obufsize;
1197
1198 if (sc->sc_methods->ucom_write != NULL)
1199 sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno,
1200 ub->ub_data, data, &cnt);
1201 else
1202 memcpy(ub->ub_data, data, cnt);
1203
1204 ub->ub_len = cnt;
1205 ub->ub_index = 0;
1206
1207 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_full, ub, ub_link);
1208
1209 softint_schedule(sc->sc_si);
1210
1211 out:
1212 return;
1213 }
1214
1215 void
1216 ucomstop(struct tty *tp, int flag)
1217 {
1218 #if 0
1219 struct ucom_softc *sc =
1220 device_lookup_private(&ucom_cd, UCOMUNIT(tp->t_dev));
1221
1222 mutex_enter(&sc->sc_lock);
1223 mutex_spin_enter(&tty_lock);
1224 if (ISSET(tp->t_state, TS_BUSY)) {
1225 /* obuff_full -> obuff_free? */
1226 /* sc->sc_tx_stopped = 1; */
1227 if (!ISSET(tp->t_state, TS_TTSTOP))
1228 SET(tp->t_state, TS_FLUSH);
1229 }
1230 mutex_spin_exit(&tty_lock);
1231 mutex_exit(&sc->sc_lock);
1232 #endif
1233 }
1234
1235 static void
1236 ucom_write_status(struct ucom_softc *sc, struct ucom_buffer *ub,
1237 usbd_status err)
1238 {
1239 struct tty *tp = sc->sc_tty;
1240 uint32_t cc = ub->ub_len;
1241
1242 KASSERT(mutex_owned(&sc->sc_lock));
1243
1244 switch (err) {
1245 case USBD_IN_PROGRESS:
1246 ub->ub_index = ub->ub_len;
1247 break;
1248 case USBD_STALLED:
1249 ub->ub_index = 0;
1250 softint_schedule(sc->sc_si);
1251 break;
1252 case USBD_NORMAL_COMPLETION:
1253 usbd_get_xfer_status(ub->ub_xfer, NULL, NULL, &cc, NULL);
1254 rnd_add_uint32(&sc->sc_rndsource, cc);
1255 /*FALLTHROUGH*/
1256 default:
1257 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_full, ub_link);
1258 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
1259 cc -= sc->sc_opkthdrlen;
1260
1261 mutex_spin_enter(&tty_lock);
1262 CLR(tp->t_state, TS_BUSY);
1263 if (ISSET(tp->t_state, TS_FLUSH))
1264 CLR(tp->t_state, TS_FLUSH);
1265 else
1266 ndflush(&tp->t_outq, cc);
1267 mutex_spin_exit(&tty_lock);
1268
1269 if (err != USBD_CANCELLED && err != USBD_IOERROR &&
1270 !sc->sc_dying) {
1271 if ((ub = SIMPLEQ_FIRST(&sc->sc_obuff_full)) != NULL)
1272 ucom_submit_write(sc, ub);
1273
1274 mutex_spin_enter(&tty_lock);
1275 (*tp->t_linesw->l_start)(tp);
1276 mutex_spin_exit(&tty_lock);
1277 }
1278 break;
1279 }
1280 }
1281
1282 static void
1283 ucom_submit_write(struct ucom_softc *sc, struct ucom_buffer *ub)
1284 {
1285
1286 KASSERT(mutex_owned(&sc->sc_lock));
1287
1288 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, ub->ub_len,
1289 0, USBD_NO_TIMEOUT, ucomwritecb);
1290
1291 ucom_write_status(sc, ub, usbd_transfer(ub->ub_xfer));
1292 }
1293
1294 static void
1295 ucomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status)
1296 {
1297 struct ucom_softc *sc = (struct ucom_softc *)p;
1298
1299 mutex_enter(&sc->sc_lock);
1300 ucom_write_status(sc, SIMPLEQ_FIRST(&sc->sc_obuff_full), status);
1301 mutex_exit(&sc->sc_lock);
1302
1303 }
1304
1305 static void
1306 ucom_softintr(void *arg)
1307 {
1308 struct ucom_softc *sc = arg;
1309 struct tty *tp = sc->sc_tty;
1310 struct ucom_buffer *ub;
1311
1312 mutex_enter(&sc->sc_lock);
1313 mutex_enter(&tty_lock);
1314 if (!ISSET(tp->t_state, TS_ISOPEN)) {
1315 mutex_exit(&tty_lock);
1316 mutex_exit(&sc->sc_lock);
1317 return;
1318 }
1319 mutex_exit(&tty_lock);
1320
1321 ub = SIMPLEQ_FIRST(&sc->sc_obuff_full);
1322
1323 if (ub != NULL && ub->ub_index == 0)
1324 ucom_submit_write(sc, ub);
1325
1326 if (sc->sc_rx_unblock)
1327 ucom_read_complete(sc);
1328
1329 mutex_exit(&sc->sc_lock);
1330 }
1331
1332 static void
1333 ucom_read_complete(struct ucom_softc *sc)
1334 {
1335 int (*rint)(int, struct tty *);
1336 struct ucom_buffer *ub;
1337 struct tty *tp;
1338
1339 KASSERT(mutex_owned(&sc->sc_lock));
1340
1341 tp = sc->sc_tty;
1342 rint = tp->t_linesw->l_rint;
1343 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full);
1344
1345 while (ub != NULL && !sc->sc_rx_stopped) {
1346
1347 /* XXX ttyinput takes tty_lock */
1348 while (ub->ub_index < ub->ub_len && !sc->sc_rx_stopped) {
1349 /* Give characters to tty layer. */
1350 if ((*rint)(ub->ub_data[ub->ub_index], tp) == -1) {
1351 /* Overflow: drop remainder */
1352 ub->ub_index = ub->ub_len;
1353 } else
1354 ub->ub_index++;
1355 }
1356
1357 if (ub->ub_index == ub->ub_len) {
1358 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_full, ub_link);
1359
1360 ucomsubmitread(sc, ub);
1361
1362 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full);
1363 }
1364 }
1365
1366 sc->sc_rx_unblock = (ub != NULL);
1367 }
1368
1369 static usbd_status
1370 ucomsubmitread(struct ucom_softc *sc, struct ucom_buffer *ub)
1371 {
1372 usbd_status err;
1373
1374 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, sc->sc_ibufsize,
1375 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ucomreadcb);
1376
1377 if ((err = usbd_transfer(ub->ub_xfer)) != USBD_IN_PROGRESS) {
1378 /* XXX: Recover from this, please! */
1379 printf("ucomsubmitread: err=%s\n", usbd_errstr(err));
1380 return err;
1381 }
1382
1383 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_empty, ub, ub_link);
1384
1385 return USBD_NORMAL_COMPLETION;
1386 }
1387
1388 static void
1389 ucomreadcb(struct usbd_xfer *xfer, void *p, usbd_status status)
1390 {
1391 struct ucom_softc *sc = (struct ucom_softc *)p;
1392 struct tty *tp = sc->sc_tty;
1393 struct ucom_buffer *ub;
1394 uint32_t cc;
1395 u_char *cp;
1396
1397 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1398
1399 mutex_enter(&sc->sc_lock);
1400 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_empty);
1401 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_empty, ub_link);
1402
1403 if (status == USBD_CANCELLED || status == USBD_IOERROR ||
1404 sc->sc_dying) {
1405 DPRINTF("dying", 0, 0, 0, 0);
1406 ub->ub_index = ub->ub_len = 0;
1407 /* Send something to wake upper layer */
1408 if (status != USBD_CANCELLED) {
1409 (tp->t_linesw->l_rint)('\n', tp);
1410 mutex_spin_enter(&tty_lock); /* XXX */
1411 ttwakeup(tp);
1412 mutex_spin_exit(&tty_lock); /* XXX */
1413 }
1414 mutex_exit(&sc->sc_lock);
1415 return;
1416 }
1417
1418 if (status == USBD_STALLED) {
1419 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
1420 ucomsubmitread(sc, ub);
1421 mutex_exit(&sc->sc_lock);
1422 return;
1423 }
1424
1425 if (status != USBD_NORMAL_COMPLETION) {
1426 printf("ucomreadcb: wonky status=%s\n", usbd_errstr(status));
1427 mutex_exit(&sc->sc_lock);
1428 return;
1429 }
1430
1431 usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL);
1432
1433 #ifdef UCOM_DEBUG
1434 /* This is triggered by uslsa(4) occasionally. */
1435 if ((ucomdebug > 0) && (cc == 0)) {
1436 device_printf(sc->sc_dev, "ucomreadcb: zero length xfer!\n");
1437 }
1438 #endif
1439
1440 KDASSERT(cp == ub->ub_data);
1441
1442 rnd_add_uint32(&sc->sc_rndsource, cc);
1443
1444 if (sc->sc_opening) {
1445 ucomsubmitread(sc, ub);
1446 mutex_exit(&sc->sc_lock);
1447 return;
1448 }
1449
1450 if (sc->sc_methods->ucom_read != NULL) {
1451 sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno,
1452 &cp, &cc);
1453 ub->ub_index = (u_int)(cp - ub->ub_data);
1454 } else
1455 ub->ub_index = 0;
1456
1457 ub->ub_len = cc;
1458
1459 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_full, ub, ub_link);
1460
1461 ucom_read_complete(sc);
1462 mutex_exit(&sc->sc_lock);
1463 }
1464
1465 static void
1466 ucom_cleanup(struct ucom_softc *sc)
1467 {
1468
1469 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1470
1471 DPRINTF("aborting pipes", 0, 0, 0, 0);
1472
1473 KASSERT(mutex_owned(&sc->sc_lock));
1474
1475 ucom_shutdown(sc);
1476 if (sc->sc_bulkin_pipe != NULL) {
1477 struct usbd_pipe *bulkin_pipe = sc->sc_bulkin_pipe;
1478 sc->sc_bulkin_pipe = NULL;
1479 mutex_exit(&sc->sc_lock);
1480 usbd_abort_pipe(bulkin_pipe);
1481 mutex_enter(&sc->sc_lock);
1482 }
1483 if (sc->sc_bulkout_pipe != NULL) {
1484 struct usbd_pipe *bulkout_pipe = sc->sc_bulkout_pipe;
1485 sc->sc_bulkout_pipe = NULL;
1486 mutex_exit(&sc->sc_lock);
1487 usbd_abort_pipe(bulkout_pipe);
1488 mutex_enter(&sc->sc_lock);
1489 }
1490 }
1491
1492 #endif /* NUCOM > 0 */
1493
1494 int
1495 ucomprint(void *aux, const char *pnp)
1496 {
1497 struct ucom_attach_args *ucaa = aux;
1498
1499 if (pnp)
1500 aprint_normal("ucom at %s", pnp);
1501 if (ucaa->ucaa_portno != UCOM_UNK_PORTNO)
1502 aprint_normal(" portno %d", ucaa->ucaa_portno);
1503 return UNCONF;
1504 }
1505
1506 int
1507 ucomsubmatch(device_t parent, cfdata_t cf,
1508 const int *ldesc, void *aux)
1509 {
1510 struct ucom_attach_args *ucaa = aux;
1511
1512 if (ucaa->ucaa_portno != UCOM_UNK_PORTNO &&
1513 cf->cf_loc[UCOMBUSCF_PORTNO] != UCOMBUSCF_PORTNO_DEFAULT &&
1514 cf->cf_loc[UCOMBUSCF_PORTNO] != ucaa->ucaa_portno)
1515 return 0;
1516 return config_match(parent, cf, aux);
1517 }
1518