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