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