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