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