ucom.c revision 1.136 1 /* $NetBSD: ucom.c,v 1.136 2023/02/17 23:44:18 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.136 2023/02/17 23:44:18 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 error = cv_timedwait_sig(&sc->sc_statecv, &sc->sc_lock,
556 ticks);
557 mutex_exit(&sc->sc_lock);
558 return error ? error : ERESTART;
559 }
560 }
561
562 /*
563 * Wait while the device is initialized by the
564 * first opener or cleaned up by the last closer.
565 */
566 enum ucom_state state = sc->sc_state;
567 if (state == UCOM_OPENING || sc->sc_closing) {
568 if (flag & FNONBLOCK)
569 error = EWOULDBLOCK;
570 else
571 error = cv_wait_sig(&sc->sc_statecv, &sc->sc_lock);
572 mutex_exit(&sc->sc_lock);
573 return error ? error : ERESTART;
574 }
575 KASSERTMSG(state == UCOM_OPEN || state == UCOM_ATTACHED,
576 "state is %d", state);
577
578 /*
579 * If this is the first open, then make sure the pipes are
580 * running and perform any initialization needed.
581 */
582 bool firstopen = (state == UCOM_ATTACHED);
583 if (firstopen) {
584 KASSERT(!ISSET(tp->t_state, TS_ISOPEN));
585 KASSERT(tp->t_wopen == 0);
586
587 tp->t_dev = dev;
588 sc->sc_state = UCOM_OPENING;
589 mutex_exit(&sc->sc_lock);
590
591 if (sc->sc_methods->ucom_open != NULL) {
592 error = sc->sc_methods->ucom_open(sc->sc_parent,
593 sc->sc_portno);
594 if (error)
595 goto bad;
596 }
597
598 ucom_status_change(sc);
599
600 /* Clear PPS capture state on first open. */
601 mutex_spin_enter(&timecounter_lock);
602 memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state));
603 sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
604 pps_init(&sc->sc_pps_state);
605 mutex_spin_exit(&timecounter_lock);
606
607 /*
608 * Initialize the termios status to the defaults. Add in the
609 * sticky bits from TIOCSFLAGS.
610 */
611 struct termios t;
612
613 t.c_ispeed = 0;
614 t.c_ospeed = TTYDEF_SPEED;
615 t.c_cflag = TTYDEF_CFLAG;
616 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
617 SET(t.c_cflag, CLOCAL);
618 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
619 SET(t.c_cflag, CRTSCTS);
620 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
621 SET(t.c_cflag, MDMBUF);
622 /* Make sure ucomparam() will do something. */
623 tp->t_ospeed = 0;
624 (void) ucomparam(tp, &t);
625 tp->t_iflag = TTYDEF_IFLAG;
626 tp->t_oflag = TTYDEF_OFLAG;
627 tp->t_lflag = TTYDEF_LFLAG;
628 ttychars(tp);
629 ttsetwater(tp);
630
631 /*
632 * Turn on DTR. We must always do this, even if carrier is not
633 * present, because otherwise we'd have to use TIOCSDTR
634 * immediately after setting CLOCAL, which applications do not
635 * expect. We always assert DTR while the device is open
636 * unless explicitly requested to deassert it. Ditto RTS.
637 */
638 ucom_dtr(sc, 1);
639 ucom_rts(sc, 1);
640
641 mutex_enter(&sc->sc_lock);
642 sc->sc_rx_unblock = 0;
643 sc->sc_rx_stopped = 0;
644 sc->sc_tx_stopped = 0;
645
646 for (size_t i = 0; i < UCOM_IN_BUFFS; i++) {
647 struct ucom_buffer *ub = &sc->sc_ibuff[i];
648 error = ucomsubmitread(sc, ub);
649 if (error) {
650 mutex_exit(&sc->sc_lock);
651 goto bad;
652 }
653 }
654 }
655 mutex_exit(&sc->sc_lock);
656
657 DPRINTF("unit=%jd, tp=%#jx dialout %jd nonblock %jd", unit,
658 (uintptr_t)tp, !!UCOMDIALOUT(dev), !!ISSET(flag, O_NONBLOCK));
659 error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
660 if (error)
661 goto bad;
662
663 error = (*tp->t_linesw->l_open)(dev, tp);
664 if (error)
665 goto bad;
666
667 /*
668 * Success! If this was the first open, notify waiters that
669 * the tty is open for business.
670 */
671 if (firstopen) {
672 mutex_enter(&sc->sc_lock);
673 KASSERT(sc->sc_state == UCOM_OPENING);
674 sc->sc_state = UCOM_OPEN;
675 cv_broadcast(&sc->sc_statecv);
676 mutex_exit(&sc->sc_lock);
677 }
678 return 0;
679
680 bad:
681 /*
682 * Failure! If this was the first open, hang up, abort pipes,
683 * and notify waiters that we're not opening after all.
684 */
685 if (firstopen) {
686 ucom_cleanup(sc, flag);
687
688 mutex_enter(&sc->sc_lock);
689 KASSERT(sc->sc_state == UCOM_OPENING);
690 sc->sc_state = UCOM_ATTACHED;
691 cv_broadcast(&sc->sc_statecv);
692 mutex_exit(&sc->sc_lock);
693 }
694 return error;
695 }
696
697 /*
698 * ucomcancel(dev, flag, mode, l)
699 *
700 * Called on revoke or last close. Must interrupt any pending I/O
701 * operations and make them fail promptly; once they have all
702 * finished (except possibly new opens), ucomclose will be called.
703 * We set sc_closing to block new opens until ucomclose runs.
704 */
705 int
706 ucomcancel(dev_t dev, int flag, int mode, struct lwp *l)
707 {
708 const int unit = UCOMUNIT(dev);
709 struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
710
711 UCOMHIST_FUNC(); UCOMHIST_CALLED();
712
713 DPRINTF("unit=%jd", UCOMUNIT(dev), 0, 0, 0);
714
715 /*
716 * This can run at any time before ucomclose on any device
717 * node, even if never attached or if attach failed, so we may
718 * not have a softc or a tty.
719 */
720 if (sc == NULL)
721 return 0;
722 struct tty *tp = sc->sc_tty;
723 if (tp == NULL)
724 return 0;
725
726 /*
727 * Mark the device closing so opens block until we're done
728 * closing. Wake them up so they start over at the top -- if
729 * we're closing because we're detaching, they need to wake up
730 * and notice it's time to fail.
731 */
732 mutex_enter(&sc->sc_lock);
733 sc->sc_closing = true;
734 cv_broadcast(&sc->sc_statecv);
735 mutex_exit(&sc->sc_lock);
736
737 /*
738 * Cancel any pending tty I/O operations, causing them to wake
739 * up and fail promptly, and preventing any new ones from
740 * starting to wait until we have finished closing.
741 */
742 ttycancel(tp);
743
744 return 0;
745 }
746
747 /*
748 * ucomclose(dev, flag, mode, l)
749 *
750 * Called after ucomcancel, when all prior operations on the /dev
751 * node have completed. Only new opens may be in progress at this
752 * point, but they will block until sc_closing is set to false.
753 */
754 int
755 ucomclose(dev_t dev, int flag, int mode, struct lwp *l)
756 {
757 const int unit = UCOMUNIT(dev);
758 struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
759 int error = 0;
760
761 UCOMHIST_FUNC(); UCOMHIST_CALLED();
762
763 DPRINTF("unit=%jd", UCOMUNIT(dev), 0, 0, 0);
764
765 /*
766 * This can run at any time after ucomcancel on any device
767 * node, even if never attached or if attach failed, so we may
768 * not have a softc or a tty.
769 */
770 if (sc == NULL)
771 return 0;
772 struct tty *tp = sc->sc_tty;
773 if (tp == NULL)
774 return 0;
775
776 /*
777 * Close the tty, causing anyone waiting for it to wake, and
778 * hang up the phone.
779 */
780 ucom_cleanup(sc, flag);
781
782 /*
783 * ttyclose should have cleared TS_ISOPEN and interrupted all
784 * pending opens, which should have completed by now.
785 */
786 ttylock(tp);
787 KASSERT(!ISSET(tp->t_state, TS_ISOPEN));
788 KASSERT(tp->t_wopen == 0);
789 ttyunlock(tp);
790
791 /*
792 * Close any device-specific state.
793 */
794 if (sc->sc_methods->ucom_close != NULL) {
795 sc->sc_methods->ucom_close(sc->sc_parent,
796 sc->sc_portno);
797 }
798
799 /*
800 * We're now closed. Can reopen after this point, so resume
801 * transfers, mark us no longer closing, and notify anyone
802 * waiting in open. The state may be OPEN or ATTACHED at this
803 * point -- OPEN if the device was already open when we closed
804 * it, ATTACHED if we interrupted it in the process of opening.
805 */
806 mutex_enter(&sc->sc_lock);
807 KASSERTMSG(sc->sc_state == UCOM_ATTACHED || sc->sc_state == UCOM_OPEN,
808 "%s sc=%p state=%d", device_xname(sc->sc_dev), sc, sc->sc_state);
809 KASSERT(sc->sc_closing);
810 sc->sc_state = UCOM_ATTACHED;
811 sc->sc_closing = false;
812 cv_broadcast(&sc->sc_statecv);
813 mutex_exit(&sc->sc_lock);
814
815 return error;
816 }
817
818 int
819 ucomread(dev_t dev, struct uio *uio, int flag)
820 {
821 const int unit = UCOMUNIT(dev);
822 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
823 struct tty *tp = sc->sc_tty;
824
825 UCOMHIST_FUNC(); UCOMHIST_CALLED();
826
827 return (*tp->t_linesw->l_read)(tp, uio, flag);
828 }
829
830 int
831 ucomwrite(dev_t dev, struct uio *uio, int flag)
832 {
833 const int unit = UCOMUNIT(dev);
834 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
835 struct tty *tp = sc->sc_tty;
836
837 UCOMHIST_FUNC(); UCOMHIST_CALLED();
838
839 return (*tp->t_linesw->l_write)(tp, uio, flag);
840 }
841
842 int
843 ucompoll(dev_t dev, int events, struct lwp *l)
844 {
845 const int unit = UCOMUNIT(dev);
846 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
847 struct tty *tp = sc->sc_tty;
848
849 UCOMHIST_FUNC(); UCOMHIST_CALLED();
850
851 return (*tp->t_linesw->l_poll)(tp, events, l);
852 }
853
854 struct tty *
855 ucomtty(dev_t dev)
856 {
857 const int unit = UCOMUNIT(dev);
858 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
859
860 return sc->sc_tty;
861 }
862
863 int
864 ucomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
865 {
866 const int unit = UCOMUNIT(dev);
867 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
868 struct tty *tp = sc->sc_tty;
869 int error;
870
871 UCOMHIST_FUNC(); UCOMHIST_CALLED();
872
873 DPRINTF("cmd=0x%08jx", cmd, 0, 0, 0);
874
875 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
876 if (error != EPASSTHROUGH)
877 return error;
878
879 error = ttioctl(tp, cmd, data, flag, l);
880 if (error != EPASSTHROUGH)
881 return error;
882
883 if (sc->sc_methods->ucom_ioctl != NULL) {
884 error = sc->sc_methods->ucom_ioctl(sc->sc_parent,
885 sc->sc_portno, cmd, data, flag, l->l_proc);
886 if (error != EPASSTHROUGH)
887 return error;
888 }
889
890 error = 0;
891
892 DPRINTF("our cmd=0x%08jx", cmd, 0, 0, 0);
893
894 switch (cmd) {
895 case TIOCSBRK:
896 ucom_break(sc, 1);
897 break;
898
899 case TIOCCBRK:
900 ucom_break(sc, 0);
901 break;
902
903 case TIOCSDTR:
904 ucom_dtr(sc, 1);
905 break;
906
907 case TIOCCDTR:
908 ucom_dtr(sc, 0);
909 break;
910
911 case TIOCGFLAGS:
912 mutex_enter(&sc->sc_lock);
913 *(int *)data = sc->sc_swflags;
914 mutex_exit(&sc->sc_lock);
915 break;
916
917 case TIOCSFLAGS:
918 error = kauth_authorize_device_tty(l->l_cred,
919 KAUTH_DEVICE_TTY_PRIVSET, tp);
920 if (error)
921 break;
922 mutex_enter(&sc->sc_lock);
923 sc->sc_swflags = *(int *)data;
924 mutex_exit(&sc->sc_lock);
925 break;
926
927 case TIOCMSET:
928 case TIOCMBIS:
929 case TIOCMBIC:
930 tiocm_to_ucom(sc, cmd, *(int *)data);
931 break;
932
933 case TIOCMGET:
934 *(int *)data = ucom_to_tiocm(sc);
935 break;
936
937 case PPS_IOC_CREATE:
938 case PPS_IOC_DESTROY:
939 case PPS_IOC_GETPARAMS:
940 case PPS_IOC_SETPARAMS:
941 case PPS_IOC_GETCAP:
942 case PPS_IOC_FETCH:
943 #ifdef PPS_SYNC
944 case PPS_IOC_KCBIND:
945 #endif
946 mutex_spin_enter(&timecounter_lock);
947 error = pps_ioctl(cmd, data, &sc->sc_pps_state);
948 mutex_spin_exit(&timecounter_lock);
949 break;
950
951 default:
952 error = EPASSTHROUGH;
953 break;
954 }
955
956 return error;
957 }
958
959 static void
960 tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits)
961 {
962 u_char combits;
963
964 combits = 0;
965 if (ISSET(ttybits, TIOCM_DTR))
966 SET(combits, UMCR_DTR);
967 if (ISSET(ttybits, TIOCM_RTS))
968 SET(combits, UMCR_RTS);
969
970 mutex_enter(&sc->sc_lock);
971 switch (how) {
972 case TIOCMBIC:
973 CLR(sc->sc_mcr, combits);
974 break;
975
976 case TIOCMBIS:
977 SET(sc->sc_mcr, combits);
978 break;
979
980 case TIOCMSET:
981 CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS);
982 SET(sc->sc_mcr, combits);
983 break;
984 }
985 u_char mcr = sc->sc_mcr;
986 mutex_exit(&sc->sc_lock);
987
988 if (how == TIOCMSET || ISSET(combits, UMCR_DTR))
989 ucom_dtr(sc, (mcr & UMCR_DTR) != 0);
990 if (how == TIOCMSET || ISSET(combits, UMCR_RTS))
991 ucom_rts(sc, (mcr & UMCR_RTS) != 0);
992 }
993
994 static int
995 ucom_to_tiocm(struct ucom_softc *sc)
996 {
997 u_char combits;
998 int ttybits = 0;
999
1000 mutex_enter(&sc->sc_lock);
1001 combits = sc->sc_mcr;
1002 if (ISSET(combits, UMCR_DTR))
1003 SET(ttybits, TIOCM_DTR);
1004 if (ISSET(combits, UMCR_RTS))
1005 SET(ttybits, TIOCM_RTS);
1006
1007 combits = sc->sc_msr;
1008 if (ISSET(combits, UMSR_DCD))
1009 SET(ttybits, TIOCM_CD);
1010 if (ISSET(combits, UMSR_CTS))
1011 SET(ttybits, TIOCM_CTS);
1012 if (ISSET(combits, UMSR_DSR))
1013 SET(ttybits, TIOCM_DSR);
1014 if (ISSET(combits, UMSR_RI | UMSR_TERI))
1015 SET(ttybits, TIOCM_RI);
1016
1017 #if 0
1018 XXX;
1019 if (sc->sc_ier != 0)
1020 SET(ttybits, TIOCM_LE);
1021 #endif
1022 mutex_exit(&sc->sc_lock);
1023
1024 return ttybits;
1025 }
1026
1027 static void
1028 ucom_break(struct ucom_softc *sc, int onoff)
1029 {
1030 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1031
1032 DPRINTF("onoff=%jd", onoff, 0, 0, 0);
1033
1034 if (sc->sc_methods->ucom_set != NULL)
1035 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1036 UCOM_SET_BREAK, onoff);
1037 }
1038
1039 static void
1040 ucom_dtr(struct ucom_softc *sc, int onoff)
1041 {
1042 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1043
1044 DPRINTF("onoff=%jd", onoff, 0, 0, 0);
1045
1046 if (sc->sc_methods->ucom_set != NULL)
1047 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1048 UCOM_SET_DTR, onoff);
1049 }
1050
1051 static void
1052 ucom_rts(struct ucom_softc *sc, int onoff)
1053 {
1054 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1055
1056 DPRINTF("onoff=%jd", onoff, 0, 0, 0);
1057
1058 if (sc->sc_methods->ucom_set != NULL)
1059 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1060 UCOM_SET_RTS, onoff);
1061 }
1062
1063 void
1064 ucom_status_change(struct ucom_softc *sc)
1065 {
1066 struct tty *tp = sc->sc_tty;
1067
1068 if (sc->sc_methods->ucom_get_status != NULL) {
1069 u_char msr, lsr;
1070
1071 sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno,
1072 &lsr, &msr);
1073 mutex_enter(&sc->sc_lock);
1074 u_char old_msr = sc->sc_msr;
1075
1076 sc->sc_lsr = lsr;
1077 sc->sc_msr = msr;
1078 mutex_exit(&sc->sc_lock);
1079
1080 if (ISSET((msr ^ old_msr), UMSR_DCD)) {
1081 mutex_spin_enter(&timecounter_lock);
1082 pps_capture(&sc->sc_pps_state);
1083 pps_event(&sc->sc_pps_state,
1084 (sc->sc_msr & UMSR_DCD) ?
1085 PPS_CAPTUREASSERT :
1086 PPS_CAPTURECLEAR);
1087 mutex_spin_exit(&timecounter_lock);
1088
1089 (*tp->t_linesw->l_modem)(tp, ISSET(msr, UMSR_DCD));
1090 }
1091 } else {
1092 mutex_enter(&sc->sc_lock);
1093 sc->sc_lsr = 0;
1094 /* Assume DCD is present, if we have no chance to check it. */
1095 sc->sc_msr = UMSR_DCD;
1096 mutex_exit(&sc->sc_lock);
1097 }
1098 }
1099
1100 static int
1101 ucomparam(struct tty *tp, struct termios *t)
1102 {
1103 const int unit = UCOMUNIT(tp->t_dev);
1104 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1105 int error = 0;
1106
1107 /* XXX should take tty lock around touching tp */
1108
1109 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1110
1111 /* Check requested parameters. */
1112 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) {
1113 error = EINVAL;
1114 goto out;
1115 }
1116
1117 /*
1118 * For the console, always force CLOCAL and !HUPCL, so that the port
1119 * is always active.
1120 */
1121 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) {
1122 SET(t->c_cflag, CLOCAL);
1123 CLR(t->c_cflag, HUPCL);
1124 }
1125
1126 /*
1127 * If there were no changes, don't do anything. This avoids dropping
1128 * input and improves performance when all we did was frob things like
1129 * VMIN and VTIME.
1130 */
1131 if (tp->t_ospeed == t->c_ospeed &&
1132 tp->t_cflag == t->c_cflag) {
1133 goto out;
1134 }
1135
1136 /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */
1137
1138 /* And copy to tty. */
1139 tp->t_ispeed = 0;
1140 tp->t_ospeed = t->c_ospeed;
1141 tp->t_cflag = t->c_cflag;
1142
1143 if (sc->sc_methods->ucom_param != NULL) {
1144 error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno,
1145 t);
1146 if (error)
1147 goto out;
1148 }
1149
1150 /* XXX worry about CHWFLOW */
1151
1152 /*
1153 * Update the tty layer's idea of the carrier bit, in case we changed
1154 * CLOCAL or MDMBUF. We don't hang up here; we only do that by
1155 * explicit request.
1156 */
1157 DPRINTF("l_modem", 0, 0, 0, 0);
1158 (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD));
1159
1160 #if 0
1161 XXX what if the hardware is not open
1162 if (!ISSET(t->c_cflag, CHWFLOW)) {
1163 if (sc->sc_tx_stopped) {
1164 sc->sc_tx_stopped = 0;
1165 ucomstart(tp);
1166 }
1167 }
1168 #endif
1169 out:
1170 return error;
1171 }
1172
1173 static int
1174 ucomhwiflow(struct tty *tp, int block)
1175 {
1176 const int unit = UCOMUNIT(tp->t_dev);
1177 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1178 int old;
1179
1180 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1181
1182 KASSERT(&sc->sc_lock);
1183 KASSERT(ttylocked(tp));
1184
1185 old = sc->sc_rx_stopped;
1186 sc->sc_rx_stopped = (u_char)block;
1187
1188 if (old && !block) {
1189 sc->sc_rx_unblock = 1;
1190 kpreempt_disable();
1191 softint_schedule(sc->sc_si);
1192 kpreempt_enable();
1193 }
1194
1195 return 1;
1196 }
1197
1198 static void
1199 ucomstart(struct tty *tp)
1200 {
1201 const int unit = UCOMUNIT(tp->t_dev);
1202 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1203 struct ucom_buffer *ub;
1204 u_char *data;
1205 int cnt;
1206
1207 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1208
1209 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
1210 goto out;
1211 if (sc->sc_tx_stopped)
1212 goto out;
1213
1214 if (!ttypull(tp))
1215 goto out;
1216
1217 /* Grab the first contiguous region of buffer space. */
1218 data = tp->t_outq.c_cf;
1219 cnt = ndqb(&tp->t_outq, 0);
1220
1221 if (cnt == 0)
1222 goto out;
1223
1224 ub = SIMPLEQ_FIRST(&sc->sc_obuff_free);
1225 if (ub == NULL) {
1226 SET(tp->t_state, TS_BUSY);
1227 goto out;
1228 }
1229
1230 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_free, ub_link);
1231
1232 if (SIMPLEQ_FIRST(&sc->sc_obuff_free) == NULL)
1233 SET(tp->t_state, TS_BUSY);
1234
1235 if (cnt > sc->sc_obufsize)
1236 cnt = sc->sc_obufsize;
1237
1238 if (sc->sc_methods->ucom_write != NULL)
1239 sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno,
1240 ub->ub_data, data, &cnt);
1241 else
1242 memcpy(ub->ub_data, data, cnt);
1243
1244 ub->ub_len = cnt;
1245 ub->ub_index = 0;
1246
1247 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_full, ub, ub_link);
1248
1249 kpreempt_disable();
1250 softint_schedule(sc->sc_si);
1251 kpreempt_enable();
1252
1253 out:
1254 DPRINTF("... done", 0, 0, 0, 0);
1255 return;
1256 }
1257
1258 void
1259 ucomstop(struct tty *tp, int flag)
1260 {
1261 #if 0
1262 const int unit = UCOMUNIT(tp->t_dev);
1263 struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1264
1265 mutex_enter(&sc->sc_lock);
1266 ttylock(tp);
1267 if (ISSET(tp->t_state, TS_BUSY)) {
1268 /* obuff_full -> obuff_free? */
1269 /* sc->sc_tx_stopped = 1; */
1270 if (!ISSET(tp->t_state, TS_TTSTOP))
1271 SET(tp->t_state, TS_FLUSH);
1272 }
1273 ttyunlock(tp);
1274 mutex_exit(&sc->sc_lock);
1275 #endif
1276 }
1277
1278 static void
1279 ucom_write_status(struct ucom_softc *sc, struct ucom_buffer *ub,
1280 usbd_status err)
1281 {
1282 struct tty *tp = sc->sc_tty;
1283 uint32_t cc = ub->ub_len;
1284
1285 KASSERT(mutex_owned(&sc->sc_lock));
1286
1287 switch (err) {
1288 case USBD_IN_PROGRESS:
1289 ub->ub_index = ub->ub_len;
1290 break;
1291 case USBD_STALLED:
1292 ub->ub_index = 0;
1293 kpreempt_disable();
1294 softint_schedule(sc->sc_si);
1295 kpreempt_enable();
1296 break;
1297 case USBD_NORMAL_COMPLETION:
1298 usbd_get_xfer_status(ub->ub_xfer, NULL, NULL, &cc, NULL);
1299 rnd_add_uint32(&sc->sc_rndsource, cc);
1300 /*FALLTHROUGH*/
1301 default:
1302 SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_full, ub_link);
1303 SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
1304 cc -= sc->sc_opkthdrlen;
1305
1306 ttylock(tp);
1307 CLR(tp->t_state, TS_BUSY);
1308 if (ISSET(tp->t_state, TS_FLUSH))
1309 CLR(tp->t_state, TS_FLUSH);
1310 else
1311 ndflush(&tp->t_outq, cc);
1312 ttyunlock(tp);
1313
1314 if (err != USBD_CANCELLED && err != USBD_IOERROR &&
1315 !sc->sc_closing) {
1316 if ((ub = SIMPLEQ_FIRST(&sc->sc_obuff_full)) != NULL)
1317 ucom_submit_write(sc, ub);
1318
1319 ttylock(tp);
1320 (*tp->t_linesw->l_start)(tp);
1321 ttyunlock(tp);
1322 }
1323 break;
1324 }
1325 }
1326
1327 static void
1328 ucom_submit_write(struct ucom_softc *sc, struct ucom_buffer *ub)
1329 {
1330
1331 KASSERT(mutex_owned(&sc->sc_lock));
1332
1333 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, ub->ub_len,
1334 0, USBD_NO_TIMEOUT, ucomwritecb);
1335
1336 ucom_write_status(sc, ub, usbd_transfer(ub->ub_xfer));
1337 }
1338
1339 static void
1340 ucomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status)
1341 {
1342 struct ucom_softc *sc = (struct ucom_softc *)p;
1343
1344 mutex_enter(&sc->sc_lock);
1345 ucom_write_status(sc, SIMPLEQ_FIRST(&sc->sc_obuff_full), status);
1346 mutex_exit(&sc->sc_lock);
1347
1348 }
1349
1350 static void
1351 ucom_softintr(void *arg)
1352 {
1353 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1354
1355 struct ucom_softc *sc = arg;
1356 struct tty *tp = sc->sc_tty;
1357
1358 mutex_enter(&sc->sc_lock);
1359 ttylock(tp);
1360 if (!ISSET(tp->t_state, TS_ISOPEN)) {
1361 ttyunlock(tp);
1362 mutex_exit(&sc->sc_lock);
1363 return;
1364 }
1365 ttyunlock(tp);
1366
1367 struct ucom_buffer *ub = SIMPLEQ_FIRST(&sc->sc_obuff_full);
1368
1369 if (ub != NULL && ub->ub_index == 0)
1370 ucom_submit_write(sc, ub);
1371
1372 if (sc->sc_rx_unblock)
1373 ucom_read_complete(sc);
1374
1375 mutex_exit(&sc->sc_lock);
1376 }
1377
1378 static void
1379 ucom_read_complete(struct ucom_softc *sc)
1380 {
1381 int (*rint)(int, struct tty *);
1382 struct ucom_buffer *ub;
1383 struct tty *tp;
1384
1385 KASSERT(mutex_owned(&sc->sc_lock));
1386
1387 tp = sc->sc_tty;
1388 rint = tp->t_linesw->l_rint;
1389 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full);
1390
1391 while (ub != NULL && !sc->sc_rx_stopped) {
1392
1393 /* XXX ttyinput takes ttylock */
1394 while (ub->ub_index < ub->ub_len && !sc->sc_rx_stopped) {
1395 /* Give characters to tty layer. */
1396 if ((*rint)(ub->ub_data[ub->ub_index], tp) == -1) {
1397 /* Overflow: drop remainder */
1398 ub->ub_index = ub->ub_len;
1399 } else
1400 ub->ub_index++;
1401 }
1402
1403 if (ub->ub_index == ub->ub_len) {
1404 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_full, ub_link);
1405 ucomsubmitread(sc, ub);
1406 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full);
1407 }
1408 }
1409
1410 sc->sc_rx_unblock = (ub != NULL);
1411 }
1412
1413 static int
1414 ucomsubmitread(struct ucom_softc *sc, struct ucom_buffer *ub)
1415 {
1416 usbd_status err;
1417
1418 KASSERT(mutex_owned(&sc->sc_lock));
1419
1420 usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, sc->sc_ibufsize,
1421 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ucomreadcb);
1422
1423 if ((err = usbd_transfer(ub->ub_xfer)) != USBD_IN_PROGRESS) {
1424 /* XXX: Recover from this, please! */
1425 printf("%s: err=%s\n", __func__, usbd_errstr(err));
1426 return EIO;
1427 }
1428
1429 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_empty, ub, ub_link);
1430
1431 return 0;
1432 }
1433
1434 static void
1435 ucomreadcb(struct usbd_xfer *xfer, void *p, usbd_status status)
1436 {
1437 struct ucom_softc *sc = (struct ucom_softc *)p;
1438 struct ucom_buffer *ub;
1439 uint32_t cc;
1440 u_char *cp;
1441
1442 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1443
1444 mutex_enter(&sc->sc_lock);
1445
1446 if (status == USBD_CANCELLED || status == USBD_IOERROR ||
1447 sc->sc_closing) {
1448 DPRINTF("... done (status %jd closing %jd)",
1449 status, sc->sc_closing, 0, 0);
1450 mutex_exit(&sc->sc_lock);
1451 return;
1452 }
1453
1454 ub = SIMPLEQ_FIRST(&sc->sc_ibuff_empty);
1455 SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_empty, ub_link);
1456
1457 if (status != USBD_NORMAL_COMPLETION) {
1458 if (status == USBD_STALLED) {
1459 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
1460 } else {
1461 printf("ucomreadcb: wonky status=%s\n",
1462 usbd_errstr(status));
1463 }
1464
1465 DPRINTF("... done (status %jd)", status, 0, 0, 0);
1466 /* re-adds ub to sc_ibuff_empty */
1467 ucomsubmitread(sc, ub);
1468 mutex_exit(&sc->sc_lock);
1469 return;
1470 }
1471
1472 usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL);
1473
1474 #ifdef UCOM_DEBUG
1475 /* This is triggered by uslsa(4) occasionally. */
1476 if ((ucomdebug > 0) && (cc == 0)) {
1477 device_printf(sc->sc_dev, "ucomreadcb: zero length xfer!\n");
1478 }
1479 #endif
1480 KDASSERT(cp == ub->ub_data);
1481
1482 rnd_add_uint32(&sc->sc_rndsource, cc);
1483
1484 if (sc->sc_state != UCOM_OPEN) {
1485 /* Go around again - we're not quite ready */
1486 /* re-adds ub to sc_ibuff_empty */
1487 ucomsubmitread(sc, ub);
1488 mutex_exit(&sc->sc_lock);
1489 DPRINTF("... done (not open)", 0, 0, 0, 0);
1490 return;
1491 }
1492
1493 mutex_exit(&sc->sc_lock);
1494 if (sc->sc_methods->ucom_read != NULL) {
1495 sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno,
1496 &cp, &cc);
1497 ub->ub_index = (u_int)(cp - ub->ub_data);
1498 } else
1499 ub->ub_index = 0;
1500
1501 ub->ub_len = cc;
1502
1503 mutex_enter(&sc->sc_lock);
1504 SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_full, ub, ub_link);
1505 ucom_read_complete(sc);
1506 mutex_exit(&sc->sc_lock);
1507
1508 DPRINTF("... done", 0, 0, 0, 0);
1509 }
1510
1511 static void
1512 ucom_cleanup(struct ucom_softc *sc, int flag)
1513 {
1514 struct tty *tp = sc->sc_tty;
1515
1516 UCOMHIST_FUNC(); UCOMHIST_CALLED();
1517
1518 DPRINTF("closing pipes", 0, 0, 0, 0);
1519
1520 /*
1521 * Close the tty and interrupt any pending opens waiting for
1522 * carrier so they restart or give up. This may flush data.
1523 */
1524 (*tp->t_linesw->l_close)(tp, flag);
1525 ttyclose(tp);
1526
1527 /*
1528 * Interrupt any pending xfers and cause them to fail promptly.
1529 * New xfers will only be submitted under the lock after
1530 * sc_closing is cleared.
1531 */
1532 usbd_abort_pipe(sc->sc_bulkin_pipe);
1533 usbd_abort_pipe(sc->sc_bulkout_pipe);
1534
1535 /*
1536 * Hang up the phone and start the timer before we can make a
1537 * call again, if necessary.
1538 */
1539 ucom_shutdown(sc);
1540 }
1541
1542 #endif /* NUCOM > 0 */
1543
1544 int
1545 ucomprint(void *aux, const char *pnp)
1546 {
1547 struct ucom_attach_args *ucaa = aux;
1548
1549 if (pnp)
1550 aprint_normal("ucom at %s", pnp);
1551 if (ucaa->ucaa_portno != UCOM_UNK_PORTNO)
1552 aprint_normal(" portno %d", ucaa->ucaa_portno);
1553 return UNCONF;
1554 }
1555
1556 int
1557 ucomsubmatch(device_t parent, cfdata_t cf,
1558 const int *ldesc, void *aux)
1559 {
1560 struct ucom_attach_args *ucaa = aux;
1561
1562 if (ucaa->ucaa_portno != UCOM_UNK_PORTNO &&
1563 cf->cf_loc[UCOMBUSCF_PORTNO] != UCOMBUSCF_PORTNO_DEFAULT &&
1564 cf->cf_loc[UCOMBUSCF_PORTNO] != ucaa->ucaa_portno)
1565 return 0;
1566 return config_match(parent, cf, aux);
1567 }
1568