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